Android内存修改
这个主要分为java层和so层的修改,java层基于反射,而so层的分类又分为两种,一种是不注入的修改,修改proc目录下的内容,而注入式就是我们的内存修改,也是比较常用。
so层修改
我们如果不修改代码段,仅仅是修改data段之类的是不需要修改属性页权限的。
实例代码:
1 | static int total = 0; |
就是一个简单的数据累加,我们的目的就是可以随意修改静态变量。
首先我们需要先找到这个变量的相对偏移,首先我们用IDA搜索这个导出函数:
这个带符号的加1其实就是我们的静态变量加一,所以这个静态变量的地址放在了我们的R0寄存器,而R0的值就是来自于R3寄存器指向的地址的值,所以R3是我们需要分析的,R3的地址是之前的R3加上PC,IDA给我们计算出来其实实际上就是加上4004,而这个4004是如何计算出来的呢?
我们动态分析一下,动态调试转到之后看到这个代码:
1 | libTestJNI.so:4E257F88 Java_com_example_testjni_NativeClass_settotal |
R3的值一开始是4E25B004 - 0x4E257F8E
得到的,经计算是:0x3706
确实是0x3706,我们增加的这个PC其实是IDA的PC往下指向的2两条指令,下面两条指令都是两个字节,所以是4个字节(thumb指令),而当前的指令(执行到ADD的时候)PC是我们当前查看的这个模块加上F8A:
所以我们应该使用基地址+0xF8A+0x4+0x3076=0x4004
所以我们静态变量的地址应该是这个so模块加上0x4004得到的地址。
最后我们可以看下R0的值:
确实使我们的变量。
分析到这里就可以了,我们现在需要解决的就是我们如何修改这个内存单元的值,还是用注入实现吧,方便快捷。
首先我们先要有这样一个函数:
1 | bool GetModuleBase(long long * ulModBase,pid_t pid,const char * pszModName){ |
这个函数是用来获取我们模块基地址的:
- 第一个参数由于我们用的是c语言,所以不能用引用,只能指针传入,并且,c语言要用bool这个命名,我们需要引入:
#include <stdbool.h>
。 - 第二个参数是我们要查询的进程PID
- 第三个参数是我们要查询的模块名称
1 | long long address; |
这个样子address这个变量里面存储的就是我们的模块基地址,既然得到了变量基地址,那么我们就可以用内存拷贝去修改我们的值:
1 | int tmp=100; |
这个样子就可以了,还是之前我们用到的ADBI框架。./hijack -d -p 1935 -l /data/local/tmp/libexample.so
1935是我们进程的PID。
java层就是将这个变量弹出吐司。