本帖最后由 chocolate. 于 2025-7-7 16:04 编辑
猿人学第二十关逆向分析教程
[原创] 猿人学学员题34题 js加课例题1 逆向分析
还原“猿人学 第20关”中加密参数 sign 的生成逻辑,最终用 Python 脚本模拟访问接口。
分析地址:aHR0cHM6Ly9tYXRjaC55dWFucmVueHVlLmNuL21hdGNoLzIwIw==
🚩 第一步:抓包定位 sign 参数
F12 打开 DevTools,观察 Network 请求
🧠 第二步:断点调试找加密函数
🔍 第三步:进入 WASM 找明文
下个断点,找到加密方法
直接复制所有的加密方法,扔给ai
这里我们看到具体的加密方法为match_twenty__sign,找一下对应位置
call $match_twenty::sign::h5787c0a9b8e619b6
下断点进入到具体的方法里
同样的复制内容给ai
然后找到对应的加密方法(wasm中对应的位置)
在这里下断点
查看
往下找一下,发现有个md5字样,打上断点
查看方法上方这三个变量的值,分别为
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);
}
}
方法,然后进入
因为浏览器也是要通过指针进行读值的,可以借助浏览器的方法,查看上方获取到的数据
function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
在控制台替换值并输入
cachedTextDecoder.decode(getUint8Memory0().subarray(1114192, 1114192 + 31))
就可以获取到加密前的明文
- 找到
sign(ptr, len) 所使用的明文地址
- 用浏览器控制台的
getStringFromWasm0 方法查看明文
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()
|