这篇文章记录 D3CTF 2026 `d3llvm` 在启动阶段的分析过程,重点不在最终输入算法,而在下面这条链路:
-> logcat 定位 JNI_OnLoad
-> 逐层 trace 外层 libd3llvm.so
-> 放行环境检查
-> 发现加密的 libd3llvm_payload.so
-> 通过 dlsym 捕获 Payload_OnLoad
-> 从内存恢复可被 IDA 正确识别的 payload ELF
-> 分析 payload 内层状态机
-> 定位并验证第二层检查
测试环境
设备:Pixel 5,arm64-v8a,已解锁并具有 root
系统:Android
动态分析:Frida 17.15.3
静态分析:JADX、IDA Pro
辅助工具:adb、logcat、apktool
包名:com.example.d3llvm
1. 从启动崩溃开始
安装 APK 后直接点击图标,直接闪退。看起来是环境检测到异常,抓日志看看清理日志、启动 Activity,再导出本次崩溃信息:
```cmd
adb shell am force-stop com.example.d3llvm
adb logcat -c
adb shell am start -n com.example.d3llvm/.MainActivity
adb logcat -d > "D:\anzhuonixiang\d3llvm_log.txt"
```

可以看出,Android 明确指出 `libd3llvm.so` 的 `JNI_OnLoad` 返回了错误值。
所以目前线索指向分析libd3llvm.so,进去看看到底怎么检测的,先用apktool解包一下apk。
2. 静态查看外层 JNI_OnLoad


看起来有点吓人,检测点挺多而且嵌套了几层,大致找几个看一下

TracePid检测有没有正在被调试

检测Bootloader锁是否打开,也就是说root过的手机环境会被检测
3. 先 trace 返回值判断哪些检测点需要绕开
由于apk一打开直接闪退,应使用启动模式而不是附加模式
frida -U -f com.example.d3llvm -l .\d3llvm_trace_step.js

第一次运行时,外层流程停在 `sub_103BC`。修改返回值继续

哦豁,都验证通过,但依然没有启动成功。怀疑是下图中的Payload_Onload函数校验没通过。

改一下脚本,抓一下v3 v5的值。v3是Payload_Onload函数的函数地址,且位于另一个.so文件(libd3llvm_payload.so)

找到了,v5为-1,也就是说Payload_Onload函数大概率也是个校验函数,执行结果不满足要求。
这里如果直接修改Payload_Onload函数返回值,有可能会导致其中一些初始化操作不执行,保险起见去对应函数部分看一下。
4. 动态dump出libd3llvm_payload.so
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。