解密flash播放器

轉載自公衆號:python_shequ

今天在摸魚(劃掉)逛V2EX的時候,有個帖子引起了我的注意

求助一個網站視頻加密方式, 已排除是 base64 加密 - V2EX

https://www.v2ex.com/t/493201

帖子內容:

視頻鏈接加密之後是這樣的:
lxxt6jIID2Byq541xEB6F3u71bYaE5A/A-1dMFS4o9mx8uzpm81KxH25u1E29:Cl7Wg|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_:hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_/hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_\hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_.hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7__hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_AhQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7bhQW5e|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7ChQW5e|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7dhQW5e
網站鏈接在這: http://www.tvsky.tv/Industry/Show/278/33875/
請問是什麼加密, 求助。

作爲一個助人爲樂的好青年,當然要順手幫樓主看一下啦😳

打開這個網站看看,這是一個用Flash播放器加載並播放視頻的頁面,傳入播放器的參數如帖中所述是有加密的

使用Chrome的開發者工具查看播放器元素

傳入播放器的參數:

flvurl=lxxt6jIID2Byq541xEB6F3u71bYaE5A/A-1dMFS4o9mx8uzpm81KxH25u1E29:Cl7Wg|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_:hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_/hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_\hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_.hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7__hQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_AhQ5Ue|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7bhQW5e|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7ChQW5e|lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7dhQW5e&isautoplay=1&adswf=

抓包發現有一個.flv文件的鏈接,應該就是播放器加載出來的視頻

使用Chrome的開發者工具查看網絡請求

全局搜索這個URL的部分內容是搜不到的,判斷出這個URL應該是在播放器中對傳入的flvurl參數進行解密,然後再加載出視頻


那麼,遇到這種情況的時候我們應該怎麼做才能破解出這個解密URL的過程呢?

首先,我們需要將這個頁面上的Flash播放器給逆向一下,就像在爬HTML5視頻網站碰到加密參數時逆向JavaScript一樣。

但是Flash播放器是一個被編譯後的.swf文件,我們並不能像JavaScript那樣直接看到代碼,需要先進行反編譯。

是時候祭出JPEXS了,在GitHub上可以找到

https://github.com/jindrapetrik/jpexs-decompiler/releases

下載完後啓動它,界面長這樣:

JPEXS啓動界面

默認的語言是英語,可以切換成中文,在Settings – Change language裏選擇

JPEXS切換成中文

然後我們將這個播放器的.swf文件給下載下來,並使用JPEXS打開

播放器文件地址在源頁面的HTML中可以看到

<pre style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; color: rgb(51, 51, 51); font-size: 17px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

http://www.tvsky.tv/FlvPlay/Playerx.swf

</pre>

用JPEXS打開播放器文件

然後我們有兩種方式快速定位到可能存在解密代碼的位置

第一種方式:

打開後找到腳本組下frame1的DoAction腳本

點擊後窗口右側會反編譯這個腳本的內容,並展示出反編譯出來的AS源代碼和P代碼(類似於彙編語言),我們只需要看AS源代碼的部分就行了

播放器加載狀態

根據在網頁中播放器的樣子,在加載時會有一個“正在加載Flv文件”的字樣,直接按Ctrl+F搜索它

搜索反編譯出來的代碼中的字符串

找到init函數

第二種:

隨便找一個腳本打開,然後按Ctrl+Shift+F打開全局搜索,同樣搜索“正在加載Flv文件”

全局搜索

快速定位出加載視頻部分後,根據init函數這裏的代碼可以看出,loc2就是被傳進播放器的flvurl

那麼下面的這部分就是它的解密操作了

init部分:_flvurl = _loc2_.split("|");var _loc1_ = 0;while(_loc1_ < _flvurl.length){   _flvurl[_loc1_] = Pass2Str(_flvurl[_loc1_]);   _loc1_ = _loc1_ + 1;}var PwdStr = "AbCdEfGhIjKlMnOpQrStUvWxYzaBcDeFgHiJkLmNoPqRsTuVwXyZ1234509876-_.\\/:";var PwdStrRan = "12345678987654321";var _PwdLen = 4;var _PwdAddLen = 4;function Pass2Str(Str){   var _loc2_ = "";   var _loc3_ = "";   var _loc4_ = 0;   var _loc1_ = 1;   while(_loc1_ <= Str.length)   {      _loc2_ = Str.substr(_loc1_,1);      if(_loc1_ % (_PwdLen + 1) != 0)      {         _loc3_ = _loc3_ + NumS(_loc2_,_loc4_);      }      else      {         _loc4_ = parseInt(_loc2_);      }      _loc1_ = _loc1_ + 1;   }   return _loc3_;}function NumS(s, _PwdAddLen1){   var _loc1_ = PwdStr.indexOf(s);   _loc1_ = _loc1_ - (_PwdAddLen + _PwdAddLen1 - 1);   if(_loc1_ <= 0)   {      return PwdStr.substr(_loc1_ + PwdStr.length,1);   }   return PwdStr.substr(_loc1_,1);}

