0- 前言
爬蟲是一門需要實(shí)戰(zhàn)的學(xué)問。 而對于初學(xué)者來說,要想學(xué)好反爬,js逆向則是敲門磚。今天給大家?guī)硪粋€(gè)js逆向入門實(shí)例,接下來我們一步一步來感受下入門的逆向是什么樣的。該案例選自猿人學(xué)練習(xí)題。猿人學(xué)第一題
1- 拿到需求
進(jìn)入頁面拿到需求我們先不要急著看源碼, 沒事多點(diǎn)點(diǎn)喝杯茶。需求為抓取頁面上所有機(jī)票的平均值。
2- 參數(shù)分析
1- 打開無痕瀏覽器, 免得上班刷題被網(wǎng)管查到記錄。 然后可以放心的多一點(diǎn)看一
前三頁都挺正常的, 看起來就是普普通通的AJAX請求
2- 第四頁第五頁畫風(fēng)突變,不讓看了。一想也是, 防止你手動(dòng)計(jì)算, 只能逆了js才能訪問。 好吧, 我們現(xiàn)在來構(gòu)建一下請求。
3- 復(fù)制請求到postman, 可以正常訪問。
將代碼復(fù)制到python, 亦可以正常訪問。 哇, 感覺還行啊
再運(yùn)行一下, 報(bào)錯(cuò)了, 看下postman, 也報(bào)錯(cuò)了。 看樣子是有時(shí)效性的參數(shù)。 那我們來看看參數(shù)吧。
就是這個(gè)了, 多抓幾次包, 確定page是頁數(shù),還有一個(gè)m是變動(dòng)的。 瞅著后面像是個(gè)時(shí)間戳。前面是一段類似加密參數(shù)。 那我們的目標(biāo)明確了, 就是這個(gè)m。 破解了, 就可以正常獲取到頁面了吧。
3- 逆向過程
1- 首先我們要知道一個(gè)參數(shù)如何加密的,需要先找到加密代碼。 以下提供兩個(gè)方法:
方法一:從Initiator中進(jìn)入
最后一個(gè)請求在此發(fā)出。 我們在此處打上斷點(diǎn), 即為發(fā)送請求時(shí)所有參數(shù)在此以全部加載完。那我們重新請求, 既可以看到參數(shù)的變化,從call stack中尋找, 或者search中搜索關(guān)鍵詞都行。 慢慢找到參數(shù) m 的生成地方
最終我們在request中找到了m的生成地方, 查看m參數(shù)是如何生成的
我們看到參數(shù)m 是有 window[‘\x66’] 這個(gè)值生成。很明顯這個(gè)js文件中并沒有該值的生成邏輯。 那如何找到 window[‘\x66’] 的加載地方呢。 我們繼續(xù)往上一個(gè)堆棧找, 即anonymous。
進(jìn)入后我們發(fā)現(xiàn)這里有一大段未格式化的js代碼。 寫的不規(guī)范,十有八九就是不想讓你看。 如果一個(gè)網(wǎng)站js代碼不想讓別人讀,那它一定有問題, 我們把這段代碼拿出來格式化一下
去掉一些沒有什么卵用的東西, 剩下了兩段js代碼。
一段是我們在上一個(gè)js中看到的oo0O0(mw)函數(shù),
另一段是window的相關(guān)屬性。
咱們都展開看一下,運(yùn)行一下, 發(fā)現(xiàn)報(bào)錯(cuò)。 缺少w函數(shù), 我們?nèi)鄙堆a(bǔ)啥,一個(gè)個(gè)給他找齊
D:\Scriptspace\逆向\學(xué)習(xí)逆向第一步\猿人學(xué)_第一題\第一段js.js:1
w();
^
只用補(bǔ)齊w() 和 D()兩個(gè)函數(shù), 再次運(yùn)行即正常了, 我們拿到參數(shù) mw, 傳入oo0O0(mw) 試試效果
結(jié)果如下, 又去少了window.a, 繼續(xù)補(bǔ), 補(bǔ)到運(yùn)行不報(bào)錯(cuò)為止。
參數(shù)全部補(bǔ)齊后, 又報(bào)了一個(gè)如下錯(cuò)誤。
node:buffer:1349
throw lazyDOMException(‘Invalid character’, ‘InvalidCharacterError’);
^
DOMException [InvalidCharacterError]: Invalid character
at new DOMException (node:internal/per_context/domexception:53:5)
at _node_internal (node:internal/util:520:10)
at atob (node:buffer:1349:13)
at oo0O0 (D:\Scriptspace\逆向\學(xué)習(xí)逆向第一步\猿人學(xué)_第一題\第一段js.js:52:10)
at Object. (D:\Scriptspace\逆向\學(xué)習(xí)逆向第一步\猿人學(xué)_第一題\第一段js.js:57:13)
at Module._compile (node:internal/modules/cjs/loader:1254:14)
at Module._extensions…js (node:internal/modules/cjs/loader:1308:10)
at Module.load (node:internal/modules/cjs/loader:1117:32)
at Module._load (node:internal/modules/cjs/loader:958:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
沒辦法一個(gè)個(gè)去打印查看一下,并隨手chatgpt一下, 經(jīng)過gpt的解析, 代碼應(yīng)該是如下這樣。
其中mw是個(gè)變量, 估計(jì)是傳入的mw的值。目測這就是一個(gè)函數(shù)啊
atob(window['b'])[J('0x0', ']dQW')](J('0x1', 'GTu!'), "mw" )
我們在控制臺將函數(shù)打印一下,并提取出來
格式化一整理, 這就是個(gè)函數(shù)啊, 我們將參數(shù)傳入。一運(yùn)行, 成功了。 多次校驗(yàn), 這個(gè)值就是參數(shù)m的加密值。 還準(zhǔn)備打持久戰(zhàn),怎么稀里糊涂就已經(jīng)拿到值了。
總結(jié)
按照我們原本的思路, 我們的處理邏輯是
1- 我們多次請求, 對頁面進(jìn)行抓包, 分析其參數(shù)。
猜想為: 加密參數(shù)外加cookie中其他參數(shù)
案例中: 只有一個(gè)m參數(shù)為必須參數(shù)
2- 對js進(jìn)行斷點(diǎn)調(diào)試, 找到m參數(shù)生成的地方
猜想為: 一段js加密, 或許會有混淆。
案例中: 加密邏輯為一段未格式化的<script>腳本,格式化后就能正常調(diào)用。
3- 對加密代碼進(jìn)行解析
猜想為: 生成出有一段 oo0O0(mw) 的代碼, 和一段window的參數(shù)代碼。 需要復(fù)現(xiàn)兩段代碼邏輯, 整合后進(jìn)行解密。
案例中: 只處理了 oo0O0(mw) 函數(shù), 并在函數(shù)中找到了eval(atob(window['b'])[J('0x0', ']dQW')](J('0x1', 'GTu!'), '\x27' + mw + '\x27')); 這段數(shù)據(jù), 在找不到window['b']的生成處后,直接打印了atob(window['b'])得到一段js代碼。 解析js代碼, 確認(rèn)直接為加密邏輯
4- 校驗(yàn), 通過讀傳參時(shí)的js確定參數(shù)為時(shí)間戳, 并將時(shí)間戳傳入加密邏輯, 成功獲取參數(shù)m的值。
js逆向需要我們有一定的js功底, 不同的js逆向難易程度都有所不同。 針對于本案例是屬于比較簡單的js逆向。有種還未還是解析就已經(jīng)拿到了加密邏輯的感覺。 適合練手
補(bǔ)充
在前面說到有幾個(gè)斷點(diǎn)調(diào)試的方法,在之前的爬蟲文章中也提到了, 針對這個(gè)案例,補(bǔ)充一下查找斷點(diǎn)的方法
第一個(gè):添加 xhr斷點(diǎn), 因?yàn)楸景咐袨閍jax請求, 獲取到了接口, 可以直接在這里打上斷點(diǎn)
第二個(gè):就是本案例中用到的, 直接callstack中斷點(diǎn)
第三個(gè): 直接搜索參數(shù)中的page, 直接找到加密邏輯。(這個(gè)方法有一定的隨機(jī)性, 謹(jǐn)慎使用)
代碼
加密邏輯大家自己搞定, 我這里只放python代碼了。將加密邏輯摳出來, 運(yùn)行這段python直接獲取結(jié)果。文章來源:http://www.zghlxwxcb.cn/news/detail-627611.html
import execjs, time, urllib.parse
def get_param_m():
timestamp = int(time.time()) * 1000 + (16798545 + -72936737 + 156138192)
M_time = int(timestamp/1000)
mwqqppz = str(timestamp)
with open ('猿人學(xué)第一題.js',encoding='utf-8') as f:
js_data = f.read()
js = execjs.compile(js_data)
js_result = js.call('hex_md5', mwqqppz)
param_m = "{}丨{}".format(js_result, M_time)
return param_m
def get_info(page, param_m):
import requests
url = "https://match.yuanrenxue.cn/api/match/1?page={}&m={}".format(page, param_m)
url = urllib.parse.quote(url, safe=':/?=&')
print(url)
headers = {
'authority': 'match.yuanrenxue.cn',
'accept': 'application/json, text/javascript, */*; q=0.01',
'accept-language': 'zh-CN,zh;q=0.9',
'cache-control': 'no-cache',
'cookie': 'Hm_lvt_c99546cf032aaa5a679230de9a95c7db=1690184377,1690941596,1690969392,1690971468; Hm_lvt_9bcbda9cbf86757998a2339a0437208e=1690184376,1690941595,1690969392,1690971468; Hm_lvt_434c501fe98c1a8ec74b813751d4e3e3=1690971476; Hm_lpvt_434c501fe98c1a8ec74b813751d4e3e3=1690971476; tk=-7962460354862954537; sessionid=1mcld1cz4z54nrnhkuxfq7wtysc7vdds; Hm_lpvt_9bcbda9cbf86757998a2339a0437208e=1691027865; Hm_lpvt_c99546cf032aaa5a679230de9a95c7db=1691027869',
'pragma': 'no-cache',
'referer': 'https://match.yuanrenxue.cn/match/1',
'sec-ch-ua': '"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36',
'x-requested-with': 'XMLHttpRequest'
}
response = requests.request("GET", url, headers=headers).json()
print(response['data'])
sum = 0
for val in response['data']:
sum += val['value']
mean_num = sum/len(response['data'])
return mean_num
if __name__ == '__main__':
sum_num = 0
for page in range(1, 6):
param_m = get_param_m()
print(param_m)
res = get_info(page ,param_m)
print(res)
sum_num += res
result = sum_num/5
print(result)
文章來源地址http://www.zghlxwxcb.cn/news/detail-627611.html
到了這里,關(guān)于web爬蟲第五彈 - JS逆向入門(猿人學(xué)第一題)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!