Python 爬蟲進(jìn)階必備 | 當(dāng) Js 逆向遇上 wasm(一)
點(diǎn)擊上方“咸魚學(xué)Python”,選擇“加為星標(biāo)”
第一時(shí)間關(guān)注Python技術(shù)干貨!

圖源:極簡(jiǎn)壁紙
前言
Wasm 是一種底層匯編語(yǔ)言,具有文本格式支持,其目標(biāo)是可移植、安全和高效。
Wasm 的模塊可以被導(dǎo)入的到一個(gè)網(wǎng)絡(luò) app(或Node.js)中,并且暴露出供 JavaScript 使用的 Wasm 函數(shù)。
Wasm 與其他虛擬機(jī)的主要區(qū)別在于,它沒有針對(duì)任何特定的編程語(yǔ)言進(jìn)行優(yōu)化,而只是抽象底層硬件,字節(jié)碼直接對(duì)應(yīng)于現(xiàn)代 cpu 的指令和內(nèi)存模型。
簡(jiǎn)單的來說就是它是比較底層的匯編語(yǔ)言,它比較難懂,它比較安全

上面的概念部分只是了解下關(guān)于 wasm 的基本概念,主要還是得看實(shí)操
今日網(wǎng)站
aHR0cHM6Ly9tYXRjaC55dWFucmVueHVlLmNvbS9tYXRjaC8xNQ==
抓包分析與加密定位
訪問網(wǎng)站可以看到要求我們獲取到當(dāng)前頁(yè)面的總數(shù)

所以先開抓包看看頁(yè)面信息的獲取
大致分析一下可以知道訪問首頁(yè)是沒有加密參數(shù)的,但是翻頁(yè)的時(shí)候是需要一個(gè)加密參數(shù)m

所以需要分析的參數(shù)就是這個(gè)m
我們找到 js 的堆棧

在第三個(gè)的位置可以找到這個(gè) js 加密的位置

可以看到這里提交了參數(shù)list,這里的m是window.m調(diào)用后的結(jié)果
通過箭頭2可以找到window.m的邏輯

這里就引出了window.q這個(gè)函數(shù)
打上斷點(diǎn)再點(diǎn)擊翻頁(yè)可以斷在window.q中
我們跟進(jìn)去看看這里window.q的邏輯

通過上一個(gè)的js邏輯我們大概可以猜出來上面這一大段應(yīng)該是來自wasm
文件應(yīng)該是從/static/match/match15/main.wasm加載

我們找到這個(gè)wasm文件
復(fù)現(xiàn)
這里的wasm文件拿到了但是我們要怎么去分析它呢?
這里有兩種方法,看了下網(wǎng)上關(guān)于 wasm 的輪子非常多,可以將 wasm 轉(zhuǎn)換成 c、c++ 等,方法遠(yuǎn)不只兩個(gè)
方法一
第一種是使用wasm2js
#?項(xiàng)目地址
https://github.com/thlorenz/wasm2js
安裝
npm?install?wasm2js
然后可以使用這個(gè)包讀取這個(gè)wasm文件還原成js,然后扣邏輯就可以了
方法二
第二種是使用現(xiàn)成的 python 第三方包pywasm
安裝
pip?install?pywasm
使用 demo
import?pywasm
#?pywasm.on_debug()
runtime?=?pywasm.load('./examples/fib.wasm')
r?=?runtime.exec('fib',?[10])
print(r)?#?55
看了下官方的 demo,好像非常簡(jiǎn)單
那我們也試一下
這里比較難受的是,我們?cè)谧x取wasm之后要調(diào)用那個(gè)方法?
還是要找到wasm的入口才行,所以又回到了解析 wasm 的路子上
還好網(wǎng)上輪子不少,下面這個(gè)網(wǎng)站提供
wat2wasm
wasm2wat
兩種格式的互轉(zhuǎn)
https://webassembly.github.io/wabt/demo/
我們這里需要選擇的是wasm2wat,就是將wasm轉(zhuǎn)化為c語(yǔ)言
解析之后的樣子像下面這樣

這里其實(shí)就可以看到大概的邏輯了,這里文件導(dǎo)出了encode,我們可以在外部調(diào)用這個(gè)方法,傳入t1、t2即可
如果你感覺轉(zhuǎn)化為c語(yǔ)言也不是很好懂的話,可以再用下面的這個(gè)包
https://github.com/WebAssembly/wabt
https://github.com/WebAssembly/wabt/blob/main/docs/decompiler.md
但是編譯一次發(fā)現(xiàn)還不如wasm2js好用
通過在線編譯器我們已經(jīng)知道了這個(gè) wasm 文件的導(dǎo)出方法是encode,所以試著帶入計(jì)算
import?math
import?random
import?time
import?pywasm
t?=?int(time.time())
t1?=?int(t?/?2)
t2?=?int(t?/?2?-?math.floor(random.random()?*?50?+?1))
wasm_vm?=?pywasm.load("demo1.wasm")
m?=?wasm_vm.exec("encode",?[t1,?t2])
print(m)
print(str(m)?+?'|'?+?str(t1)?+?'|'?+?str(t2))

這樣就可以得出m的值了
之后會(huì)再寫兩篇關(guān)于 wasm 的內(nèi)容,wasm 還是很有意思的,主要是輪子很多可以拿來就用,過程全靠躺。
好了,以上就是今天的全部?jī)?nèi)容了。
我是沒有更新就在摸魚的咸魚
收到請(qǐng)回復(fù)~
我們下次再見。
對(duì)了,看完記得一鍵四連,這個(gè)對(duì)我真的很重要。
