Android APK,libkctf.so 的 nativeProcessInput 校验 100 位小写 hex(50 字节)注册码。50 字节被拆成偶数下标 25 字节走 Check A、奇数下标 25 字节走 Check B,两条链靠一个字节 v99 耦合。
题目的难点在反分析上:
破掉这两点后,剩下的是一个 46 位稀疏布尔方程组,DFS 秒解。
AndroidManifest.xml 里 extractNativeLibs=false,所以 lib/arm64-v8a/libkctf.so
在 APK 里是 Stored 未压缩的,可直接 dump。Java 层字符串用 c() 异或 0xA5A5A5A5
混淆、d() 是个被 jadx 展平成死循环的状态机(读 smali 还原即可),但都只是幌子,
校验全在 native。
so 有控制流平坦化 + 不透明谓词 + BR X16 间接派发,IDA 反编译多处失真(无独立
prologue 的函数被并进调用者)。
用 Unicorn 手写 harness 把 nativeProcessInput 单独跑起来(solve/uc_oracle.py):
pyelftools 读 .rela.dyn/.rela.plt 做重定位(60 条,20 个导入桩)、
JNI vtable 打桩、以及裸 svc #0 系统调用(so 绕过 libc 直接 mmap,nr=222)。
angr 在这里走不通(NEON 的 Iop_ZeroHI64ofV128 未实现)。
sub_130CC / loc_1325C / loc_13878 三段曾被写成"只维护不透明状态",实际都是真校验:
loc_1325C 用 LE32(v117[9:13]) 作种子生成 256 字节 xorshift32 密钥流,
异或进 S 盒(偏移 (0x8C+i)&0xff),再校验 sbox[0..2] == 85 26 27。
失败就重新载入恒等表 —— 这正是之前所有实验看到的现象。→ sbox[0]=0x85。

loc_13878 的 rot = (v117[21]&0x1F) ^ (在 sub_126B8 前 1KB 找到 BRK ? 1 : 0)
是真反调试;八个方程 ROL((x+(K>>5))^K^((x>>12)+(K<<4)), rot) == M[j%4]^const
唯一解出 rot=7、dword_16484=0x371342。失败则 rot 强制归零。

解出偶字节与 Check A 对 Check B 的唯一要求:
sub_5FE8 是个rate 等于全状态的 ARX 海绵(12 轮纯 ARX,挤出时直接吐整个 32 字节状态)。
这是致命设计缺陷:KDF 可逆,给定需要的 32 字节状态就能反推 25 个奇字节,
而 7 字节 0x5A 填充顺带成为一个 56 位一致性校验。
(sub_6374 里那套 NEON MixColumns + GF(2^8) 0x1b 的"AES"全部相消,实测 sub_6374(x,y,k)=x^y、
sub_6614(x,y)=x+y。)

状态四个字里 A0/C0/D0 由设备常量 G(sub_10E18 产出的 32 字节,真机测得)的三段比对钉死,
只剩 b0 一个 64 位未知。而 acc144 == 0 的 8 个方程里,除 w27 外每一项都是常量:

i=0..3 与 i=4..7 两半独立自洽(2^-32 的巧合概率),所以

B 一固定,sub_5998(b0,B,w27,0xD7) & 0x3FFFFFFFFFFF == 0x16EFF8C39C23
这 46 个输出位每位只依赖 b0 的 2~5 位,DFS 直接解,再用 56 位填充筛出唯一解。
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。