在逆向过程中经常会遇到各种加密,如果在java层还好说,大部分都是在so层,而且自定义的算法较多,加壳,混淆,这时候我们就可以尝试调用它们app的so文件,其中常见的手段就是签名验证,首先打开jadx-gui分析出java层加密调用so层方法
顺着找上去发现调用so文件
直接找到加载so文件的地方
将so文件copy到我们demo中开启一个http服务,直接调用下encyptString方法
发现并没有返回真正的加密结果,一定so层做逻辑效验了,我们找到这个so文件,使用ida打开,找到导出的函数
发现采用的方式是动态注册(静态注册是以java_包名_类名_方法名开头的,否则就是动态注册)动态注册会加载JNI_OnLoad 函数,我们进入这个函数
可视效果太差了,我们导入jni.h头文件(百度搜下载即可,简单的说就是java和c的翻译官),右键选择JNIEnv
发现代码瞬间清晰了很多
找到RegisterNative第3个参数0ff_7004就是我们导出的函数地址,我们进入这个函数,找到java层导出的函数地址sub_3DC4,因为so采用的是Thumb指令,所以要+1
跟进去,查看下思维导图
可以看代码执行的逻辑很简单无非就是一个判断,我们F5转换成伪C代码
发现ERROR_9304好眼熟啊
这正是我们demo返回的错误信息,由此可得出,if里面肯定就是正常逻辑了,else里面就是返回错误的逻辑,我们继续跟进sub_15C0
可以看到通过反射拿到当前app的签名和正确的签名做比较,如果不确实是否有签名验证,就直接打开字符串窗口Shift+F12,搜索"signatures",如果有就毋庸置疑了,我们并不关心他是怎样的逻辑,我们关心的只是他的返回值,直接找到返回值v4
可以看出如果v4等于0的时候那么肯定就是错误的逻辑,我们只需要让v4变量的初始化值为1或者直接修改返回值为1,这里我们采用第二种方式,回到汇编处
CMP R0,#0 这句话就是比较R0寄存器(sub_15C0的返回值)的值如果为0则跳转到BEQ对应的函数地址,我们直接将R0寄存器值改为1,其汇编就是CMP R0,#1,找到对应的16进制3DD8
使用010编辑器打开当前so文件,Ctrl+G跳转到该函数地址处,将00直接改成01,之后保存修改
再次打开so文件查看修改后的结果。
将修改后的so文件放到demo中请求,得到结果如下:
成功获取到结果
文章仅供学习交流,禁止一切商务用途。
网友评论