图/文 h_one
原理:大部分逆向工具都是线性读取字节码并解析, 如dex2jar,baksmali,apktool等,当遇到无效字节码时,就会引起反编译工具解析失败。
例如:新版的dex2jar 遇到这种情况任然没法转化成jar,在新版本的baksmail和apktool已修复此问题。
010editor查看,红色框中就是加入的陷阱类,绕过方法很简单,只要将这个三个类删除,重编译即可
在Android4.2.x前的一种保护方 式,通过APK(压缩文件)进行伪加密,其修改原理是修改连续4位字节标记为“P K 01 02”后的第5字节(ps:一般在文件末尾有多处),奇数表示加密偶数不加密,这种保护方式一般只会出现在一些cm里,因为:
1.对系统不兼容;
2.伪加密 处理后的apk市场也无法对其进行安全检测,部分市场会拒绝这类APK上传市场
Android平台对文件名的长度是没有限制的,但是操作系统要求不能大于255;于是可以构建超长字符的类名达到反编译错误目的。
目的:防止/检测二次打包
android在解析AXML文件时,是用属性的资源id,而不是资源名,当android系统遇到非法资源id时,并不会做解析,所以可以对axml文件解析,添加无用的属性。但是对于破解者来说,一般会在Java层增加log信息,然后打包apk,
此时如apktool之类的逆向工具,就会无法解析无效属性,或进入trap类(检测二次打包)
目的:为了保护关键代码被逆向分析,一般放在应用程序初始化过程中,如init_array,或jni_onload函数里进行检查代码执行。、
对调试器的检测(ida,gdb,strace,
ltrace,android_server等调试工具)
例如,对android_server进程检测。针对这种检测只需将android_server改名就可绕过
[objc] view plain copy
State属性值T 表示调试状态,TracerPid 属性值正在调试此进程的pid,在非调试情况下State为S或R, TracerPid等于0
下图中第一个红色框值为非调试状态值,第二个红色框值为调试状态值:
[objc] view plain copy
ptrace 自身或者fork子进程相互ptrace(梆梆加固之类的反调试)
[objc] view plain copy
利用Inotify机制,对/proc/pid/mem和/proc/pid/pagemap文件进行监视。inotify
API提供了监视文件系统的事件机制,可用于监视个体文件,或者监控目录。具体原理可参考:http://man7.org/linux/man- pages/man7/inotify.7.html
伪代码:
[objc] view plain copy
对read做hook
因为一般的内存dump都会调用到read函数,所以对read做内存hook,检测read数据是否在自己需要保护的空间来阻止dump
[objc] view plain copy
用户层行为和数据检测,模拟器特有属性值,以及模拟器体系结构特征
hook代码肯定是在app自身模块加载之前运行的,那么在app的maps表里会首先加载hook框架的dex,我们只要对此dex做简单的校验,就会检测到app被注入了。
编码思路:
遍历maps表,查看子串是否存在“apk@classes.dex”的字符串,若存在--获取该模块的startAddr和endAddr, 然后检验此odex的头部是否为真正的dex文件。
STDFD保存寄存器值到栈上,LDMFD将栈上数据赋值到寄存器中,这个过程修改了函数返回的地址。
hook检测点(path检测点的函数代码,函数返回值修改等),修改源码(改变字段属性主要针对模拟器仿真,修改函数返回值,例如绕过签名校验等)
eg:
ida patch 线程退出函数: patch 地址48D9668A处的函数调用
00 00 0A EF (movs R0, R0)
由于/proc/pid/status,/proc/pid/wchan,/proc/pid/mem等都是针对文件状态的检测,入口点函数一般都为fopen,
我们可以事先拦截fopen,查看app是否有这方面的防护。
以某某app为例:如下图此app fopen了这些文件,我们就能猜测这是对调试检测。
绕过方法:在指定目录下(/data/local/tmp)新建一文件alimolisec,
hook fopen函数检测到文件名子串有/proc/self时,就重定位打开alimolisec文件
[objc] view plain copy
1.不替换源classes.dex,也没有做任何加密的处理,对classes.dex中的Activity,service, receiver等的oncreate,onReceive加密替换,壳首先拿到执行权,在自身so里完成对源dex还原。
2.不替换源classes.dex,也没有做任何加密的处理,
修改原Dex的Class_Data,将MyContentProvider,Application,Activity,service类的入口函数 onCreate方法标记为native方法,但是原始字节码仍然未加密保存在dex文件中。
3.对classes.dex整包加密,使用壳加载器内存解密classes.dex并替换原始成源classes.dex
4.对classes.dex整包加密,并将原dex拆分成两部分,在内存中分两块区域存储(阿里移动安全比赛加固)。
1.对部分整包加密的可以通过运行时内存dump,部分通过拦截dvmDexFileOpenPartial函数即可获取完整dex。(dex连续)
2.对于修改了dex的Class_data和classes.dex做了拆分的,可以通过找到dex对应的pDvmDex结构,重建dex(dex不连续或不完整的)
▏cydia substrate
原理:框架注入zygote进程,采用inline hook(
修改目标函数前N字节,跳转到自定义函数入口,备份目标函数前N个字节,跳转回目标函数)
▏Xposed
原理:替换app_process,将需要hook的java函数替换成JNI函数,所有需要HOOK的函数首先由xposedCallHandler处理,xposedCallHandler负责调用注册的beforeHookMethod和afterHookedMethod函数
▏adbi
原理:利用ptrace()函数attach到一个进程上,然后在其调用序列中插入一个调用dlopen()函数的步骤,将一个事先预先备好的.so文件加载到要hook的进程内存中,最终由这个加载的.so文件在初始化函数中hook指定的函数。
http://man7.org/linux/man-pages/man7/inotify.7.html
http://www.dexlabs.org/blog/btdetect
https://bluebox.com/technical/android-emulator-detection-by-observing-low-level-caching-behavior/
https://github.com/crmulliner/adbi
手机扫一扫
移动阅读更方便
你可能感兴趣的文章