spiderdemo T4 基本wasm

首先会跳转,我一开始不知道怎么解决这个跳转

但是可以在跳转前一瞬间打开view-source:去查看源代码:

然后找到加载代码,丢给ai分析一通,给了个大致流程:

逆向流程分析

  1. WASM 加密验证机制
    从代码中可以看到核心验证逻辑:

// 关键加密参数

const timestamp = Math.floor(window.get_timestamp() / 1000).toString();

const verifyString = ${type}_page_${page};

const wasmAuth = window.encrypt_simple(verifyString, timestamp);

// 请求参数

url += &wasm_auth=${encodeURIComponent(wasmAuth)};

headers['X-WASM-Timestamp'] = timestamp;

headers['X-WASM-Page'] = page.toString();

关键点:

verifyString 格式: {challenge_type}page {page}

encrypt_simple() - WASM导出的加密函数

get_timestamp() - WASM导出的时间戳函数

需要传递 wasm_auth、X-WASM-Timestamp、X-WASM-Page 三个参数

  1. 大致逆向步骤

步骤1: 下载并分析 wasm_anti.js

步骤2: 找到 .wasm 文件的加载逻辑

步骤3: 反编译 .wasm 文件 (使用 wasm2c 或 wabt)

步骤4: 定位 encrypt_simple 函数的算法实现

步骤5: 定位 get_timestamp 函数实现

步骤6: 用 Python 重写加密算法

步骤7: 爬取100页数据并求和

那么第一步就是下载js代码

下载了三个js

然后在anti.js里看到了加载wasm的地方,然后就直接下载了文件

那么下载好文件,要做的就两个事情了

py 复制代码
def encrypt_simple(verify_string, timestamp):
    # TODO: 从反编译的 WASM 中提取加密算法
    pass

def get_timestamp():
    # TODO: 从反编译的 WASM 中提取时间戳逻辑
    pass

由于我暂时还不是很会反编译wasm

我直接拿给ai分析一下

但是ai现在还是不能反编译wasm自动,所以不能一直依赖ai了。。

基于对你提供的 wasm_anti_bg.wasm 文件内容的静态分析(通过字符串和符号表),可以确定该 WASM 模块是使用 Rust 编写的,并且核心逻辑是 AES-128 加密

以下是对该文件的逆向分析结论及对应的 Python 代码实现。

1. 逆向分析结论

  • 编译语言 : Rust (依据: src/lib.rs, core::fmt, alloc::vec 等字符串特征)。

  • 加密算法 : AES-128

  • 文件包含 aes_128aes_encryptsub_bytesshift_rowsmix_columns 等 AES 算法的标准底层操作名称。这表明它可能包含了一个纯 Rust 实现的 AES 算法(而非调用外部 JS 库)。

  • 时间戳逻辑 : 字符串 js_sys::Date::now 表明它调用了 JavaScript 的 Date.now(),即返回 13位毫秒级时间戳

  • 加密模式推测:

  • 由于函数名为 encrypt_simple 且涉及反爬(anti_bg),通常这类 WASM 挑战会使用 AES-128-ECB (最简单,无需 IV)或者 AES-128-CBC(需要 IV)。

  • 密钥(Key)通常由 时间戳 衍生而来,或者是一个硬编码的静态字符串。


所以他还是不知道正常代码是什么样子的。

所以这个时候还是要去解决跳转问题

用插件hook一下跳转

代码被混淆了,做一个替换

拿着代码一通分析,发现关键逻辑在这里:

所以直接把这个函数滞空

滞空之后,可以正常翻页了


然后就去看代码

找到wasm的网络包,进栈

打个断点:

在加密位置打上断点,准备进入

在这里返回:

慢慢来,需要在wasm中单步跟一下,找到真正的加密:

跟到这个部分:

继续往下走:

继续跟到这里,在这里找密钥

在var 400里找到key

  1. 特征分析0xCC 是 C/C++ 编译器在 Debug 模式下填充未初始化栈内存 的经典标志("烫烫烫")。0xC03F... 这种结构看起来像是浮点数或位切片(Bitslice)算法的中间状态。
  2. 参数位置aes128_key_schedule 函数通常有两个参数:Context (输出)Key (输入)
  • 在汇编中:
wat 复制代码
local.get $var7
i32.const 44   ;; 参数 1: 很有可能是输出缓冲区 (Context)
i32.add
local.get $var7
i32.const 400  ;; 参数 2: 很有可能是输入密钥 (Raw Key)
i32.add
call ...key_schedule...
  • 你之前检查的是 44,那是输出结果(或者还没写的脏内存)。
  • 真正的 Key 藏在第二个参数 400 里!
  1. 代码证据
    在调用 key_schedule 之前的几行代码中,程序在疯狂地往 $var7 + 400403407... 写数据。这证明它正在现场拼装 Key

