Androidhook原理及APP安全
Xposed原理
如何保证APP最安全。
这篇⽂章不对逆向和hook进⾏分析,如有不知道的,请看我之前的⽂章。
介绍:
刷机包解压打开⾥⾯的问件构成是这个样⼦的:
META-INF/ ⾥⾯有⽂件配置脚本 flash-script.sh 配置各个⽂件安装位置。
system/bin/ 替换zygote进程等⽂件
system/framework/XposedBridge.jar jar包位置
system/lib system/lib64 ⼀些so⽂件所在位置
xposed.prop xposed版本说明⽂件
所以安装Xposed的过程就上把上⾯这些⽂件放到⼿机⾥相同⽂件路径下。
通过查看⽂件安装脚本发现:
system/bin/下⾯的⽂件替换了app_process等⽂件,app_process就是zygote进程⽂件。所以Xposed通过替换zygote进程实现了控制⼿机上所有app进程。因为所有app进程都是由Zygote fork出来的。
Xposed的基本原理是修改了ART/Davilk虚拟机,将需要hook的函数注册为Native层函数。当执⾏到这⼀函数是虚拟机会优先执⾏Native层函数,然后再去执⾏Java层函数,这样完成函数的hook。
通过读Xposed源码发现其启动过程:
1、⼿机启动时init进程会启动zygote这个进程。由于zygote进程⽂件app_process已被替换,所以启动的时Xposed版的zygote进程。
2、Xposed_zygote进程启动后会初始化⼀些so⽂件(system/lib system/lib64),然后进⼊XposedBridge.jar中的XposedBridge.main中初始化jar包完成对⼀些关键Android系统函数的hook。
3、Hook则是利⽤修改过的虚拟机将函数注册为native函数。
4、然后再返回zygote中完成原本zygote需要做的⼯作。
hook流程:
Xposed
Installer框架中真正起作⽤的是对⽅法的Hook和Replace。在Android系统启动的时候,Zygote进程加
载XposedBridge.jar,将所有需要替换的Method通过JNI⽅法hookMethodNative指向Native⽅法xposedCallHandler,这个⽅法再通过调⽤
handleHookedMethod这个Java⽅法来调⽤被劫持的⽅法转⼊Hook逻辑。
上⾯提到的hookMethodNative是XposedBridge.jar中的私有的本地⽅法,它将⼀个⽅法对象作为传⼊参数并修改Dalvik虚拟机中对于该⽅法的定义,把该⽅法的类型改变为Native并将其实现指向另外⼀个B⽅法。
换⾔之,当调⽤那个被Hook的A⽅法时,其实调⽤的是B⽅法,调⽤者是不知道的。在hookMethodNative的实现中,会调⽤XposedBridge.jar中的handleHookedMethod这个⽅法来传递参数。handleHookedMethod这个⽅法类似于⼀个统⼀调度的Dispatch例程,其对应的底层的C++函数是xposedCallHandler。⽽handleHookedMethod实现⾥⾯会根据⼀个全局结构
hookedMethodCallbacks来选择相应的Hook函数并调⽤他们的before和after函数,当多模块同时Hook⼀个⽅法的时候Xposed会⾃动根据Module的优先级来排序。
调⽤顺序如下:A.before -> B.before -> original method -> B.after -> A.after
总结:
1、替换/system/bin/app_process程序控制zygote进程,使⽤xposed版zygote,然后加载刷机包的so⽂件,然后初始化xposed.jar包的main⽅法,先对Android系统函数进⾏hook。然后再返回zygote中完成原本zygote需要做的⼯作。 app中hook则是先修改虚拟机,然后将⽅法改为native⽅法,然后进⾏hook
2、当我们在hook⼀个⽅法的,⾸先是xposed.jar的hookMethodNative⽅法,通过传⼊的⽅法参数信息,修改虚拟机的定义改为Native ⽅法。 从⽽进⾏hook处理
如何保证我们APP的安全性
⼀、检测Hook的⽅法:
① 通过PackageManager查看安装列表
最简单的检测,我们调⽤Android提供的PackageManager的API来遍历系统中App的安装情况来辨别是否有安装Xposed Installer相关的软件包
PackageManager packageManager = PackageManager();
List applicationInfoList = InstalledApplications(PackageManager.GET_META_DATA);
for (ApplicationInfo applicationInfo: applicationInfoList) {
if (applicationInfo.packageName.equals("de.robv.android.xposed.installer")) {
// is }
}
② ⾃造异常读取栈
try {
throw new Exception("blah");
} catch(Exception e) {
for (StackTraceElement stackTraceElement: e.getStackTrace()) {
// ClassName() MethodName() 是否存在Xposed
}
}
E/GEnvironment: no such table: preference (code 1): while compiling: SELECT keyguard_show_livewallpaper FROM preference
...
package.ExtPackageManager.checkUpdate(ExtPackageManager.java:127)
st.MiFGService$1.run(MiFGService.java:41)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5072)
at flect.Method.invokeNative(Native Method)
at flect.Method.invoke(Method.java:515)
...
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
bv.android.xposed.XposedBridge.main(XposedBridge.java:132) //发现Xposed模块
at dalvik.system.NativeStart.main(Native Method)
③ 检查关键Java⽅法被变为Native JNI⽅法
刚上⾯我说过了,xposed在hook的时候会把你这个⽅法改为Native JNI⽅法,可以利⽤这个检测:(觉得⽐较重要的⽅法)
通过反射调⽤Modifier.Modifiers())⽅法可以校验⽅法是不是Native JNI⽅法,Xposed同样可以篡改isNative这个⽅法的返回值。
④ 反射读取XposedHelper类字段,Xposed框架将Hook信息存储在字段fieldCache,methodCache,constructorCache 中, 利⽤java 反射机制获取这些信息,检测Hook信息中是否含有你们App中敏感的⽅法,字段,构造⽅法
boolean methodCache = CheckHook(clsXposedHelper, "methodCache", keyWord);
private static boolean CheckHook(Object cls, String filedName, String str) {
boolean result = false;
String interName;
Set keySet;
try {
Field filed = Class().getDeclaredField(filedName);
filed.setAccessible(true);
keySet = (cls)).keySet();
if (!keySet.isEmpty()) {
for (Object aKeySet: keySet) {
interName = String().toLowerCase();
if (ains("⾃⼰APP信息") || ains("⽐如⽀付宝") ) {
result = true;
break;
}
}
}
...
return result;
}
Native层检测
由上⽂可知,⽆论在Java层做何种检测,Xposed都可以通过Hook相关的API并返回指定的结果来绕过检测,只要有⽅法就可以被Hook。如果仅在Java层检测就显得很徒劳,为了有效提搞检测准确率,就须做到Java和Native层同时检测。每个App在系统中都有对应的加载库列表,这些加载库列表在/proc/
下对应的pid/maps⽂件中描述,在Native层读取/proc/self/maps⽂件不失为检测Xposed Installer的有效办法之⼀。由于Xposed Installer通常只能Hook Java层,因此在Native层使⽤C来解析/proc/self/maps⽂件,搜检App⾃⾝加载的库中是否存在XposedBridge.jar、相关的Dex、Jar和So库等⽂件。
bool is_xposed()
{
bool rel = false;
FILE *fp = NULL;
char* filepath = "/proc/self/maps";
...
string xp_name = "XposedBridge.jar";
fp = fopen(filepath,"r"))
while (!feof(fp))
{
fgets(strLine,BUFFER_SIZE,fp);
origin_str = strLine;
str = trim(origin_str);
if (contain(str,xp_name))
{
rel = true; //检测到Xposed模块
break;
}
}
.
..
}
⼆、混淆永远都不可或缺
这个就不⽤多解释了
android获取真正的签名三、防⽌应⽤被抓包
调⽤api:
如果发现不为空那么就表⽰当前设备被挂代理了,那么就有可能被抓包的风险了
四、检测是否被调式:
这个也是借助系统的⼀个api来进⾏判断:android.os.Debug.isDebuggerConnected();
五、签名校验防护策略
第⼀:直接在本地做防护,如果发现签名不⼀致直接退出应⽤
第⼆:将签名信息携带请求参数中参与加密,服务端进⾏签名校验,失败就返回错误数据即可六、加固⽅案
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论