Android免Root权限Hook系统函数修改程序运行时内存指令逻辑

一、知识回顾

在之前一篇文章中,已经介绍了Android中如何修改内存指令改变方法执行逻辑,当时那篇文章的大致流程很简单,在程序运行起来,dex文件被加载到内存中之后,通过读取maps文件,获取到dex文件的内存起始地址,然后通过文件头信息找到指定dex在内存中的数据结构,这里还需要详细了解dex文件的格式,不了解的同学可以点击看这篇文章:Android中Dex文件格式解析,然后使用系统函数修改内存读写属性,在通过指定方法名找到该方法在内存的指令地址,然后替换即可。我们可以简单看一下dex文件被映射到内存之后的地址:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第1张图片


二、免root进行native层hook

上面的这种方案有一点不好就是,需要熟悉dex文件格式,然后通过方法名通过地址转化获取其内存对应的指令,操作有点繁琐,而本文将介绍一种简便的方式,修改起来非常简单。就是通过hook系统函数来做到这一点。而这种hook功能是免root的,所以只能hook应用内部逻辑。对其他应用程序没有任何效果,不过这个就已经满足本文操作的需求了,关于hook系统函数网上已经有现成的框架:Android-Inline-Hook;这个框架用法也非常简单。自己下载之后导入工程即可。下面来看看它的具体用法:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第2张图片

新建一个NDK工程,这个不多说了,然后把这几个框架中的文件拷贝到jni目录下,hook代码主要在InlineHook.cpp中:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第3张图片

这里看到我们会用到两个函数进行hook:

第一个是注册函数:registerInlineHook

参数:

    1、原始函数地址

    2、hook的新函数地址

    3、原始函数的二级指针

第二个是hook函数:inlineHook

参数:

    1、原始函数地址

这里为了演示效果,我们先Hook系统函数puts,需要在hook之前定义新函数以及旧函数的函数指针类型,这里一定要注意,新函数定义类型要和原始函数保持一致。不然hook失败的:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第4张图片

接下来,我们需要出发这个hook操作,我们可以在java层定义一个native方法,然后加载出发即可:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第5张图片

这里定义一个native方法了,然后用javah命令生成指定的头文件即可:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第6张图片

在native方法中开始进行hook操作,运行程序看日志信息即可:

640

看到了我们成功的hook了系统函数puts。接下来我们开始进入本文的正题了,如何hook系统函数来修改程序运行时态指令。


三、hook系统加载类函数

在上面的hook操作中可以看到,如果想hook一个函数,需要先找到这个函数的声明,所以第一步需要想好hook哪个系统函数,如何获取这个函数的声明?这个不难,因为我们想修改程序运行时态指令,那么肯定和dex加载解析过程分不开,这个就简单了,直接去 [Android源码/dalvik/libdex/] 下找到DexFile.h头文件,查看他的内部函数声明和一些数据结构定义信息:

640

我们发现了这个函数,为什么呢?因为我们知道一个方法执行之前肯定需要解析类信息加载到内存,而这个函数就是加载类必定运行的函数,在看看这个函数的声明:


返回值是DexClassDef结构体指针,看看DexClassDef定义结构体:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第7张图片

这个结构体描述了一个类的详细信息,每个字段在这里不多解释了,不了解的同学可以去看看之前介绍dex文件格式的那篇文章。这里关心的就是类代码数据的偏移地址,这个值在后面会用到,用它获取类代码结构体信息,后面会介绍。


两个参数是:

第一个参数:DexFile结构体指针

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第8张图片

这个结构体包括了整个类的全局信息。后面再获取其他结构体信息都会用到这个值。

第二个参数:是加载类的名称

这个参数在这里也非常重要,因为我们想修改一个方法的指令,肯定需要通过类去查找的,这个类名就非常重要了。