修正:提取真正的 Key

请保持断点在 call ...key_schedule... 不变,在 Console 中执行以下代码:

js 复制代码
// 1. 基地址 (请再次确认当前 Scope 中的 $var7 值,不要直接用旧的)
// 假设还是 1047712,如果变了请修改!
var base = 1047712; 

// 2. 查看偏移量 400 (这是真正的 Key 入口)
var realKeyPtr = base + 400;
var realKeyBytes = new Uint8Array(wasm.memory.buffer).slice(realKeyPtr, realKeyPtr + 16);

// 3. 打印结果
console.log("★ 真·AES Key (Hex):", Array.from(realKeyBytes).map(b => b.toString(16).padStart(2, '0')).join(''));
console.log("★ 真·AES Key (String):", new TextDecoder().decode(realKeyBytes));

最后确认是一个aes加密,有盐值和key

这里我只找到了key,iv推出来的

py 复制代码
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import binascii

# ==========================================
# 🕵️‍♂️ IV 逆向提取器
# ==========================================

# 1. 核心参数 (已通过你的 JS 验证)
KEY = b""

# 2. 浏览器的"正确答案" (以你之前截图的 Page 4 为例)
# 密文: 39d6...
browser_ciphertext_hex = "39d6129e89e5c92e4afc0c516993e35cde4564db0120473cb57be5aa94238b5d"
browser_ciphertext = binascii.unhexlify(browser_ciphertext_hex)

# 3. 对应的"正确明文" (Page 4)
# 截图里 timestamp 是 1768612656
page = 4
timestamp = "1768612656"
plaintext_str = f"wasm_challenge_page_{page}{timestamp}"
# 加上标准的 PKCS7 Padding
plaintext_bytes = pad(plaintext_str.encode(), 16)

print(f"[*] 尝试破解 IV...")
print(f"[*] 使用 Key: {KEY}")
print(f"[*] 明文 Block 1: {plaintext_bytes[:16]}")

# 4. 破解逻辑
# CBC 公式: Cipher = Enc(Plain XOR IV)
# 逆向公式: Dec(Cipher) = Plain XOR IV
# 最终推导: IV = Dec(Cipher) XOR Plain

# 先用 ECB 模式解密 (相当于只做 Dec 这一步)
cipher_ecb = AES.new(KEY, AES.MODE_ECB)
decrypted_intermediate = cipher_ecb.decrypt(browser_ciphertext)

# 取出第一块进行 XOR
block1_plain = plaintext_bytes[:16]
block1_dec = decrypted_intermediate[:16]

# 计算 IV
iv = bytes(a ^ b for a, b in zip(block1_plain, block1_dec))

print(f"\n🎉 成功捕获 IV!")
print(f"👉 IV (Hex): {iv.hex()}")
print(f"👉 IV (Str): {iv}")

# 5. 验证破解结果
print(f"\n[验证] 使用破解的 IV 重新加密...")
cipher_check = AES.new(KEY, AES.MODE_CBC, iv)
token_check = cipher_check.encrypt(plaintext_bytes).hex()
if token_check == browser_ciphertext_hex:
    print("✅ 验证通过!生成的 Token 与浏览器完全一致!")
else:
    print("❌ 验证失败...")
```
相关推荐
二狗哈1 天前
WebAssembly 入门分享
wasm
BuHuaX4 天前
Unity项目怎么接入抖音小游戏?
unity·c#·游戏引擎·wasm·游戏策划
LYFlied11 天前
Rust代码打包为WebAssembly二进制文件详解
开发语言·前端·性能优化·rust·wasm·跨端
LYFlied14 天前
WebAssembly为何能实现极致性能:从设计原理到执行优势
前端·wasm·跨端
拾荒李14 天前
使用Webassembly实现图片压缩
前端·javascript·性能优化·rust·wasm·webassembly
MoonBit月兔18 天前
用 MoonBit 打造的 Luna UI:日本开发者 mizchi 的 Web Components 实践
前端·数据库·mysql·ui·缓存·wasm·moonbit
oioihoii25 天前
C++与浏览器交织-从Chrome插件到WebAssembly,开启性能之门
c++·chrome·wasm
LYFlied1 个月前
WebAssembly (Wasm) 跨端方案深度解析
前端·职场和发展·wasm·跨端
MoonBit月兔1 个月前
MoonBit 获瑞士 DFINITY 基金会支持,进入 Internet Computer 技术生态
wasm·编程语言·moonbit