解决Xposed hook不到加固的应用问题

由于 Xposed 是系统级,所以 hook 的时机是很早,当 hook 加固的应用时会出现 hook 不到的情况。本文采用三种方法,从根本上解决了这一问题。

解决Xposed hook不到加固的应用问题

应用被加固 Xposed 是 hook 不到的

测试的是一个不良 App,名字是 移动TV。

要用 Xposed hook 的类是 com.cz.babySister.activity.MainActivity。

首先用 objection search 一下这个类,看是否存在。

  1. objection -g com.cz.babySister explore
  2. android hooking search classes com.cz.babySister.activity.MainActivity

1.png

通过从内存里面查找,发现 com.cz.babySister.activity.MainActivity 类是的的确确存在的。

那么既然这个类存在,用 Xposed hook 应该就可以 hook 的到。

编写 Xposed hook 代码:

  1. package com.bmstd.xposed1;
  2. import de.robv.android.xposed.IXposedHookLoadPackage;
  3. import de.robv.android.xposed.XC_MethodHook;
  4. import de.robv.android.xposed.XposedBridge;
  5. import de.robv.android.xposed.XposedHelpers;
  6. import de.robv.android.xposed.callbacks.XC_LoadPackage;
  7. public class HookTest implements IXposedHookLoadPackage {
  8. @Override
  9. public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
  10. if (loadPackageParam.packageName.equals("com.cz.babySister")) {
  11. Class<?> aClass = XposedHelpers.findClass("com.cz.babySister.activity.MainActivity", loadPackageParam.classLoader);
  12. XposedBridge.hookAllMethods(aClass, "onCreate", new XC_MethodHook() {
  13. @Override
  14. protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  15. super.beforeHookedMethod(param);
  16. XposedBridge.log("MainActivity onCreate called");
  17. }
  18. });
  19. }
  20. }
  21. }

发现会一直触发 java.lang.ClassNotFoundException 类找不到的异常。

2.png

将 App 进行静态分析,拖入 GDA 中,发现这是一个加了壳的 App ,进行了腾讯加固。

3.png

所以,由于 Xposed 是系统级别 hook 框架,Xposed 注入的时机是很早的,而壳程序总是又较 App 应用程序最先执行的,所以 Xposed hook 默认使用的是壳的 ClassLoader 而不是应用本身的 ClassLoader,所以是不可能 hook 到应用内部的代码的。

这就将问题转换为,如何转换 ClassLoader。

基本原理

要使用 Xposed hook 加固的应用分为三步

  1. 是拿到加载应用本身 dex 的 ClassLoader
  2. 是通过这个 ClassLoader 去找到被加固的类
  3. 是通过这个类去 hook 需要 hook 的方法

从多dex hook不到的问题角度去解决 Xposed hook 不到加固的应用

现在很多的 app 都有多个 dex 文件,因为谷歌规定单个 dex 文件中的方法不能超过 65536 个。

如果代码太多的话必须拆分 dex。如果用 Xposed 去 hook 非默认 dex 文件的类就会发生 ClassNotFoundError。

要解决这个问题,需要拿到对应 dex 文件的上下文环境。

android 在加载 dex 文件后会创建一个 Application 类,然后会调用 attach 方法,attach 方法的参数就是上下文 context。

4.png

而且 attach 方法是 final 方法,不会因为被覆盖而 hook 不到,拿到这个 context 就可以获取对应的 classloader,然后可以顺利 hook 到需要的类。

根据上面的思路,编写代码:

  1. package com.bmstd.xposed1;
  2. import android.app.Application;
  3. import android.content.Context;
  4. import de.robv.android.xposed.IXposedHookLoadPackage;
  5. import de.robv.android.xposed.XC_MethodHook;
  6. import de.robv.android.xposed.XposedBridge;
  7. import de.robv.android.xposed.XposedHelpers;
  8. import de.robv.android.xposed.callbacks.XC_LoadPackage;
  9. public 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. // 解决多dex文件hook不到问题
  14. XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class,
  15. new XC_MethodHook() {
  16. @Override
  17. protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  18. super.beforeHookedMethod(param);
  19. // 获取上下文
  20. Context context = (Context) param.args[0];
  21. XposedBridge.log("context => " + context);
  22. // 类加载器
  23. ClassLoader classLoader = context.getClassLoader();
  24. XposedBridge.log("classLoader => " + classLoader);
  25. // 替换类加载器进行 hook 对应的方法
  26. Class<?> aClass = XposedHelpers.findClass("com.cz.babySister.activity.MainActivity", classLoader);
  27. XposedBridge.hookAllMethods(aClass, "onCreate", new XC_MethodHook() {
  28. @Override
  29. protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  30. super.beforeHookedMethod(param);
  31. XposedBridge.log("MainActivity onCreate called");
  32. }
  33. });
  34. }
  35. });
  36. }
  37. }
  38. }