分析完了这个函数声明之后,下面就开始操作了hook了,不过还需要做两件事:

  • 第一件事:因为我们看到上面涉及到很多dex的结构体定义,所以我们需要手动的把这个系统头文件DexFile.h拷贝到我们的工程中,我们可以只保留一些有用的结构体定义和函数即可。

  • 第二件事:因为hook的时候需要原始函数地址的,所以这里我们需要利用系统函数dlopen和dlsym来获取指定函数的地址,关于这两个函数用法网上介绍的知识非常多了,这里不在详细介绍了,他们大致的功能就是可以通过函数名获取so文件中的函数地址。

这里要注意,为了获取正确的函数名称,我们需要导出设备中的libdvm.so文件,在设备的[/system/lib/libdvm.so]下,然后用IDA打开libdvm.so文件:

640

搜索dexFindClass函数名,然后查看他的代码位置,获取导出的函数名。


上面两件事完成之后,下面就可以开始hook操作了,操作过程和上面hook系统函数puts方式完全一样:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第9张图片

然后我们使用dlopen和dlsym函数获取正确的函数地址即可。

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第10张图片

hook触发逻辑,依然是之前定义的native方法:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第11张图片

到这里,我们还需要做一个操作,就是手动利用DexClassLoader来加载一个我们自己编写的dex文件,来看看hook是否成功了。所以我们还需要在构建一个工程:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第12张图片

这个工程非常简单,有一个核心的工具类,类中有一个计算方法:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第13张图片

我们的目的就是把这个方法的乘法改成加法操作。运行这个工程,获取dex文件,这里为了加载简单,直接把这个dex文件放到SD卡目录下,然后在回到上面的hook工程,需要在Java成编写一个加载dex文件的方法:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第14张图片

我们利用DexClassLoader加载之前将CoreDex工程编译获取的dex文件,然后加载类利用反射执行计算方法,传入的参数是2和3,正常结果是乘法也就是6,我们就要把乘法变成加法,让结果输出的是5。加载逻辑我们用一个点击事件来触发:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第15张图片

在回到native层中的hook代码:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第16张图片

这里主要看hook的新函数功能,过程有点复杂,这里一步一步来详细分析。首先我们需要过滤处理的类,不能把所有的类都做处理,然后通过原始函数,获取类的DexClassDef结构信息,然后利用系统函数dlsym调用函数dexReadAndVerifyClassData获取类对应的数据结构信息,这里依然需要用IDA打开libdvm.so文件查看这个函数的导出名称:

640

获取到类对应的数据结构DexClassData信息,之后就可以获取类中的方法个数和具体信息了,这里再来看一下DexClassData数据结构信息,这个结构体在DexClass.h中,我们依然把结构信息拷贝到我们的工程中即可:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第17张图片

有了这个结构体,下面就来获取方法的个数,这里的方法分为类方法和对象方法,在DexDataClassHeader结构体信息中。


这里利用系统函数dexGetClassData获取类的代码数据结构:640

接下来,继续看如何获取类中的方法信息:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第18张图片

因为我们知道那个calculateMoney方法是对象方法,所以这里直接获取对象方法结构体信息,然后依次遍历获取每个方法,通过系统函数dexGetMethodId获取DexMethodIds结构体信息:

640

这里需要注意的是每个方法都是在内存中依次挨着的,所以直接利用指针操作即可获取每个方法的结构体信息。然后在利用系统函数dexStringById获取方法名称,这个也是系统函数,一样方式拷贝到工程中来即可:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第19张图片

有了方法名就需要进行过滤了,只处理我们的那个calculateMoney方法,然后在获取方法对应的数据结构信息DexCode了,依然如此,我们需要把DexCode结构体信息从系统中拷贝到工程中:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第20张图片

然后利用系统函数dexGetCode通过DexMethod结构体获取DexCode结构体信息

640

有了DexCode结构体信息之后,我们可以打印方法的原始指令数据:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第21张图片

然后我们因为需要修改内存指令,所以还需要把内存修改为可读属性:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第22张图片

这里需要注意的是,修改的起始地址一定是系统内存页的整数倍,所以需要做一次转化。修改完内存属性之后。


四、修改指令逻辑

