python爬蟲- js逆向解密之破解AES(CryptoJS)加密的反爬機制v2


前言

其實有關AES,之前發過一版的博客文章,python爬蟲- js逆向解密之破解AES(CryptoJS)加密的反爬機制

而這次雖然也是AES,但是這次的變化有點大了。

 

這次的目標對象同樣也是我的老朋友給我的,還是老規矩,地址我不會給出來的

打開網址,界面如下:

 

 

 

不要問我為什么碼了這么多,主要涉及到了手機號哈,馬賽克必須馬死

 

開始分析

 

首先,看XHR,用結果搜,沒搜到

 

 

那行,接着看網站源碼,用id為phonenum去整站搜索,然后找到以下幾段代碼塊:

 

 

 

 

 

代碼:

第一段:
key: "showEncryptPhone", value: function() { if (0 != $("#phonenum").length) { var e = getStoragePhone(); e ? ($("#phonenum").val(mobileEncrypt(e)), $("#phonenum").attr("disabled", "true")) : $("#changePhoneBtn").hide() } } } ------------ 第二段: $("#app").on("input propertychange", "#phonenum", function(e) { d("#phonenum"); var t = e.target.value; setStoragePhone(t) })

 

首先,可能稍微懂一點點js代碼的,應該都能大概猜到,真正的代碼其實是第一段,為啥呢,你看第二段,propertychange,這明顯是監聽修改的啊,再看第一個showEncryptPhone,這就是顯示加密了的手機號,那一定是第一段代碼了。

 

給第一段的每行代碼

 

 

 

刷新頁面,一步一步走,走到getStoragePhone()時,跳到里這個函數里:

 

 

當我鼠標放到window.msgTargetPhone時,已經有結果了

 

 

 

那么關鍵點就在getStoragePhone這個函數里了,重新打斷點到這個函數上,之前的斷點刪除了,刷新看,結果立馬就有了結果,那么,關鍵點就在window.msgTargetPhone上了,我用msgTargetPhone搜索,得到以下3個結果:

 

 

 

 

 

同樣的,看名字,第三個肯定不是了,這不就是上面的那個被我們排除的函數一個原理嗎?這第三個是監聽是否改變值的,如果改變值就進入,而目標的整個頁面里,手機號時是訪問后就會自動出現的,並不是改變值出現的。而再看第一個,initUserMobileCache,看名字啊,初始化手機號,直覺告訴我就是這里了,先進這個函數看看咋回事

 

我正准備進入initUserMobileCache一頓分析時,我那朋友發來消息問我咋樣了,我說,你可別急啊,我找到關鍵點了。

 

給這個函數打上斷點:

 

 

刷新頁面,一步一步往下走,直接走到下面這個函數,而且,這個e的參數看的太眼熟了,一看就是最開始的XHR請求得到的,這里我馬死,就不展示了,這個s(e)走完之后就,手機號就出現了,那么,這么說,這個s(e)才是真正的關鍵點了

 

 

 

代碼:

function s(e) { var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : g; if (!e) return ""; var n = p(e, t, { iv: f }); return n.toString(CryptoJS.enc.Utf8) }

 

 

找到關鍵點

 

再回到上級看下,就是AESDecrypt這個函數跳轉過去的,看到這個函數名AESDecrypt,那么不用多說了,用的就是AES加密了

 

 

 

 

接着我另開一個標簽頁,然后試試這個s函數能不能直接調用:

 

 結果就報了個g沒有定義,這個g,就煩了,不能搜了,為啥呢,這個太大眾化了,根本不好搜索它在哪,不信你看:

 

 

