Android内存数据读取与修改/内存代码注入/内存dump

在Android的逆向时,对内存数据的操作主要有三种:内存数据读取与修改,内存代码注入,内存dump。之前对这三种操作的概念比较模糊,因此找了些资料整理如下,加深自己的理解。





修改数据

修改内存数据

修改内存数据需要在十六进制窗口中进行编辑,可先将反汇编窗口与十六进制窗口同步。如下图所示,在反汇编窗口中点击鼠标右键弹出菜单,选中Synchronize with选项,在子菜单中可以选择反汇编窗口同步的窗口或寄存器,这里选择同步Hex View-1窗口,即与十六进制窗口同步。窗口同步后在反汇编窗口中跳转到指定地址十六进制窗口也会跟随着跳转到指定地址,方便我们对内存数据进行查看和编辑。

Android内存数据读取与修改/内存代码注入/内存dump_第1张图片

右键菜单同步窗口选项

在需要修改内存数据时,可以在十六进制窗口中跳转到需要修改的内存地址处,点击鼠标右键,如下图所示,在弹出的菜单中点击Edit选项,即可以直接在十六进制窗口中进行编辑。

Android内存数据读取与修改/内存代码注入/内存dump_第2张图片

 十六进制窗口编辑数据选项

修改数据完成后单击右键菜单,如下图所示,在弹出的右键惨淡中点击Apply changes选项可保存对内存数据的修改。

Android内存数据读取与修改/内存代码注入/内存dump_第3张图片

十六进制窗口保存修改选项

修改寄存器

在动态分析过程中,经常遇到需要修改寄存器值的情况,IDA提供了方便地修改寄存器值的方法。在寄存器窗口中,在需修改的寄存器单击鼠标右键,会弹出如下图所示的菜单,可以在右键菜单中选择对应的选项来对寄存器的值进行修改,例如可通过Modify value选项对寄存器的值进行修改,通过Zero value选项将对应寄存器的值设置为0,通过Toggle value选项对寄存器的值取反。

Android内存数据读取与修改/内存代码注入/内存dump_第4张图片

修改寄存器值的右键菜单

修改代码

在IDA动态调试时修改代码与修改数据的方法相似,在内存中代码也是以数据的方式存储,均需要在十六进制窗口对其进行编辑和修改,因此本小节不再重复介绍修改的方法,而是介绍部分在逆向分析过程中需要修改代码的场景。

NOP函数

在动态逆向分析过程中,经常遇到需要NOP程序的关键函数,通常有两种方法来修改函数的代码。第一种方法可以在调用函数的地址处进行修改,将调用函数的汇编指令修改成NOP指令。ARM汇编中并没有提供单独的NOP指令,但可以使用”movs r0,r0”指令来代替NOP指令,其对应的十六进制数值为”00 00 A0 E1”,在IDA中该指令会被识别成NOP指令。

第二种方法是在函数首部直接让函数返回,将函数头部的汇编指令修改成mov pc,lr”指令,表示直接返回,其对应的十六进制数值为0E F0 A0 E1,在IDA中会被识别成RET指令。

改变执行流程

在程序中一般伴随有很多条件语句,这些条件语句决定着程序的执行流程。在动态调试过程中我们可通过修改条件判断时寄存器值或者直接NOP条件判断语句来控制程序的执行流程。

以上摘自:http://gslab.qq.com/portal.php?mod=view&aid=157


内存注入

Android内存数据读取与修改/内存代码注入/内存dump_第5张图片

ptrace注入远程进程流程

摘自:http://gslab.qq.com/portal.php?mod=view&aid=16

动态调试dump内存

IDC脚本

在动态分析过程中经常需要使用IDC脚本。使用IDC脚本可通过菜单栏的File->Script Command选项打开如下图所示的对话框,在右侧的输入框中可以编辑IDC脚本,或者通过菜单栏的File->Script File选项来直接打开一个IDC文件。

Android内存数据读取与修改/内存代码注入/内存dump_第6张图片

IDC脚本编辑对话框

IDC脚本的应用场景十分广泛,最常用的就是Dump内存数据。在逆向分析过程中,经常遇到Android应用程序对dex文件进行了加密处理,在Native程序中对dex文件进行解密。逆向分析人员要获取到真正的dex文件,可以在解密dex文件的代码处中断,使用IDC脚本Dump已经解密的内存空间数据转储到文件中。

以上摘自:http://gslab.qq.com/portal.php?mod=view&aid=157

下面是个IDC脚本dump内存的示例

////IDC dump dex////
auto fp, dex_addr, end_addr;
fp = fopen("F:\\dump.dex", "wb");
end_addr = r0 + r1;
for ( dex_addr = r0; dex_addr < end_addr; dex_addr ++ )
    fputc(Byte(dex_addr), fp);

  通常在dvmDexFileOpenPartial()这个函数下断点,R0寄存器指向的地址就是dex文件在内存中的地址,R1寄存器就是dex文件的大小。如果经过了加固,那么内存中可能没有完整的dex,或者如360加固不再走 dvmDexFileOpenPartial而是自己实现此函数功能,那么在此处下断点也无法拿到完整的dex。可以考虑使用dexHunter的类抽取法,或者hook mmap等。



你可能感兴趣的:(Android安全)