执行代码后,可以看到首先进入了壳的 context ,然后获取到了壳的 ClassLoader。

5.png

等正式进入 App 后,android 会重新加载 App 本身 dex 文件,会创建一个 Application 类,然后会调用 attach 方法,attach 方法的参数就是上下文 context。通过这个 context 获取到的就是 App 本身的 ClassLoader 了。

在通过这个 ClassLoader 找到要 hook 的类,执行后的结果就是成功 hook 到类中的方法。

6.png

从动态加载dex hook不到的问题角度去解决 Xposed hook 不到加固的应用

从上面的理论分析得知,重点问题还是在 ClassLoader 的切换。

所以直接使用 java.lang.ClassLoader.loadClass(java.lang.String) 这个方法。

这个方法的功能是:加载具有指定二进制名称的类,成功,然后一个类的对象。

7.png

根据上面的思路,编写代码:

  1. package com.bmstd.xposed1;
  2. import de.robv.android.xposed.IXposedHookLoadPackage;
  3. import de.robv.android.xposed.XC_MethodHook;
  4. import de.robv.android.xposed.XposedBridge;
  5. import de.robv.android.xposed.XposedHelpers;
  6. import de.robv.android.xposed.callbacks.XC_LoadPackage;
  7. public class HookTest implements IXposedHookLoadPackage {
  8. @Override
  9. public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
  10. if (loadPackageParam.packageName.equals("com.cz.babySister")) {
  11. XposedBridge.log("has hooked!");
  12. // 解决动态加载dex文件hook不到问题
  13. XposedHelpers.findAndHookMethod(ClassLoader.class,
  14. "loadClass",
  15. String.class,
  16. new XC_MethodHook() {
  17. @Override
  18. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  19. super.afterHookedMethod(param);
  20. // 打印当前已经加载的类
  21. XposedBridge.log("clazz => " + param.getResult());
  22. Class<?> clazz = (Class<?>) param.getResult();
  23. if (clazz != null &amp;&amp; clazz.getName().equals("com.cz.babySister.activity.MainActivity")) {
  24. XposedBridge.hookAllMethods(clazz, "onCreate", new XC_MethodHook() {
  25. @Override
  26. protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  27. super.beforeHookedMethod(param);
  28. XposedBridge.log("MainActivity onCreate called");
  29. }
  30. });
  31. }
  32. }
  33. });
  34. }
  35. }
  36. }

执行代码后,首先找到了壳的类。

8.png

然后陆续找到了所有类,并成功进行预想中的 hook 。

9.png

从应用加载角度解决 Xposed hook 不到加固的应用

App 是通过 Zygote 进程孵化的,通过 ActivityThread.main() 进入 App 。

performLaunchActivity() 函数用于响应 Activity 的操作。

并且 ActivityThread 类中还存在 Application 类型的 mInitialApplication。

10.png

mInitialApplication 可以获得当前的 ClassLoader。

根据上面的思路,编写代码:

  1. package com.bmstd.xposed1;
  2. import android.app.Application;
  3. import de.robv.android.xposed.IXposedHookLoadPackage;
  4. import de.robv.android.xposed.XC_MethodHook;
  5. import de.robv.android.xposed.XposedBridge;
  6. import de.robv.android.xposed.XposedHelpers;
  7. import de.robv.android.xposed.callbacks.XC_LoadPackage;
  8. public class HookTest implements IXposedHookLoadPackage {
  9. @Override
  10. public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
  11. if (loadPackageParam.packageName.equals("com.cz.babySister")) {
  12. Class ActivityThread = XposedHelpers.findClass("android.app.ActivityThread", loadPackageParam.classLoader);
  13. XposedBridge.hookAllMethods(ActivityThread, "performLaunchActivity", new XC_MethodHook() {
  14. @Override
  15. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  16. Application mInitialApplication = (Application) XposedHelpers.getObjectField(param.thisObject, "mInitialApplication");
  17. ClassLoader finalClassloader = mInitialApplication.getClassLoader();
  18. XposedBridge.log("found classload is => " + finalClassloader.toString());
  19. Class<?> MainActivity = XposedHelpers.findClass("com.cz.babySister.activity.MainActivity", finalClassloader);
  20. XposedBridge.hookAllMethods(MainActivity, "onCreate", new XC_MethodHook() {
  21. @Override
  22. protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  23. super.beforeHookedMethod(param);
  24. XposedBridge.log("MainActivity onCreate called");
  25. }
  26. });
  27. }
  28. });
  29. }
  30. }
  31. }

再次成功完成 hook 。

11.png

  • 发表于 2023-05-04 09:00:02
  • 阅读 ( 9921 )
  • 分类:漏洞分析

2 条评论

bmstd
bmstd

13 篇文章

站长统计