接下来就可以构造指令,然后替换内存指令即可。那么如何获取原始指令,怎么把乘法改成加法呢?这里就需要利用010Editor软件了,直接查看这个方法的指令数据:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第23张图片

这里看到,这个方法有三条指令,但是一条指令是两个字节,所以一共是6个字节,这里看到的是十进制的数据了,我们可以把这三个十进制数据转化成6个十六进制数据:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第24张图片

然后我们现在只需要把乘法指令码改成加法指令码即可,这个需要参考Bytecode of Dalvik了:

640

这里也看到加法指令就是十六进制的90,也就是十进制的144,所以咋们替换指令就简单了:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第25张图片

替换指令之后,在此打印指令数据即可,好了,到这里我们就完成了所有的操作了,下面就来运行看看日志信息了:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第26张图片

看到日志,我们成功的把指令146变成了144了,在往下看日志,就可以看到计算结果是加法了,也就是5:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第27张图片

就这样我们在内存中修改了这个方法的指令逻辑,把乘法逻辑变成了加法逻辑了。神奇吧。到这里我们也算介绍完了本文的大致内容了。不过有的同学可以看得没太明白,没关系,下面在来总结一下流程:


五、流程总结

首先明确我们的目的就是想能修改内存中指定方法的运行指令逻辑,那么不用之前介绍的那个读取内存中的dex数据然后靠地址来检索到指令地址,而是采用hook系统函数来实现:

第一步:就需要找到hook点,每个方法要想运行肯定是先将方法所属的类加载到内存中,那么就需要调用系统的函数:dexFindClass,而这个函数的返回值是一个DexClassDef结构体信息。

第二步:通过DexClassDef结构体信息获取类的数据结构体信息DexClassData,然后获取类的所有方法信息。

第三步:遍历方法结构体信息DexMethod,找到我们想要处理的方法信息,然后在获取其DexCode方法数据结构体信息。

第四步:有了方法数据结构体信息之后,就可以获取到方法的指令个数和具体指令数据,在修改之前必须修改内存属性为可读写的。

第五步:通过查阅虚拟机指令集,找到加法指令码替换原来的乘法指令码,然后覆盖内存中的原始指令即可。


所以在这个过程中发现,会涉及到很多数据结构体,不过好在这些结构体信息都定义在DexFile.h和DexClass.h这两个头文件中,他们存放在[Android源码/dalvik/libdex/]目录下。而这些结构体信息也是相互包含的,下面就来整理一下:

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第28张图片


严重说明

本文涉及到的代码工具可以去小密圈自取,为了安全考虑代码不进行公开,希望大家利用本文技术作为研发目的,绝不可以用于非法目的,否则后果自负与本文作者无任何关系!点击立即进入小密圈


六、总结

当然本文介绍完了之后,其实有一个很大的用途就是hook虚拟机的一些函数来做一些事情,其实说到这里本文并不是本次研究的重点,重点是下一篇文章,只是为了需要hook系统的函数,本文就先做个铺垫而已。聪明的人应该知道我下一篇文章要介绍啥了,而下一篇文章才是重点。篇幅原因,不得不将其内容拆分了。看文本文之后,一定要记得一点,不仅在java层可以免root进行hook操作,在native也是可以的。这个知识点对未来安全防护,逆向分析,应用开发都非常重要。

手机查看文章不方便,可以网页看

http://www.wjdiankong.cn



《Android应用安全防护和逆向分析》

点击查看图书详情

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第29张图片


长按下面??二维码,关注编码美丽


Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第30张图片


编码美丽小密圈

小密圈中汇集众神分享技术,所有源码、工具、破解样本、插件都汇集在小密圈中

---点击立即进入小密圈---


天若有情天亦老,我为逆向续一秒!猛戳下方"阅读原文",购买安全逆向图书!

Android免Root权限Hook系统函数修改程序运行时内存指令逻辑_第31张图片

你可能感兴趣的:(Android免Root权限Hook系统函数修改程序运行时内存指令逻辑)