🗒️闯关UnCrackable level3
2026-3-8
| 2026-8-17
字数 1981阅读时长≈ 5 分钟

静态分析

寻找java层和native层检测点

反编译源代码:找到java层的检测点
checkRoot1-3和isDebuggable与前2关一样,绕过如下:
notion image
check_code函数跟进能看到bar,native层检测
notion image

分析IDA中bar函数的校验

导入libfoo.so到IDA,搜索functions找到bar函数,f5反编译代码如下:
result肯定是校验结果,v6和v7进入while循环,return (_DWORD)v7 == 24;从v7=0可以看出v7不是最终的秘密字符串,只是一个计数器类的角色。进入while循环的只有v8和v6。寻找目标就变成哪个是秘密字符串。
 
从java层看到 check_code传了一个入参是用户在界面输入的字符串,
notion image
IDA中的入参只有a1和a3,它们的关联值都给了v6,虽然不知道为啥双参数,但是v6肯定就是用户输入的字符串。那么v8就是秘密字符串
notion image
v8在memset的时候才分配了空间,这时候没值,赋值只能在sub_10E0之后,所以我们需要hook sub_10E0的返回值。
 
同时,程序调用bar函数,一直到执行sub_10E0之前,需要经过if ( dword_15054 == 2 )
函数内部没有dword_15054的定义,所以在其他地方给dword_15054赋值为2
IDA交叉引用找到init处存在++dword_15054,此时有一个sub_323C()防源码篡改,但是使用frida不需要篡改。
notion image
另一处是sub_31B0函数中存在++dword_15054
notion image
if ( dword_15054 == 2 )需要俩处++dword_15054都生效,每一处都+1。
init()处的校验是sub_323C防篡改,不影响frida脚本。
sub_31B0()处调起了一个函数sub_30D0(),进入查看发现,此处通过打开/proc/self/maps,使用strstr()匹配frida和xposed
notion image
思考绕过逻辑:
第一种:hook fopen函数,当fopen打开的 /proc/self/maps时,重定向到一个没有问题的目录。
第二种:hook strstr函数,当发现frida和xposed的时候,强制返回值为false
使用第二种绕过逻辑:

frida最终脚本:

此时,我们绕过了java层的校验,bar中native层对frida,xposed的检测,可以让代码逻辑成功加载到 用户输入字符串和秘密字符串 比较的地方。
询问ai后,秘密字符串是v8和 qword_15038 逐字节做 XOR 运算,hook sub_10E0函数在onleave获取v8的值就行。
之前 Java 层的 MainActivity 中,调用init("pizzapizzapizzapizzapizz".getBytes())。Native 层的 init 函数其实做的操作就是:把这串 "pizza..." 存到了内存地址为 0x15038 (qword_15038) 的全局变量空间里。
最终脚本,随意输入个字符串对比,frida就会输出:
notion image
 
  • 渗透逆向
  • IDA动态调试闯关UnCrackable level1-2
    Loading...