ksjsb/docs/libweapon_vimg_feasibility.md
2026-07-30 20:25:56 +08:00

157 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# libweapon VIMG 纯算实现记录
> 状态:已完成
>
> 约束:运行时不依赖 Frida、抓包、APK、ELF、Unicorn 或 app-fields。
## 1. 最终结论
`passport_account_image` 是客户端本地确定性生成值:
```text
mf(context, event).a().toString()
-> Engine.pr(99999, 0, javaLength * 2, json)
-> VIMG_<base64>$AI_<32hex>
-> WeaponHI.img / wcfg["a_y_q_z"]
-> mobile/checker、requestMobileCode、mobileVerifyCode
```
`wcfg` 只负责本地缓存。`$AI_` 不是服务端签发值,`/f/a/p` 也不是
登录票据的生成前置条件。
目标样本:
```text
out/p0_64_extract/lib/arm64-v8a/libweapon.2.2174a68a..so
SHA256 5d7681c583c66b35e0ee3ce558e5a1ff7fa5be44f19a1e217acc2224455837d7
```
## 2. Java 与 JNI 链
- `wc.k()` 调用 `Engine.pr(ze.v0, 0, s2.a(str) * 2, str)`
- `ze.v0 = 99999`
- `str = new mf(context, event).a().toString()`
- mode 0 对应 native `0x19ea90`
- `0x19ea90` 依次调用 base 生成器 `0x1a1850` 和 AI 生成器 `0x1a2d94`
## 3. VIMG Base
```text
payload_bytes = JNI modified UTF-8(payload)
plain = 2d 3d 00 00 7d 01 || LE16(len(payload_bytes)) || payload_bytes
native_buffer = plain XOR 0x55
cipher = ChaCha20-IETF(native_buffer, fixed_state, counter=1)
base = "VIMG_" + Base64(cipher)
```
ChaCha 初始状态:
```text
1783595e 8dc26a78 2599184e 729781d3
2adef3f4 9876ef16 9abed34f 9103de12
a92157f6 a9a24ff4 9138d3fd 2a2193f3
00000001 74f4cbcd 98c26a78 ab99184e
```
轮函数是标准 20 轮 ChaCha旋转量为 `16/12/8/7`
## 4. AI H1
将完整 `VIMG_...` ASCII 文本按小端 uint32 分组。调用方每批处理最多
64 个字native 压缩函数先折叠为 16 个字:
```python
folded = [0] * 16
for index, word in enumerate(source_words):
folded[index % 16] ^= word
```
随后执行自定义 IV 的 10 轮 BLAKE2s 压缩:
```text
H0:
aa98186e f3ccd768 99531aae 669781d3
125fd5b4 9883595e 74f4cbcd 98c26a78
IV:
ab99184e f3ccd768 99531aae 669781d3
125fd5b4 9883595e 74f4cbcd 98c26a78
```
- counter 是累计处理的 uint32 字数。
- 最后一批令 `v[14] ^= 0xffffffff`
- sigma 是标准 BLAKE2s 10x16 消息置换表。
- 输出为 8 个低 32 位链值。
- H1 文本为 8 个 `%08x` 直接拼接,末尾附一个空格。
## 5. AI H2
H2 只使用 H1 文本前 16 个 ASCII 字节:
```text
ADD_BASE = 0c35ff3dcbfefb3f3efd6539fd39efcd
H2[i] = ((ADD_BASE[i] + 3) & 0xff) XOR H1_TEXT[i]
AI[i] = H2[i] XOR (2dd345c0)[i % 4]
```
最终:
```text
passport_account_image = base + "$AI_" + hex(AI)
```
## 6. mf Payload
`core/weapon_mf.py``mf.a()` 的 JSONObject 插入顺序构造字段,包括:
- 设备型号、厂商、Android 版本和本地 DID。
- elapsedRealtime、uptime、启动时间和 boot count。
- Weapon 上报时间与本地报告计数器。
- 样本中的反调试/环境状态字段。
同一轮登录只生成一次票据,并复用于预检、发码和验码。
## 7. 实现与验证
生产实现:
- `core/weapon_vimg.py`VIMG base、H1/H2、完整票据与反解。
- `core/weapon_mf.py`:设备 JSON 和 profile 票据生成。
- `tools/sms_login_cli.py`:纯算票据接入登录链。
分析 oracle
- `tools/libweapon_vimg_oracle.py`:仅用于离线差分,不进入生产路径。
验证结果:
- 固定 native 向量覆盖空输入、UTF-8、ChaCha 跨块、H1 跨 16/64 字。
- 21 组不同长度随机输入与 Unicorn native oracle 逐字节一致。
- 捕获票据反解出的 757 字节真实 `mf` JSON 可由 oracle 重新生成完全相同
的 base 和 `$AI_`
## 8. CLI
短信登录每次生成全新画像、在线注册 DFP并在注册完成后用当前云 DID 现场生成
`passport_account_image`
```powershell
uv run python -m tools.sms_login_cli --mobile MOBILE
```
已有验证码时跳过发码:
```powershell
uv run python -m tools.sms_login_cli `
--mobile MOBILE `
--code CODE
```
CLI 不提供设备画像、app-fields、WCFG 或复现种子的注入入口,避免把历史设备
状态带入下一次登录。
DFP 在线注册可能把本地初始 DID 替换为云 DID。主 APP 随后调用
`WeaponHI.setG(currentDid)`,所以 `mf` 字段 `03000` 必须使用注册后的
`DeviceProfile.did`,并与登录 query 的 `did` 保持一致,不能继续使用
`local_did`