你不會說這幾百個一個一個看吧,那得整到啥時候去了,此時,應該怎么辦呢,看源碼,但是得有章法的看,看下面這一縱列的函數定義,這些都應該在一個函數作用域里,那就看上下文這個自執行函數【!function(e){】的作用域里有沒有定義過【g】

 

 

 

 

 往下翻沒幾行就看到了下面這個,這里不就是定義了g嗎,不止g,還有p也定義了

 

 摳出核心代碼

 

那么,我們就可以稍微改下s函數的源碼:

 

function s(e) { var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : CryptoJS.enc.Utf8.parse('e5b40d286cxfca34'); if (!e) return ""; var n = CryptoJS.AES.decrypt(e, t, { iv: CryptoJS.enc.Utf8.parse('Con-ere-ceD-cumt') }); return n.toString(CryptoJS.enc.Utf8) }

 

去控制台看下呢,我順便改了下函數名cryp:

 

 

沒引入CrpytoJS,在控制台引入下:

 

var script = document.createElement('script'); script.src = "http://cdn.staticfile.org/crypto-js/3.1.9-1/crypto-js.min.js"; document.getElementsByTagName('head')[0].appendChild(script);

 

 

 

或者你也可以直接把crpyto的源碼賦值下來然后在控制台然后回車

 

 

現在再看,果然成功了

 

 

看來沒毛病了,核心代碼就是這個。

 

另外說下,我一開始是打算去扣cryptojs里的代碼的,后面發現調用層級太多了,所以放棄了,直接引用整個crypto算了

 

 

用python實現

 

用crypto庫實現

 

我之前的文章里,python爬蟲- js逆向解密之破解AES(CryptoJS)加密的反爬機制 ,那套代碼在這里沒法用,所以,只能用下面的代碼:

 

 

from Crypto.Cipher import AES import base64 class AesCrypt(): def __init__(self, key, model, iv): self.model = {'ECB': AES.MODE_ECB, 'CBC': AES.MODE_CBC}[model] self.key = self.add_16(key) self.iv = iv.encode() if model == 'ECB': self.aes = AES.new(self.key, self.model)  # 創建aes對象
        elif model == 'CBC': self.aes = AES.new(self.key, self.model, self.iv)  # 創建aes對象

    def add_16(self, par): # python3字符串是unicode編碼,需要 encode才可以轉換成字節型數據
        par = par.encode('utf-8') while len(par) % 16 != 0: par += b'\x00'
        return par def aesdecrypt(self, text): # CBC解密需要重新創建一個aes對象
        if self.model == AES.MODE_CBC: self.aes = AES.new(self.key, self.model, self.iv) text = base64.decodebytes(text.encode('utf-8')) self.decrypt_text = self.aes.decrypt(text) return self.decrypt_text.decode('utf-8').strip('\0') if __name__ == '__main__': key = 'e5b40d286cxfca34' iv = 'Con-ere-ceD-cumt' word = 'xxxxxxx' model = 'CBC' pr = AesCrypt(key,model,iv) print(pr.aesdecrypt(word))

 

執行,可行,結果能跟剛才控制台的結果對上:

 

 

用node.js實現

 

另外,不是說一定得python才能實現的,你也可以把crypto和這里摳出來的代碼作為字符串,然后用execjs和js2py之類的庫執行js,然后拿到結果,或者你還可以不用把crypto的源碼拿出來,在你電腦上裝上node.js,node里裝上crypto,然后把js的環境設置到你本地的node環境也是可以的。

os.environ["NODE_PATH"] = "D:/xxzxx/node_modules"

 

 

 

 

還沒完,找到剛才那個異步加載獲得加密字段的xhr,發現這個平台的參數提交用的是payload類型:

 

 

沒有鍵值對,也不是json,也不是類json,很強,這種的,我之前的文章里也說過,Python爬蟲處理奇葩的請求參數payload,而這里的又完全不同的一種,不過方法是一樣的,直接以字符串形式提交即可,看到了嗎啊,里面的data的值直接就是一個字符串型即可

 

 

 

好,將兩個對接上即可,完整的代碼我就不給了,相信都走到這里了,各位朋友應該可以處理了。本次破解完畢

 

此時我將代碼和結果甩給我那朋友,他發來三個字:【卧槽,穩】。我這個哥們兒一看到有新奇玩意兒就發給我讓我搞,我其實挺感謝他的,能通過他一直保持學習是挺好的,而他也是技術出生,他做安全開發的,有很多東西我們都會交流,工作內容也有交集

 

結語

 

最近這幾篇都是針對js的處理,也越來越覺得js是爬蟲的大頭,另外最近在某群里,有個老哥說他們公司招爬蟲工程師,然后收到的簡歷上寫的基本都是說會xpath處理,沒有其他更多的技術呈現,那確實啊,很多人真的對爬蟲的理解就是拿到數據,然后用正則或者bs4或者xpath就一頓操作,永遠都寫不完的表達式,不可能寫一輩子的,想想你靠寫xpath之類的,工資能提升嗎?永遠不可能的,還是要多學多用啊,涉及到的都要去了解,才能知道怎么逆向或者說怎么解析數據。就像我說的我這個朋友,他會時不時的給我一些網站讓我去分析,為什么,是因為我之前很喪的時候就跟他說不想做開發了,他沒有多說啥,而是時不時的給我點東西,讓我找到點信心或者說樂趣,我才可以做到現在。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM