so函数Hook(上)

xiaoeryu Lv5

Xposed插件开发之对so中函数的处理

对so中函数的hook跟对java层函数的hook不同,Xposed无法完成对so层函数的hook。需要使用其它的框架编写so层的hook代码,然后通过xposed进行主动调用的方式来完成hook。

这里我们先以32位为例,使用inlineHook框架 ,不过这个框架只能hook 32位的app

先来创建一个包含有so库的native C++项目,作为目标app

  • 这里strstr方法默认返回的是false,如果我们想通过hook让它的返回结果为true,有几个hook点

    1. hookstrstr()让其在遇到hookso的时候返回的结果为非空
    2. 修改testhook()的参数、或者直接修改返回值
  • 对libC函数的hook要注意一点,hook时机要在目标函数调用前

hook strstr()

对于native-lib.cpp的加载是通过System.loadLibrary()来进行加载的

  • 就是说当这个函数返回的时候这个文件生成的so文件就已经加载进入到内存里面了,但是此时还没有执行到stringFromJNI(),自然也就还没有执行到我们写的方法。
  • 那么我们就可以使用Xposed框架首先完成对System.loadLibrary()的hook,然后再写一个so文件对目标so进行hook
  • 在我们hook到System.loadLibrary()函数执行,但是目标函数还没有执行到的时候加载我们的so文件对目标so中的函数进行hook

hookSystem.loadLibrary(),加载so

这个脚本大体上跟之前差不多

public class XposedHookSo implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable{
        Log.i("XposedHookSo", loadPackageParam.packageName);
        XposedBridge.log("XposedHookSo->app packagename" + loadPackageParam.packageName);
        if (loadPackageParam.packageName.equals("com.xiaoeryu.xposedhookso")){
            XposedBridge.log("XposedHookSo" + loadPackageParam.packageName);
            XposedHelpers.findAndHookMethod("java.lang.Runtime", loadPackageParam.classLoader, "loadLibrary0", ClassLoader.class, String.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    String soname =  (String) param.args[1];
                    XposedBridge.log("beforeHookedMethod Runtime.loadLibrary0(" + soname + "," + param.args[0] + ")");
                }
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    String soname =  (String) param.args[1];
                    XposedBridge.log("afterHookedMethod Runtime.loadLibrary0("+soname+")");

                    // 在loadLibrary0执行完成后,主动调用我们的so文件
                    if (soname.contains("native-lib")){
//                        System.loadLibrary("native-lib");
                        System.load("/data/data/com.xiaoeryu.xposedhookso/files/hookso.so");
                    }
                }
            });
        }
    }
}
  • 通过xposedhookloadLibrary0监测到目标so被加载进内存之后,就主动调用我们的hookso

  • loadLibrary函数在6.1之后的版本中变为了loadLibrary0,参数顺序也有变化

    6.0.1
    public static void loadLibrary(String libName) {
        Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
    }
    
    8.1
    public static void loadLibrary(String libname) {
        Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), libname);
    }
    

编写so hook插件

将框架的源码下载下来解压,把源码拷贝到cpp项目的cpp目录下方便调用

修改CMakeLists.txt文件,把要使用的文件添加进去

接下来我们需要编写so层的hook代码

可以按照框架给的示例来稍微修改一下就可以了

  • 这里先创建一个指针来保存原来的函数,然后再创建一个指针来保存替换的函数,可以在替换函数中调用原函数的指针
创建一个新的native C++项目在native-lib.cpp中写入hookstrstr方法的代码

写完之后调试一下看看是否能拿到目标函数地址

  • 可以看到成功的拿到了so的地址和目标函数的地址

运行让它跑起来

  • 结果显示成功的hook了strstr

  • 然后编译成apk

  • 解压apk,拿出里面编译好的so文件

将刚刚写好的目标app安装在设备上

此时,我们对它进行hook之前它的运行结果

将编译好的libhookso.so文件pull到Xposed主动加载的目录下

  • 修改libhookso.so文件的名字为hookso.so
  • 修改后将其pull到此设备的这个目录下
  • 然后使用命令chmod 777 hookso.so给予文件执行权限
然后安装Xposed插件,重启设备运行目标app

运行后如果hook成功就会改变我们目标app中so文件的执行结果

总结:对32位低版本安卓进行so hook还是比较简单的,直接写Xposed加载我们使用inlineHook框架编写的so文件去hook目标app中的so函数就可以了

  • 标题: so函数Hook(上)
  • 作者: xiaoeryu
  • 创建于 : 2023-12-25 00:37:44
  • 更新于 : 2024-01-13 20:56:27
  • 链接: https://github.com/xiaoeryu/2023/12/25/so函数Hook(上)/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论