1. 程式人生 > >當你寫爬蟲時遇上Flash+加密的解決方式!

當你寫爬蟲時遇上Flash+加密的解決方式!

今天在摸魚(劃掉)逛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/

請問是什麼加密, 求助。

進群:960410445  即可獲取數十套PDF!

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

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

當你寫爬蟲時遇上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檔案的連結,應該就是播放器加載出來的視訊

當你寫爬蟲時遇上Flash+加密的解決方式!

 

私信菜鳥 007 獲取原始碼!

使用Chrome的開發者工具檢視網路請求

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

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 


 

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

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

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

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

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

下載完後啟動它,介面長這樣:

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

JPEXS啟動介面

預設的語言是英語,可以切換成中文,在Settings – Change language裡選擇

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

JPEXS切換成中文

然後我們將這個播放器的.swf檔案給下載下來,並使用JPEXS開啟

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

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

 

 

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

用JPEXS開啟播放器檔案

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

第一種方式:

開啟後找到指令碼組下frame1的DoAction指令碼

 

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

點選後窗口右側會反編譯這個指令碼的內容,並展示出反編譯出來的AS原始碼和P程式碼(類似於組合語言),我們只需要看AS原始碼的部分就行了

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

播放器載入狀態

 

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

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

搜尋反編譯出來的程式碼中的字串

 

找到init函式

第二種:

隨便找一個指令碼開啟,然後按Ctrl+Shift+F開啟全域性搜尋,同樣搜尋“正在載入Flv檔案”

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

 

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

全域性搜尋

 

快速定位出載入視訊部分後,根據init函式這裡的程式碼可以看出,_loc2_就是被傳進播放器的flvurl

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

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

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 = 4
pwd_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_url
def 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)

 

執行一下看看效果

當你寫爬蟲時遇上Flash+加密的解決方式!

 

 

BOOM!