type
Post
status
Published
date
Mar 4, 2026
slug
逆向/smail01
summary
自学安卓逆向02
tags
逆向
category
网络安全
icon
password
简要知识基础记录
花一小会时间简单看看,为了能看懂smail代码做静态分析,简记
v0-3 存变量p0-3 常存对象const-xxxx赋值invoke-xxx方法调用move-result-object v3 存返回值goto :next_iter无条件跳转 到标签 :next_iternop 空操作if-xxx v0:aaaa 如果v0xxx,跳到a标签汇编代码必记:

- X0 专门用于存放函数的返回值(调用任意函数都是)
- X0-X7 用于传递函数参数,存在X2,也可以不用X1,X0,顺序不固定
- PUSH 函数入口,R4-R11,如果函数不用,就不用声明。
- BL _strcmp调用函数-->strcmp(a,b,c,d)在反汇编常见的编译输出(如C语言编译结果)中,所有函数调用都会严格遵循AAPCS,你可以放心地认为参数顺序与寄存器顺序一致:R0 → 第一个参数,R1 → 第二个参数。 BLR间接调用。后面跟寄存器(如 BLR X8)。
- BNE(不等于0) BEQ(等于0),常用于反转条件。针对条件NOP也是常见方法
- JNI 函数(名字以 Java_ 或JNI_OnLoad开头)


- LDR/STR 搬运数据
IDA操作基础:
直接导入apk默认不加载so代码,只有dex代码。所以只能拖so文件
Import:模块导入表
Export:模块导出表(外部引入函数,猜测外部通过函数引入so文件代码此处可能存在)
Functions:所有函数(外部引入+内部存在)
Hex View:十六进制视图
Structures:结构体存储视图(可能识别不全)
跳入函数后f5可以反编译看代码
代码变量可以通过右键看交叉引用—>所有使用此变量的地方
UnCrackable-Level1.apk
frida动态绕过
进入后弹出,搜索detected找到核心检测代码

第一个函if调用三个方法,任意一个为真,就会弹出Root detected!
frida重构三个方法,直接return false
第二个if调用b.a(),结果为真,弹出App is debuggable,
如果要使输入任何数字都成功,只需要把a.a()函数重定义返回true
此处只得到最终的秘密字段,进入a函数
分析函数sg.vantagepoint.a.a.a()函数返回值给bArrA,然后通过 str.equals(new String(bArrA));判断str和bArrA是否相等。所以bArrA就是那个secret
调用一次sg.vantagepoint.a.a.a拿到返回值就行
总体脚本:


静态smail代码修改
查找函数,搜索onCreate定位
root,debug检测绕过
思路1:都要跳cond_12直接修改它为空操作,绕过root检测
判断v0等于0时,跳到cond_26,强制赋值为0即可,绕过debug
思路2:goto跳过整个检测逻辑
UnCrackable-Level2.apk
frida动态绕过
依旧是root,debuggable检测,思路一样,绕过后就能进入app
找secret逻辑
替换return false能显示success,但是得不到字符串
native层的逻辑都在so文件里,引入了函数bar,bar对于源码就是外部引入,在export表。解压后只有一个libfoo.so,导入搜索,只存在一个bar函数
静态注册的命名规则就是Java_包名_类名_方法名。如果搜不到bar,那说明是动态注册

点击后跳到IDA的主视图——>流程图,经过搜索发现空格可以切换另一个视图,再通过f5编译,就拿到了这段代码


这段代码已经将目标字符串写出来了,不过此处学习,研究一下,此处只有在byte_1300C为1才会跳进函数判断输入的字符串和目标字符串是否相等,如何确定byte_1300C一定是1,每次都能跳进if内。
通过右键byte_1300C交叉引用查看位置,发现还有一处调用赋值为1,通过命名规则我们可以知道,就是Java.sg.vantagepoint.uncrackable2.MainActivity类的init方法

在jadx中打开源码可以看到init方法在程序运行最初就已经调用,所以此处的byte_1300C是必为1不动的。

由于没写过frida动态替换so文件的代码,而IDA没有像jadx的复制代码段,所以让ai在网上找了一个这样工具
右键函数直接生成函数对应的frida脚本

将原来的绕root,调试和这个代码放在一起,绕过成功
只添加了一行代码,可以看到插件精准定位到函数,无需自己寻找
// 修改返回值:JNI jboolean 返回 1 = true
retval.replace(1);
其中hookNativeCodeCheck();这个封装好的就是插件生成的
最大的bug问题解决
学习时花了很长时间找脚本问题,最后发现是面具插件和frida冲突了
- Zygisk next插件有时会和frida冲突,导致frida脚本永远无法成功。此时最好关闭Zygisk next插件。
- 第二种解决办法就是降版本Zygisk next,官方issue中有兼容版,降版本
注意:哪怕你不用Zygisk next插件,面具自带的Zygisk也会出问题,无语
尝试静态绕过但未成功
看不懂代码,不过我们知道只需要把v6,v7变成一样的就肯定校验成功
我们知道BL是调用函数的指令,且调用了strncmp
调用函数前要准备好俩个参数,X1和X0就是目标了
改最后一个MOV V0 X1 :S1就好啦,达到效果!strncmp(v7, v7, 0x17u);

但是想直接改so的时候问ai步骤,说是会触发so完整性校验,看上去特别复杂,不是我简单学一下就会的,先放弃。