
WebAssembly技术
更新: 2025/2/24 字数: 0 字 时长: 0 分钟
技术简介
WebAssembly也叫浏览器字节码技术,是一种可以使用非JavaScript编程语言编写代码并且能在浏览器上运行的技术方案。
WebAssembly的基本思路是将一些核心逻辑使用其他语言(如C/C++语言)来编写,利用Emscripten工具编译成类似字节码的wasm格式的文件,通过JavaScript调用执行,从而起到二进制级别的防护作用。由于Webassembly是经过编译器编译之后的字节码,因此运行速度更快,体积更小,而且在语法上完全脱离 JavaScript,同时具有沙盒化的执行环境。
使用示例
比如,这就是一个基本的Webassembly示例:
WebAssembly.compile(new Uint8Array(`
00 61 73 6d 01 00 00 00 01 0c 02 60 02 7f 7f 01
7f 60 01 7f 01 7f 03 03 02 00 01 07 10 02 03 61
64 64 00 00 06 73 71 75 61 72 65 00 01 0a 13 02
08 00 20 00 20 01 6a 0f 0b 08 00 20 00 20 00 6c
0f 0b`.trim().split(/[\s\r\n]+/g).map(str => parseInt(str, 16))
)).then(module => {
const instance = new WebAssembly.Instance(module)
const { add, square } = instance.exports
console.log('2 + 4 =', add(2, 4))
console.log('3 ^ 2 =', square(3))
console.log('(2 + 5) ^ 2 =', square(add(2 + 5)))
})
**这里其实是利用WebAssembly定义了两个方法,分别是 add
和 square
,分别用于求和和开平方计算。那这两个方法是在哪里声明的呢?其实它们被隐藏在 Uint8Aray
里面。仅仅查看明文代码,我们确实无从知晓里面究竟定义了什么逻辑,但确实是可以执行的。**我们将这段代码输入到浏览器控制台下,运行结果如下:
2 + 4 = 6
3 ^ 2 = 9
(2 + 5) ^ 2 = 49
?> 提示:通过WebAssembly可以成功将核心逻辑“隐藏”起来,这样某些核心逻辑就不能被轻易找出来了。所以越来越多的网站使用WebAssembly技术来保护一些核心逻辑不轻易被人识别或破解,可以起到更好的防护效果。
wasm文件
**通过WebAssembly编译后的文件即为 .wasm
文件。在Python中可以使用第三方库 pywasm
来调用 .wasm
文件里面的方法。**第三方库 pywasm
安装命令和使用方法如下:
pip install pywasm
实战解析
难度:简单
题目地址:https://match.yuanrenxue.com/match/15
访问网址获取任务,在Network里面的Fetch/XHR选项中定位到了该网页数据的来源请求,发现相对于前面的题目还多加载了两次 main.wasm
文件,继续分析:
多次访问前面3页的页面,分析比较请求头参数,得出初步接结论:每次请求,请求头的参数没有发生变化,但参数m的值在不断发生变化,参数page则是页码数。
现在我们需要定位到,哪一行的代码发送了当前的请求,点击左侧的Initiator选项,它主要是标记请求是由哪个对象或进程发起的(请求源),重点关注里面的request请求,显示从一个名称为“15”的文件的第736行代码发送了当前请求,点击后面的地址:
跳转到了该文件的第736行,看上面有两个很熟悉的参数 page
页码和 m
加密参数,参数m的值来源于 window.m()
方法的返回值,其中 window.m()
方法返回值涉及到三个变量,window.q()
方法、t1
、t2
,其中 t1
、t2
的值和时间戳有关,而 window.q
方法和 results
的 encode
方法有关,而 results
就是 main.wasm
文件内容,也正是最开始第一次请求加载的文件:
这下就可以对加密参数完全得出结论了:
参数m:和变量t1、t2、main.wasm文件的encode方法有关
参数page:页码数
下载并保存网站上的 main.wasm
文件,双击开发者工具里的main.wasm
文件进行下载:
修改上面的示例代码,结合上面截图的m参数试运行,结果和m参数最前面的数一样:
这里我们就只需要抠生成变量 t1
、t2
的JS代码,最后返回一个数组即可:
m = function (){
t1 = parseInt(Date.parse(new Date())/1000/2);
t2 = parseInt(Date.parse(new Date())/1000/2 - Math.floor(Math.random() * (50) + 1));
return Array(t1, t2);
};