<aside>
😀
在现代Web安全中,WebAssembly(WASM)因其高效性和跨平台特性被广泛应用于浏览器端的加密和数据处理。本文详细记录了逆向分析一个使用WebAssembly加密的登录接口的过程,目标是获取登录请求中关键的sign值。通过结合JavaScript和Python技术栈,我们不仅成功破解了加密逻辑,还总结了一套通用的逆向思路和方法,适用于类似的WASM逆向工程场景。
</aside>

啥是WebAssembly就不多说了,自己去看吧。
aHR0cHM6Ly93d3cud2FpbWFveGlhLm5ldC9sb2dpbg==
主要目标获取登录接口的sign值。
python:版本3.9.13
node:版本v18.15.0
pip isntall pyexecjs

网站无防护,很容易就找到加密点,这里就略过,这不是本文的重点,最终发现是window.sign进行加密的。直接在控制台敲window.sign,然后按住Ctrl键不放,鼠标点击一下输出的函数直接跳到加密代码位置(文件名wasm_exec_v2.js)。
wasm_exec_v2.js文件简单分析,没有加密,还做了浏览器和node环境的兼容,简直太nice了,也就是说node直接能跑通。关键代码分析下
if (
global.require &&
global.require.main === module &&
global.process &&
global.process.versions &&
!global.process.versions.electron
) {
if (process.argv.length != 3) {
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
process.exit(1);
}
const go = new Go();
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
return go.run(result.instance);
}).catch((err) => {
console.error(err);
process.exit(1);
});
}
/**
查看`WebAssembly.instantiate`的`MDN`文档参数如下:
bufferSource
一个包含你想编译的 wasm 模块二进制代码的 typed array(类型数组) or ArrayBuffer(数组缓冲区)
importObject 可选
一个将被导入到新创建实例中的对象,它包含的值有函数、WebAssembly.Memory 对象等等。编译的模块中,对于每一个导入的值都要有一个与其匹配的属性与之相对应,否则将会抛出 WebAssembly.LinkError (en-US)。
也就是说:
fs.readFileSync(process.argv[2])其实是`xx.wasm`文件的二进制流`ArrayBuffer`
*/
找了一下,发下浏览器加载过一个main.wasm。那就直接在控制台重发一下请求,为了流文件粘贴复制,直接转一下格式,用到的时候代码还原一下
fetch("<https://wmx-1253696238.cos.ap-shanghai.myqcloud.com/main.wasm>", {
"referrerPolicy": "strict-origin-when-cross-origin",
"body": null,
"method": "GET",
"mode": "cors",
"credentials": "omit"
}).then(res=>{
return res.arrayBuffer();
}).then(buf=>{
let data = JSON.stringify([].slice.call(new Uint8Array(buf)));
console.log(data);
copy(data);
});
// (new Uint8Array(data)).buffer; 可以通过这行转回buffer