然後將反編譯出來的ActionScript代碼的解密URL部分改寫成Python代碼:

# http://www.tvsky.tv/Industry/Show/278/33875/ 的視頻url解密部分# 爲方便對照AS代碼閱讀,這裏只對反編譯出來的AS代碼直接進行“翻譯”,沒有使用Python的一些更簡潔的寫法_pwd_len = 4_pwd_add_len = 4pwd_str = "AbCdEfGhIjKlMnOpQrStUvWxYzaBcDeFgHiJkLmNoPqRsTuVwXyZ1234509876-_.\\/:"def decode(flv_url: str):    """    function init()    {       ......       var _loc2_ = flvurl;       ......          _flvurl = _loc2_.split("|");          var _loc1_ = 0;          while(_loc1_ < _flvurl.length)          {             _flvurl[_loc1_] = Pass2Str(_flvurl[_loc1_]);             _loc1_ = _loc1_ + 1;          }       ......    }    :param flv_url: flash參數裏的flvurl部分的value    :return: 解密後視頻url列表    """    new_flv_url = flv_url.split("|")    _loc1_ = 0    while _loc1_ < len(new_flv_url):        new_flv_url[_loc1_] = pass2str(new_flv_url[_loc1_])        _loc1_ += 1    return new_flv_urldef pass2str(str_: str):    """    function Pass2Str(Str)    {       var _loc2_ = "";       var _loc3_ = "";       var _loc4_ = 0;       var _loc1_ = 1;       while(_loc1_ <= Str.length)       {          _loc2_ = Str.substr(_loc1_,1);          if(_loc1_ % (_PwdLen + 1) != 0)          {             _loc3_ = _loc3_ + NumS(_loc2_,_loc4_);          }          else          {             _loc4_ = parseInt(_loc2_);          }          _loc1_ = _loc1_ + 1;       }       return _loc3_;    }    :param str_: 加密的url字符串    :return: 解密後的url字符串    """    _loc1_ = 1    _loc3_ = ""    _loc4_ = 0    while _loc1_ <= len(str_):        _loc2_ = str_[_loc1_ - 1]        if _loc1_ % (_pwd_len + 1) != 0:            _loc3_ = _loc3_ + num_s(_loc2_, _loc4_)        else:            _loc4_ = int(_loc2_) if _loc2_.isdigit() else 0        _loc1_ = _loc1_ + 1    return _loc3_def num_s(s, _pwd_add_len1):    """    function NumS(s, _PwdAddLen1)    {       var _loc1_ = PwdStr.indexOf(s);       _loc1_ = _loc1_ - (_PwdAddLen + _PwdAddLen1 - 1);       if(_loc1_ <= 0)       {          return PwdStr.substr(_loc1_ + PwdStr.length,1);       }       return PwdStr.substr(_loc1_,1);    }    """    _loc1_ = pwd_str.index(s)    _loc1_ = _loc1_ - (_pwd_add_len + _pwd_add_len1 - 1)    if _loc1_ <= 0:        return pwd_str[_loc1_ + len(pwd_str) - 1]    return pwd_str[_loc1_ - 1]if __name__ == '__main__':    url_list = decode(        "lxxt6jIID2Byq541xEB6F3u71bYaE5A/A-1dMFS4o9mx8uzpm81KxH25u1E29:Cl7Wg|"        "lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_:hQ5Ue|"        "lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_/hQ5Ue|"        "lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_\hQ5Ue|"        "lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_.hQ5Ue|"        "lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7__hQ5Ue|"        "lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7_AhQ5Ue|"        "lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7bhQW5e|"        "lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7ChQW5e|"        "lxxt4hGGB6F3u763zGD9i0X_4EBDh7CAC.6Irkx6q7oz7TYOL2uErB25u1E7dhQW5e"    )    print(url_list)

執行一下看看效果

BOOM!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章