T4 WASM挑战

1、分析

点击题目后会直接跳转

image-20260501112214837

新建一个页面,打上script的断点,断上所有

image-20260501112345090

直接单步执行可以看到wasm_challenge.js文件

image-20260501112438094

从页面打开的方式初步分析是location.href,直接js里搜索,并打上所有的_0x2ba6ea37断点,可以看到最后断住的位置

image-20260501010625322

image-20260501010611971

抠出来执行后可以看到它是拼接后的跳转

image-20260501010557621

把代码全部抠出来分析,压缩全部视图

image-20260501113138592

可以看到js是经过ob混淆的,同时函数名实际是没有混淆的。此时可以解混淆,直接将_0x2ba6ea51[0]这些值可以全部替换,但是我替换完也没感觉没有对结果有很大的影响,可读性也就是一般。

分析函数名,能看到debuggerCheckInterval,此函数是反调试检测,当然这是上帝视角来看的,后面我从hook一步一步讲。注释此函数后,网站就能正常访问了

image-20260501113639272

image-20260501113657478

2、hook找到检测点

hook找到函数检测,此处我选择的是anti_debugger的跳转通杀

image-20260501113844915

image-20260501113956884

可以看到跳转后直接断住,分析上面的堆栈能直接找到分析时的跳转位置

image-20260501114110345

再向上找堆栈,能找到检测函数

image-20260501114200428

3、加密函数分析

image-20260501230904480

加密参数为wasm_auth,根据堆栈信息能定位到加密点

image-20260501231023162

再往上能看到实际调用的是wasm.js里面的函数

image-20260501231123675

而wasm_anti.js会加载wasm_anti_bg.wasm,简单说最终的函数会加载wasm生成,那么我们直接AI,把js和wasm都给到他,让他帮我们生成加密函数

image-20260501231454208

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import binascii

def encrypt_simple(page: str, timestamp: str) -> str:
"""
模拟 wasm 模块中的 encrypt_simple 函数
:param page: 页面名称(字符串)
:param timestamp: 时间戳(字符串)
:return: 加密结果的十六进制字符串(48字节 → 96个十六进制字符)
"""
# 固定的密钥和 IV(来自 wasm 数据段)
key = b'0123456789abcdef'
iv = b'abcdef9876543210'

# 明文 = page + timestamp(直接拼接)
plaintext = (page + timestamp).encode('utf-8')

# AES-128-CBC 加密,需要填充到16的倍数
cipher = AES.new(key, AES.MODE_CBC, iv)
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))

# 返回十六进制字符串
return binascii.hexlify(ciphertext).decode()

# 示例用法
if __name__ == '__main__':
result = encrypt_simple("wasm_challenge_page_2", "1777610340")
print(result) # 输出应当为96个十六进制字符

测试

image-20260501231845724

image-20260501231924892

结果一致。

更多内容也在公众号更新:码字的秃猴

tuhou