聲明
本文章中所有內(nèi)容僅供學(xué)習(xí)交流饿幅,抓包內(nèi)容、敏感網(wǎng)址戒职、數(shù)據(jù)接口均已做脫敏處理栗恩,嚴(yán)禁用于商業(yè)用途和非法用途,否則由此產(chǎn)生的一切后果均與作者無(wú)關(guān)洪燥,若有侵權(quán)磕秤,請(qǐng)聯(lián)系我立即刪除!
逆向目標(biāo)
- 目標(biāo):網(wǎng)洛者反反爬蟲(chóng)練習(xí)平臺(tái)第三題:AAEncode 加密
- 鏈接:http://spider.wangluozhe.com/challenge/3
- 簡(jiǎn)介:本題仍然是要求采集100頁(yè)的全部數(shù)字捧韵,并計(jì)算所有數(shù)據(jù)加和市咆,需要摳出源碼進(jìn)行計(jì)算,主要使用了 AAEncode 加密
AAEncode 簡(jiǎn)介
AAEncode 和 JJEncode 都是同一個(gè)作者:日本的 Yosuke HASEGAWA 再来,AAEncode 可以將任何 JavaScript 代碼編碼為日式表情符號(hào)蒙兰,在線體驗(yàn)地址:https://utf-8.jp/public/aaencode.html 。
正常的一段 JS 代碼:
alert("Hello, JavaScript" )
經(jīng)過(guò) AAEncode 混淆之后的代碼:
?ω??= /`m′)? ~┻━┻ //*′?`*/ ['_']; o=(???) =_=3; c=(?Θ?) =(???)-(???); (?Д?) =(?Θ?)= (o^_^o)/ (o^_^o);(?Д?)={?Θ?: '_' ,?ω?? : ((?ω??==3) +'_') [?Θ?] ,???? :(?ω??+ '_')[o^_^o -(?Θ?)] ,?Д??:((???==3) +'_')[???] }; (?Д?) [?Θ?] =((?ω??==3) +'_') [c^_^o];(?Д?) ['c'] = ((?Д?)+'_') [ (???)+(???)-(?Θ?) ];(?Д?) ['o'] = ((?Д?)+'_') [?Θ?];(?o?)=(?Д?) ['c']+(?Д?) ['o']+(?ω?? +'_')[?Θ?]+ ((?ω??==3) +'_') [???] + ((?Д?) +'_') [(???)+(???)]+ ((???==3) +'_') [?Θ?]+((???==3) +'_') [(???) - (?Θ?)]+(?Д?) ['c']+((?Д?)+'_') [(???)+(???)]+ (?Д?) ['o']+((???==3) +'_') [?Θ?];(?Д?) ['_'] =(o^_^o) [?o?] [?o?];(?ε?)=((???==3) +'_') [?Θ?]+ (?Д?) .?Д??+((?Д?)+'_') [(???) + (???)]+((???==3) +'_') [o^_^o -?Θ?]+((???==3) +'_') [?Θ?]+ (?ω?? +'_') [?Θ?]; (???)+=(?Θ?); (?Д?)[?ε?]='\\'; (?Д?).?Θ??=(?Д?+ ???)[o^_^o -(?Θ?)];(o???o)=(?ω?? +'_')[c^_^o];(?Д?) [?o?]='\"';(?Д?) ['_'] ( (?Д?) ['_'] (?ε?+(?Д?)[?o?]+ (?Д?)[?ε?]+(?Θ?)+ (???)+ (?Θ?)+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ (???)+ (?Д?)[?ε?]+(?Θ?)+ (???)+ ((???) + (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ (???)+ (?Д?)[?ε?]+((???) + (?Θ?))+ (c^_^o)+ (?Д?)[?ε?]+(???)+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ (?Θ?)+ (c^_^o)+ (?Д?)[?ε?]+(?Θ?)+ (???)+ ((???) + (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ (???)+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ (???)+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ ((???) + (o^_^o))+ (?Д?)[?ε?]+((???) + (?Θ?))+ (???)+ (?Д?)[?ε?]+(???)+ (c^_^o)+ (?Д?)[?ε?]+(?Θ?)+ (?Θ?)+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ (???)+ (?Θ?)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (?Д?)[?ε?]+(?Θ?)+ (???)+ (?Θ?)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) - (?Θ?))+ (o^_^o)+ (?Д?)[?ε?]+(?Θ?)+ (???)+ (o^_^o)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+(?Θ?)+ ((???) + (?Θ?))+ (?Θ?)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (?Д?)[?ε?]+(?Θ?)+ ((o^_^o) +(o^_^o))+ (???)+ (?Д?)[?ε?]+(???)+ ((o^_^o) - (?Θ?))+ (?Д?)[?ε?]+((???) + (?Θ?))+ (?Θ?)+ (?Д?)[?o?]) (?Θ?)) ('_');
AAEncode 解混淆的方式和 JJEncode 類似芒篷,很簡(jiǎn)單搜变,以下介紹幾種常見(jiàn)的方法:
- 使用在線工具直接解密,比如:http://www.hiencode.com/aaencode.html 针炉;
- 去掉代碼最后一個(gè)符號(hào)
('_')
后痹雅,放到瀏覽器里面去直接執(zhí)行就可以看到源碼; - 在線調(diào)試糊识,在 AAEncode 代碼第一行下斷點(diǎn),然后一步一步執(zhí)行摔蓝,最終也會(huì)在虛擬機(jī)(VM)里看到源碼赂苗;
逆向參數(shù)
逆向的目標(biāo)主要是翻頁(yè)接口 _signature
參數(shù),調(diào)用的加密方法仍然是 window.get_sign()
贮尉,和前面兩題是一樣的拌滋,本文不再贅述,不清楚的可以去看 K 哥上期的文章猜谚。
繼續(xù)跟進(jìn)败砂,會(huì)發(fā)現(xiàn)是一個(gè)顏文字的 AAEncode 混淆:
我們將這段代碼復(fù)制出來(lái),去掉末尾的 ('_')
魏铅,直接放到瀏覽器控制臺(tái)運(yùn)行一下(建議單開(kāi)一個(gè)無(wú)痕窗口昌犹,有時(shí)候可能會(huì)有影響),就可以看到源碼了览芳,點(diǎn)擊源碼來(lái)到虛擬機(jī)(VM)斜姥,整個(gè)源碼就展現(xiàn)在我們面前了:
除了直接去掉 ('_')
運(yùn)行以外,我們還可以在混淆代碼第一行下斷點(diǎn),然后單步跟進(jìn)铸敏,最后同樣也會(huì)得到源碼缚忧,如下圖所示:
觀察一下代碼,有一個(gè) Hook window.sign
操作杈笔,還有 delete 操作闪水,然后接著是一個(gè) DES 加密的函數(shù),后面的 try-catch 語(yǔ)句設(shè)置一些 key 之類的參數(shù)蒙具,重點(diǎn)是 try-catch 語(yǔ)句球榆,下斷點(diǎn)看看實(shí)際是走的哪條語(yǔ)句:
其他邏輯我們并不用關(guān)心,直接把 try 語(yǔ)句 copy 出來(lái)店量,不讓它走異常即可芜果,DES 直接調(diào)用 crypto-js 即可,本地改寫(xiě)之后融师,配合 Python 代碼攜帶 _signature 挨個(gè)計(jì)算每一頁(yè)的數(shù)據(jù)右钾,最終提交成功:
完整代碼
GitHub 關(guān)注 K 哥爬蟲(chóng),持續(xù)分享爬蟲(chóng)相關(guān)代碼旱爆!歡迎 star 舀射!https://github.com/kgepachong/
以下只演示部分關(guān)鍵代碼,不能直接運(yùn)行怀伦! 完整代碼倉(cāng)庫(kù)地址:https://github.com/kgepachong/crawler/
JavaScript 加密代碼
/* ==================================
# @Time : 2021-12-13
# @Author : 微信公眾號(hào):K哥爬蟲(chóng)
# @FileName: challenge_3.js
# @Software: PyCharm
# ================================== */
var CryptoJS = require('crypto-js')
function encryptByDES(message, key) {
var keyHex = CryptoJS.enc.Utf8.parse(key);
var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
});
return encrypted.ciphertext.toString();
}
function getSign() {
var message = "http://spider.wangluozhe.com/challenge/3";
message = message + '|' + Date.parse(new Date()).toString();
var key = Date.parse(new Date()).toString();
return encryptByDES(message, key);
}
// 測(cè)試輸出
// console.log(getSign())
Python 計(jì)算關(guān)鍵代碼
# ==================================
# --*-- coding: utf-8 --*--
# @Time : 2021-12-13
# @Author : 微信公眾號(hào):K哥爬蟲(chóng)
# @FileName: challenge_3.py
# @Software: PyCharm
# ==================================
import execjs
import requests
challenge_api = "http://spider.wangluozhe.com/challenge/api/3"
headers = {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Cookie": "將 cookie 值改為你自己的脆烟!",
"Host": "spider.wangluozhe.com",
"Origin": "http://spider.wangluozhe.com",
"Referer": "http://spider.wangluozhe.com/challenge/2",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36",
"X-Requested-With": "XMLHttpRequest"
}
def get_signature():
with open('challenge_3.js', 'r', encoding='utf-8') as f:
ppdai_js = execjs.compile(f.read())
signature = ppdai_js.call("getSign")
print("signature: ", signature)
return signature
def main():
result = 0
for page in range(1, 101):
data = {
"page": page,
"count": 10,
"_signature": get_signature()
}
response = requests.post(url=challenge_api, headers=headers, data=data).json()
for d in response["data"]:
result += d["value"]
print("結(jié)果為: ", result)
if __name__ == '__main__':
main()