黑帽联盟

 找回密码
 会员注册
查看: 3101|回复: 2
打印 上一主题 下一主题

[安全教程] 某站视频真实地址解析详细过程

[复制链接]

52

主题

2

听众

310

积分

黑帽学员

Rank: 3Rank: 3

  • TA的每日心情
    奋斗
    2019-9-27 16:27
  • 签到天数: 258 天

    [LV.8]以坛为家I

    我是搬运工,觉得好的,支持一下

    前不久看到一篇关于BibiBili视频地址解析的源码,正好有兴趣,就自己也研究了研究,记录一下。

    1.以http://www.bilibili.com/video/av12535537/ 此视频为例HttpWatch抓包,很容易就能看出视频的地址是从https://interface.bilibili.com/playurl?quality=4&player=1&cid=20627240&ts=1504780011&sign=f37df88434579a4b009a2bee708a2a71&qn=112里获取的
    按照常例分析下参数:
    cid很容易猜测出是视频的ID,在网页源码里面也能找到
    21.png

    Qualityqn是视频的清晰度
    ts则是时间戳,这个也不用多说
    关键就是这个sign,在HttpWatch中是完全搜不到任何相关的信息的,但网页访问了http://static.hdslb.com/play.swf这个文件,那么sign算法很可能就在这个播放器里。

    2.下载这个SWF文件后,载入AS3 Sorcerer,代码一大片不是很好找

    22.png

    那就保存到文本里,在文本中查找视频地址这个关键字。

    23.png

    很快就能定位到关键的函数LoadPreviewLoadCidVideo那么接着搜索LoadPreviewLoadCidVideo定位到函数部分,可以看到代码如下
    24.png

    25.png

    那么关键算法就是在getSigngetSign_v2里面了
    1. public function getSign(_arg_1:String):String
    2.     {
    3.         var _local_2:int;
    4.         var _local_4 = null;
    5.         var _local_7:int;
    6.         var _local_8:int;
    7.         var _local_6:int;
    8.         var _local_5:int;
    9.         var _local_3:int = ESP;
    10.         _local_2 = _local_3;
    11.         _local_3 = (_local_3 - 48);
    12.         _local_5 = 16;
    13.         _local_6 = (_local_2 - 37);
    14.         ESP = (_local_3 & -16);
    15.         _local_7 = CModule.mallocString(_arg_1);
    16.         _local_8 = _arg_1.length;
    17.         do
    18.         {
    19.             var _local_9:int = (L__2E_str2 - _local_5);
    20.             _local_9 = li8((_local_9 + 16)) /*FlasCC (Alchemy)*/ ;
    21.             _local_3 = (_local_3 - 16);
    22.             si32(_local_9, (_local_3 + 4)); //FlasCC (Alchemy)
    23.             si32(_local_6, _local_3); //FlasCC (Alchemy)
    24.             ESP = _local_3;
    25.             F_sprintf();
    26.             _local_3 = (_local_3 + 16);
    27.             _local_5 = (_local_5 + -1);
    28.             _local_6 = (_local_6 + 2);
    29.         } while (_local_5 != 0);
    30.         _local_3 = (_local_3 - 16);
    31.         _local_9 = (_local_2 - 4);
    32.         si32(_local_9, (_local_3 + 12)); //FlasCC (Alchemy)
    33.         _local_9 = (_local_2 - 37);
    34.         si32(_local_9, (_local_3 + 8)); //FlasCC (Alchemy)
    35.         si32(_local_8, (_local_3 + 4)); //FlasCC (Alchemy)
    36.         si32(_local_7, _local_3); //FlasCC (Alchemy)
    37.         ESP = _local_3;
    38.         F_get_sign();
    39.         _local_3 = (_local_3 + 16);
    40.         _local_5 = eax;
    41.         _local_9 = li32((_local_2 - 4)) /*FlasCC (Alchemy)*/ ;
    42.         _local_4 = CModule.readString(_local_5, _local_9);
    43.         if (_local_7 != 0)
    44.         {
    45.             _local_3 = (_local_3 - 16);
    46.             si32(_local_7, _local_3); //FlasCC (Alchemy)
    47.             ESP = _local_3;
    48.             F_idalloc();
    49.             _local_3 = (_local_3 + 16);
    50.         };
    51.         if (_local_5 != 0)
    52.         {
    53.             _local_3 = (_local_3 - 16);
    54.             si32(_local_5, _local_3); //FlasCC (Alchemy)
    55.             ESP = _local_3;
    56.             F_idalloc();
    57.             _local_3 = (_local_3 + 16);
    58.         };
    59.         var _local_10 = _local_4;
    60.         _local_3 = _local_2;
    61.         ESP = _local_3;
    62.         return (_local_10);
    63.     }
    64. }//package com.bilibili.interfaces
    复制代码
    1. public function getSign_v2(_arg_1:String, _arg_2:int):String
    2.     {
    3.         var _local_12:*;
    4.         var _local_3:int;
    5.         var _local_5 = null;
    6.         var _local_6:int;
    7.         var _local_11:int;
    8.         var _local_8:int;
    9.         var _local_10:int;
    10.         var _local_9:int;
    11.         var _local_4:int = ESP;
    12.         _local_3 = _local_4;
    13.         _local_4 = (_local_4 - 48);
    14.         _local_6 = _arg_2;
    15.         if (_local_6 >= 5)
    16.         {
    17.             _local_12 = _arg_1;
    18.         }
    19.         else
    20.         {
    21.             _local_8 = (L__2E_str2 + (_local_6 << 4));
    22.             _local_9 = 16;
    23.             _local_10 = (_local_3 - 37);
    24.             ESP = (_local_4 & -16);
    25.             _local_6 = CModule.mallocString(_arg_1);
    26.             _local_11 = _arg_1.length;
    27.             do
    28.             {
    29.                 var _local_7:int = (_local_8 - _local_9);
    30.                 _local_7 = li8((_local_7 + 16)) /*FlasCC (Alchemy)*/ ;
    31.                 _local_4 = (_local_4 - 16);
    32.                 si32(_local_7, (_local_4 + 4)); //FlasCC (Alchemy)
    33.                 si32(_local_10, _local_4); //FlasCC (Alchemy)
    34.                 ESP = _local_4;
    35.                 F_sprintf();
    36.                 _local_4 = (_local_4 + 16);
    37.                 _local_9 = (_local_9 + -1);
    38.                 _local_10 = (_local_10 + 2);
    39.             } while (_local_9 != 0);
    40.             _local_4 = (_local_4 - 16);
    41.             _local_7 = (_local_3 - 4);
    42.             si32(_local_7, (_local_4 + 12)); //FlasCC (Alchemy)
    43.             _local_7 = (_local_3 - 37);
    44.             si32(_local_7, (_local_4 + 8)); //FlasCC (Alchemy)
    45.             si32(_local_11, (_local_4 + 4)); //FlasCC (Alchemy)
    46.             si32(_local_6, _local_4); //FlasCC (Alchemy)
    47.             ESP = _local_4;
    48.             F_get_sign();
    49.             _local_4 = (_local_4 + 16);
    50.             _local_10 = eax;
    51.             _local_7 = li32((_local_3 - 4)) /*FlasCC (Alchemy)*/ ;
    52.             _local_5 = CModule.readString(_local_10, _local_7);
    53.             if (_local_6 != 0)
    54.             {
    55.                 _local_4 = (_local_4 - 16);
    56.                 si32(_local_6, _local_4); //FlasCC (Alchemy)
    57.                 ESP = _local_4;
    58.                 F_idalloc();
    59.                 _local_4 = (_local_4 + 16);
    60.             };
    61.             if (_local_10 != 0)
    62.             {
    63.                 _local_4 = (_local_4 - 16);
    64.                 si32(_local_10, _local_4); //FlasCC (Alchemy)
    65.                 ESP = _local_4;
    66.                 F_idalloc();
    67.                 _local_4 = (_local_4 + 16);
    68.             };
    69.             _local_12 = _local_5;
    70.         };
    71.         _local_4 = _local_3;
    72.         ESP = _local_4;
    73.         return (_local_12);
    74.     }
    75. }//package com.bilibili.interfaces
    复制代码

    可以看到,二者代码非常相似,而且光看代码无法找到有用的信息,那么就得想办法去调试了

    3.目前我只知道的办法是:使用JPEXS反编译软件来修改SWF代码(插Log),然后通过Fiddler劫持替换SWF,通过显示Log信息来进行调试undefined
    要显示log信息就得安装debug版本的flash
    http://www.adobe.com/support/flashplayer/debug_downloads.html
    26.png

    为方便阅读日志信息可以安装Cygwin
    27.png

    具体步骤我也是参考了http://blog.csdn.net/hot_vc/article/details/50600717这篇文章undefined
    ————————————————————————————————————————————————————————————————————————————
    将SWF载入JPEXS
    28.png
    要想修改SWF的源码就得去修改PCODE,第一次接触这种也不是很懂,觉得有点类似于C#的IL代码
    通过AS3代码和PCODE代码的一一进行对比,还是能找到一些规律的
    为了查看代码中变量值,用到以下代码
    1. findpropstrict Qname(PackageNamespace(""),"trace")
    2. getlocal 5
    3. callpropvoid Qname(PackageNamespace(""),"trace") 1
    复制代码

    这个代码就相当于trace(_loc5_);
    修改保存后利用Fiddler来劫持替换我们的SWF
    29.png
    这样Cygwin就能输出我们想要看到的结果了。
    其中有些变量的值是地址,而不是数据,为了读取地址中的数据,利用到了这句代码CModule.readString(地址,读取长度);
    按照原PCODE的格式,写出插LOG时的PCODE
    1. pushint 60
    2. setlocal 8
    3. getlex Qname(PackageNamespace("com.bilibili.interfaces"),"CModule")
    4. getlocal 7
    5. getlocal 8
    6. callproperty Qname(PackageNamespace(""),"readString") 2
    7. coerce_s
    8. setlocal 5
    9. findpropstrict Qname(PackageNamespace(""),"trace")
    10. getlocal 5
    11. callpropvoid Qname(PackageNamespace(""),"trace") 1
    复制代码

    此代码相当于
    _loc8_:int = 60;
    _loc5_:* = CModule.readString(_loc7_,_loc8_);
    trace(_loc5_);
    30.png
    4.其实关键算法在F_get_sign()中,因为从F_get_sign()函数中出来后,eax中就已经存放带着sign的视频URL的地址了。
    F_get_sign()函数过于复杂,总之通过不断地插这两种Log查看变量信息,最终找到了算法


    31.png
    由这个地方可以看出是MD5,还有一个位置能够准确地查看到进行MD5处理的数据(已经忘了.....)
    算法如下:
    1. 五种清晰度
    2. qn=16,quality=1
    3. qn=32,quality=5
    4. qn=48,quality=2
    5. qn=64,quality=2
    6. qn=80,quality=3
    7. qn=112,quality=4

    8. 三种类型的视频bili2,bangumi,movie

    9. bili2:
    10. time = F_clock_gettime();

    11. sign = MD5(“cid=” + cid + “&player=1&qn=112&quality=4&ts=” + time + “1c15888dc316e05a15fdd0a02ed6584f”)

    12. url  =  “https://interface.bilibili.com/playurl?player=1&qn=112&cid=” + cid + “&quality=4&ts=” + time + “&sign=” + sign

    13. bangumi:
    14. time = F_clock_gettime();

    15. sign = MD5(“cid=” + cid + “&module=bangumi” + “&player=1” + “&qn=112” + “&quality=4” + “&ts=” + time + “9b288147e5474dd2aa67085f716c560d”)

    16. url  =  “https://bangumi.bilibili.com/player/web_api/playurl?cid=” + cid + “&player=1” + “&module=bangumi” + “&qn=112” + “&quality=4&ts=” + time + “&sign=” + sign
    复制代码


    也就只分析到了这里、

    顺便说下,有些tx.acgvideo.com开头的视频无法下载是因为服务器检查了Refer,只要在协议头里面加入Refer:https://static.hdslb.com/play.swf,就能下载了


    以上文章转载其它网站的,觉得感觉挺不错的,分享给大家看看
    帖子永久地址: 

    黑帽联盟 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与黑帽联盟享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和黑帽联盟的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、黑帽联盟管理员和版主有权不事先通知发贴者而删除本文

    0

    主题

    0

    听众

    3

    积分

    黑帽菜鸟

    Rank: 1

  • TA的每日心情
    慵懒
    2017-10-11 11:39
  • 签到天数: 1 天

    [LV.1]初来乍到

    表示完全看不懂
    回复

    使用道具 举报

    头像被屏蔽

    0

    主题

    0

    听众

    7

    积分

    黑帽菜鸟

    Rank: 1

  • TA的每日心情

    2019-11-28 08:27
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    提示: 作者被禁止或删除 内容自动屏蔽
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 会员注册

    发布主题 !fastreply! 收藏帖子 返回列表 搜索
    回顶部