[原创] 猿人学学员题34题 js加课例题1 逆向分析
还原“猿人学 第20关”中加密参数 sign 的生成逻辑,最终用 Python 脚本模拟访问接口。
分析地址:aHR0cHM6Ly9tYXRjaC55dWFucmVueHVlLmNuL21hdGNoLzIwIw==
第一步:抓包定位 sign 参数
F12 打开 DevTools,观察 Network 请求

image-20250707142338096.png (140.04 KB, 下载次数: 0)
下载附件
2025-7-7 15:27 上传
易 第二步:断点调试找加密函数
在浏览器中找到 sign 的调用

image-20250707142447212.png (341.34 KB, 下载次数: 0)
下载附件
2025-7-7 15:28 上传

image-20250707142503175.png (363.32 KB, 下载次数: 0)
下载附件
2025-7-7 15:28 上传
下断点进入内部方法,最终定位到调用 _index_bg_wasm__WEBPACK_IMPORTED_MODULE_0__["sign"](retptr, ptr0, len0); 的过程

image-20250707142615626.png (410.3 KB, 下载次数: 0)
下载附件
2025-7-7 15:28 上传
这里可以看出是使用的wasm加密
第三步:进入 WASM 找明文

image-20250707142707404.png (596.45 KB, 下载次数: 0)
下载附件
2025-7-7 15:29 上传
下个断点,找到加密方法

image-20250707142731094.png (633.51 KB, 下载次数: 0)
下载附件
2025-7-7 15:29 上传
直接复制所有的加密方法,扔给ai

image-20250707142845195.png (523.81 KB, 下载次数: 0)
下载附件
2025-7-7 15:29 上传
这里我们看到具体的加密方法为match_twenty__sign,找一下对应位置
call $match_twenty::sign::h5787c0a9b8e619b6
下断点进入到具体的方法里

image-20250707143005687.png (450.32 KB, 下载次数: 0)
下载附件
2025-7-7 15:30 上传

image-20250707143042317.png (649 KB, 下载次数: 0)
下载附件
2025-7-7 15:30 上传
同样的复制内容给ai

image-20250707143428036.png (438.98 KB, 下载次数: 0)
下载附件
2025-7-7 15:30 上传
然后找到对应的加密方法(wasm中对应的位置)

image-20250707143522857.png (434.5 KB, 下载次数: 0)
下载附件
2025-7-7 15:30 上传
在这里下断点
查看

image-20250707143616996.png (489.43 KB, 下载次数: 0)
下载附件
2025-7-7 15:31 上传
往下找一下,发现有个md5字样,打上断点

image-20250707145803940.png (789.29 KB, 下载次数: 0)
下载附件
2025-7-7 15:31 上传
查看方法上方这三个变量的值,分别为
value: 1048504
value: 1114192
value: 31
这里应该就是未加密之前的数据,第一个值是返回值,第二个值为明文,第三个值为偏移量,下面重新进入到
function sign(content) {
try {
const retptr = _index_bg_wasm__WEBPACK_IMPORTED_MODULE_0__["__wbindgen_add_to_stack_pointer"](-16);
var ptr0 = passStringToWasm0(content, _index_bg_wasm__WEBPACK_IMPORTED_MODULE_0__["__wbindgen_malloc"], _index_bg_wasm__WEBPACK_IMPORTED_MODULE_0__["__wbindgen_realloc"]);
var len0 = WASM_VECTOR_LEN;
_index_bg_wasm__WEBPACK_IMPORTED_MODULE_0__["sign"](retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
return getStringFromWasm0(r0, r1);
} finally {
_index_bg_wasm__WEBPACK_IMPORTED_MODULE_0__["__wbindgen_add_to_stack_pointer"](16);
_index_bg_wasm__WEBPACK_IMPORTED_MODULE_0__["__wbindgen_free"](r0, r1);
}
}
方法,然后进入

image-20250707150023823.png (490.89 KB, 下载次数: 0)
下载附件
2025-7-7 15:31 上传
因为浏览器也是要通过指针进行读值的,可以借助浏览器的方法,查看上方获取到的数据
function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
在控制台替换值并输入
cachedTextDecoder.decode(getUint8Memory0().subarray(1114192, 1114192 + 31))
就可以获取到加密前的明文

image-20250707150241062.png (69.4 KB, 下载次数: 0)
下载附件
2025-7-7 15:31 上传
cachedTextDecoder.decode(getUint8Memory0().subarray(1114192, 1114192 + 31))
✍️ 第四步:测试提交
def generate_sign(page, timestamp):
sign_string = f"{page}|{timestamp}D#uqGdcw41pWeNXm"
return hashlib.md5(sign_string.encode()).hexdigest()

image-20250707152209001.png (461.34 KB, 下载次数: 0)
下载附件
2025-7-7 15:31 上传

image-20250707151223926.png (690.02 KB, 下载次数: 0)
下载附件
2025-7-7 15:32 上传