26
2023-6
今天距2024年188天
这是鸣谦安全第153次推文
点击上方蓝字“鸣谦安全“关注我,周二,周五,每晚 19:00准时推送。
微信公众号后台回复“资源”领取学习资料,回复“QQ群”一起进群学习闲聊。
本文2507字,阅读约需5分钟
文章首发于奇安信攻防社区:https://forum.butian.net/share/2248
由于 Xposed 是系统级,所以 hook 的时机是很早,当 hook 加固的应用时会出现 hook 不到的情况。本文采用三种方法,从根本上解决了这一问题。
应用被加固 Xposed 是 hook 不到的
测试的是一个不良 App,名字是 移动TV。
要用 Xposed hook 的类是 com.cz.babySister.activity.MainActivity。
首先用 objection search 一下这个类,看是否存在。
1objection -g com.cz.babySister explore
2android hooking search classes com.cz.babySister.activity.MainActivity
通过从内存里面查找,发现 com.cz.babySister.activity.MainActivity 类是的的确确存在的。
那么既然这个类存在,用 Xposed hook 应该就可以 hook 的到。
编写 Xposed hook 代码:
1package com.bmstd.xposed1;
2
3import de.robv.android.xposed.IXposedHookLoadPackage;
4import de.robv.android.xposed.XC_MethodHook;
5import de.robv.android.xposed.XposedBridge;
6import de.robv.android.xposed.XposedHelpers;
7import de.robv.android.xposed.callbacks.XC_LoadPackage;
8
9public class HookTest implements IXposedHookLoadPackage {
10
11 @Override
12 public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
13 if (loadPackageParam.packageName.equals("com.cz.babySister")) {
14 Class<?> aClass = XposedHelpers.findClass("com.cz.babySister.activity.MainActivity", loadPackageParam.classLoader);
15 XposedBridge.hookAllMethods(aClass, "onCreate", new XC_MethodHook() {
16 @Override
17 protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
18 super.beforeHookedMethod(param);
19 XposedBridge.log("MainActivity onCreate called");
20 }
21 });
22 }
23 }
24}
发现会一直触发 java.lang.ClassNotFoundException 类找不到的异常。
将 App 进行静态分析,拖入 GDA 中,发现这是一个加了壳的 App ,进行了腾讯加固。
所以,由于 Xposed 是系统级别 hook 框架,Xposed 注入的时机是很早的,而壳程序总是又较 App 应用程序最先执行的,所以 Xposed hook 默认使用的是壳的 ClassLoader 而不是应用本身的 ClassLoader,所以是不可能 hook 到应用内部的代码的。
这就将问题转换为,如何转换 ClassLoader。
基本原理
要使用 Xposed hook 加固的应用分为三步
1. 是拿到加载应用本身 dex 的 ClassLoader
2.是通过这个 ClassLoader 去找到被加固的类
3.是通过这个类去 hook 需要 hook 的方法
从多dex hook不到的问题角度解决
现在很多的 app 都有多个 dex 文件,因为谷歌规定单个 dex 文件中的方法不能超过 65536 个。
如果代码太多的话必须拆分 dex。如果用 Xposed 去 hook 非默认 dex 文件的类就会发生 ClassNotFoundError。
要解决这个问题,需要拿到对应 dex 文件的上下文环境。
android 在加载 dex 文件后会创建一个 Application 类,然后会调用 attach 方法,attach 方法的参数就是上下文 context。
而且 attach 方法是 final 方法,不会因为被覆盖而 hook 不到,拿到这个 context 就可以获取对应的 classloader,然后可以顺利 hook 到需要的类。
根据上面的思路,编写代码:
1package com.bmstd.xposed1;
2
3import android.app.Application;
4import android.content.Context;
5
6import de.robv.android.xposed.IXposedHookLoadPackage;
7import de.robv.android.xposed.XC_MethodHook;
8import de.robv.android.xposed.XposedBridge;
9import de.robv.android.xposed.XposedHelpers;
10import de.robv.android.xposed.callbacks.XC_LoadPackage;
11
12public class HookTest implements IXposedHookLoadPackage {
13
14 @Override
15 public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
16 if (loadPackageParam.packageName.equals("com.cz.babySister")) {
17 // 解决多dex文件hook不到问题
18 XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class,
19 new XC_MethodHook() {
20 @Override
21 protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
22 super.beforeHookedMethod(param);
23 // 获取上下文
24 Context context = (Context) param.args[0];
25 XposedBridge.log("context => " + context);
26 // 类加载器
27 ClassLoader classLoader = context.getClassLoader();
28 XposedBridge.log("classLoader => " + classLoader);
29
30 // 替换类加载器进行 hook 对应的方法
31 Class<?> aClass = XposedHelpers.findClass("com.cz.babySister.activity.MainActivity", classLoader);
32 XposedBridge.hookAllMethods(aClass, "onCreate", new XC_MethodHook() {
33 @Override
34 protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
35 super.beforeHookedMethod(param);
36 XposedBridge.log("MainActivity onCreate called");
37 }
38 });
39 }
40 });
41 }
42 }
43}
执行代码后,可以看到首先进入了壳的 context ,然后获取到了壳的 ClassLoader。
等正式进入 App 后,android 会重新加载 App 本身 dex 文件,会创建一个 Application 类,然后会调用 attach 方法,attach 方法的参数就是上下文 context。通过这个 context 获取到的就是 App 本身的 ClassLoader 了。
在通过这个 ClassLoader 找到要 hook 的类,执行后的结果就是成功 hook 到类中的方法。
从动态加载dex hook不到的问题角度解决
从上面的理论分析得知,重点问题还是在 ClassLoader 的切换。
所以直接使用 java.lang.ClassLoader.loadClass(java.lang.String) 这个方法。
这个方法的功能是:加载具有指定二进制名称的类,成功,然后一个类的对象。
根据上面的思路,编写代码:
1package com.bmstd.xposed1;
2
3import de.robv.android.xposed.IXposedHookLoadPackage;
4import de.robv.android.xposed.XC_MethodHook;
5import de.robv.android.xposed.XposedBridge;
6import de.robv.android.xposed.XposedHelpers;
7import de.robv.android.xposed.callbacks.XC_LoadPackage;
8
9public class HookTest implements IXposedHookLoadPackage {
10 @Override
11 public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
12 if (loadPackageParam.packageName.equals("com.cz.babySister")) {
13 XposedBridge.log("has hooked!");
14 // 解决动态加载dex文件hook不到问题
15 XposedHelpers.findAndHookMethod(ClassLoader.class,
16 "loadClass",
17 String.class,
18 new XC_MethodHook() {
19 @Override
20 protected void afterHookedMethod(MethodHookParam param) throws Throwable {
21 super.afterHookedMethod(param);
22 // 打印当前已经加载的类
23 XposedBridge.log("clazz => " + param.getResult());
24 Class<?> clazz = (Class<?>) param.getResult();
25 if (clazz != null && clazz.getName().equals("com.cz.babySister.activity.MainActivity")) {
26 XposedBridge.hookAllMethods(clazz, "onCreate", new XC_MethodHook() {
27 @Override
28 protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
29 super.beforeHookedMethod(param);
30 XposedBridge.log("MainActivity onCreate called");
31 }
32 });
33 }
34 }
35 });
36 }
37 }
38}
执行代码后,首先找到了壳的类。
然后陆续找到了所有类,并成功进行预想中的 hook 。
从应用加载角度解决
App 是通过 Zygote 进程孵化的,通过 ActivityThread.main() 进入 App 。
performLaunchActivity() 函数用于响应 Activity 的操作。
并且 ActivityThread 类中还存在 Application 类型的 mInitialApplication。
mInitialApplication 可以获得当前的 ClassLoader。
根据上面的思路,编写代码:
1package com.bmstd.xposed1;
2
3import android.app.Application;
4
5import de.robv.android.xposed.IXposedHookLoadPackage;
6import de.robv.android.xposed.XC_MethodHook;
7import de.robv.android.xposed.XposedBridge;
8import de.robv.android.xposed.XposedHelpers;
9import de.robv.android.xposed.callbacks.XC_LoadPackage;
10
11public class HookTest implements IXposedHookLoadPackage {
12 @Override
13 public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
14 if (loadPackageParam.packageName.equals("com.cz.babySister")) {
15 Class ActivityThread = XposedHelpers.findClass("android.app.ActivityThread", loadPackageParam.classLoader);
16 XposedBridge.hookAllMethods(ActivityThread, "performLaunchActivity", new XC_MethodHook() {
17 @Override
18 protected void afterHookedMethod(MethodHookParam param) throws Throwable {
19 Application mInitialApplication = (Application) XposedHelpers.getObjectField(param.thisObject, "mInitialApplication");
20 ClassLoader finalClassloader = mInitialApplication.getClassLoader();
21 XposedBridge.log("found classload is => " + finalClassloader.toString());
22 Class<?> MainActivity = XposedHelpers.findClass("com.cz.babySister.activity.MainActivity", finalClassloader);
23 XposedBridge.hookAllMethods(MainActivity, "onCreate", new XC_MethodHook() {
24 @Override
25 protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
26 super.beforeHookedMethod(param);
27 XposedBridge.log("MainActivity onCreate called");
28 }
29 });
30 }
31 });
32 }
33 }
34}
再次成功完成 hook 。
敬请期待
回复"QQ群"一起闲聊
个人微信:bmstd6
添加请注明来意
原文始发于微信公众号(鸣谦安全):解决Xposed hook不到加固的应用问题
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论