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

</aside>

WebAssembly(wasm)逆向记录

programming_image_part_1.png

前言

啥是WebAssembly就不多说了,自己去看吧。

目标网站

aHR0cHM6Ly93d3cud2FpbWFveGlhLm5ldC9sb2dpbg==

逆向目标

主要目标获取登录接口的sign值。

调试环境

python:版本3.9.13

node:版本v18.15.0

pip isntall pyexecjs

请求分析

programming_image_part_4.png

0x0

网站无防护,很容易就找到加密点,这里就略过,这不是本文的重点,最终发现是window.sign进行加密的。直接在控制台敲window.sign,然后按住Ctrl键不放,鼠标点击一下输出的函数直接跳到加密代码位置(文件名wasm_exec_v2.js)。

0x1

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