记录一次wasm逆向

最近在找工作捏,好难找boss都是已读不回,八嘎八嘎!这天突然有一个回了然后说先爬一下他们的官网试试看捏,所以就有了这篇文章~,因为这个官网是wasm加密所以就记录一下鸟!在说这个网站之前,我们先从简单的开始吧,先从yrx的第15题开始aHR0cHM6Ly9tYXRjaC55dWFucmVueHVlLmNuL21hdGNoLzE1(自行b64解码)

1.首先打开页面抓包,我们测试几次可以发现,请求的成功与否和这个m有关,我们直接通过追栈的方式找到切入点.
image.png
imagea29563fe13c24820.png
2.我们可以看到m的加密很清晰,一下子我们就可以得到m是由window.m这个方法返回而来.并且有wasm的字样以及WebAssembly.instantiate的关键函数,我们就可以知道这是一个wasm相关的操作了,至于什么是wasm就自己去了解吧,因为不需要什么花里胡哨的操作,所以我们就不从分析wasm文件入手,我们只要能获得我们想要的结果就可以鸟!
imagedea0ad1b04e9decb.png
3.我们直接开始战斗,其实这个网站已经给我们写好了一个最基本的js操作wasm的例子了,并且适用于node环境(node版本最好大于18,因为小于18的WebAssembly可能不完整喔,并且没有fetch!),我们直接将代码拿下

1
2
3
4
5
6
7
8
9
10
fetch('https://match.yuanrenxue.cn/static/match/match15/main.wasm').then(response =>
response.arrayBuffer()
).then(bytes => WebAssembly.instantiate(bytes)).then(results => {
instance = results.instance;
window.q = instance.exports.encode;
t1 = parseInt(Date.parse(new Date()) / 1000 / 2);
t2 = parseInt(Date.parse(new Date()) / 1000 / 2 - Math.floor(Math.random() * (50) + 1));
window.kkk = window.q(t1, t2).toString() + '|' + t1 + '|' + t2;
console.log(window.kkk)
})

这里运行会报没有window,这个自己补一下就好鸟~

我们重点观察WebAssembly.instantiate这个函数,他需要传入一个类型化数组ArrayBuffer,所以这里使用了response.arrayBuffer()来转类型

如果我们想运行本地的wasm肿么办,既然我们知道需要传入的类型,那我们就可以这样写鸟.

1
2
3
4
5
6
7
8
9
10
const fs = require('fs')
let BufferData = new Uint8Array(fs.readFileSync('./未命名.wasm'))
WebAssembly.instantiate(BufferData).then(results => {
instance = results.instance;
window.q = instance.exports.encode;
t1 = parseInt(Date.parse(new Date()) / 1000 / 2);
t2 = parseInt(Date.parse(new Date()) / 1000 / 2 - Math.floor(Math.random() * (50) + 1));
window.kkk = window.q(t1, t2).toString() + '|' + t1 + '|' + t2;
console.log(window.kkk)
})

如果我们不想要转类型肿么办,就想直接fetch完直接操作捏,那么我们可以使用WebAssembly.instantiateStreaming来替代,两者的效果是一样滴.

1
2
3
4
5
6
7
8
fetch('https://match.yuanrenxue.cn/static/match/match15/main.wasm').then(response => WebAssembly.instantiateStreaming(response)).then(results => {
instance = results.instance;
window.q = instance.exports.encode;
t1 = parseInt(Date.parse(new Date()) / 1000 / 2);
t2 = parseInt(Date.parse(new Date()) / 1000 / 2 - Math.floor(Math.random() * (50) + 1));
window.kkk = window.q(t1, t2).toString() + '|' + t1 + '|' + t2;
console.log(window.kkk)
})

4.加密已经搞定鸟,这一题也就迎刃而解鸟
image0dcf5d39055f84c6.png
5.接下来就到下一个网站鸟,这个网站的网址就不公布鸟,我们熟悉流程就好啦,还是先看请求,我们可以发现请求数据和返回数据都被加密了
image46f2dfc5a48e7aaa.png
imageb92abc04b5ed8fdb.png
6.一开始看着有点像base64,并且也在网站中看到了函数关键词base64,满心欢喜的以为拿捏住了,结果是被网站拿捏住了,岂可修!,点进去不知道是个啥,现在我们的目标是要知道Ur这家伙哪里来的
imagec307e7206f07fc38.png
image54c1574f72a660b8.png
7.搜索了一下找到了它的位置,并且发现了关键字wasm,好的我们知道了这是个wasm,分析代码我们知道是经过这FWt来的我们点进去看看,果然看到了老熟人WebAssembly.instantiateStreaming,然后我们根据追栈又找到了老熟人fetch请求.
imagea1c86c2743d9322b.png
image299c9e2858507c48.png
image3702ea58c892a888.png
8.因为这里没有帮我们直接写好node环境下的,不过我们照着之前的葫芦画瓢也很快,提示缺少什么函数我们就扣什么函数补上,耐心点就可以鸟!
image59216f69af32547e.png
image5837465e58108937.png
9.希望看完的你在自己应对wasm的时候,能够施展一些拳脚~