文字版,图文版请访问“
http://gikir.com/blog/?p=136 ” !
void usage(void) {
printf(“原创文章,欢迎转载和引用,不过请附上原始链接(
http://gikir.com/blog/?p=136 )和本申明,否则嘛,哼哼…\n”);
}
本篇文章我们将介绍如何使用gikdbg.art调试调试控制台并对其进行热补丁的操作以改变原始程序的行为, 此处我们以 /system/bin/ping为例进行Step by step的操作与解释以及一些注意事项的说明。
Step 0.前置说明手机端:LGLU6200,Android 2.3.5 DVM 运行时;
PC端:ParallelDesktop虚拟机,Windows 8.0,gikdbg.art v1.2.build140612.2;
PS : 非root环境的设备由于权限的原因会有很多问题,不推荐使用!
Step 1.连接设备将设备通过USB连接调试主机,打开gikdbg.art.exe,执行 /ART Debug/Device菜单,我们就可以来到如下界面:
0-login2shell
从v1.2版本开始,已经开放了ARM汇编的功能,从上图可以看到我们分别汇编了ARM的bx lr以及THUMB的bx lr两条指令。你还可以不带参数使用$tasm或$asm两条命令选择加载$(GIKDBG.ART)/ artsample/asm.s文件进行批量汇编的测试。
Step 2.运行选择文件接着我们执行 /ART Debug/File/Open并以名称排序找到ping就可以得到如下控制台程序列表:
1-openping
双击或者执行Open按钮我们就来道start函数,一路F8进入main函数(怎么判别main函数各位自行探索一下):
2-ping-normal-main
执行F9让程序跑起来,然后我们就得到如下程序输出:
3-ping-normal-exit
这就是正常的未补丁的程序输出内容。
Step 3.热补丁修改main函数的行为
我设备上的main函数反汇编如下:
ART CPU
Address Hex dump Command Comments
0000B9A4 / $ 4FF0E92D push.w{ r4, r5, r6, r7, r8, r9, r10, r11, lr }.func_0000B9A4
0000B9A8 | . 4A9CF8DF ldr.w r4, [pc, #0xa9c]
0000B9AC | .CA9CF8DF ldr.w r12, [pc, #0xa9c]
0000B9B0 | .B0F3 sub sp, #0x1cc
0000B9B2 | . 447C add r4, pc
0000B9B4 | . 9005 str r0, [sp, #0x14]
0000B9B6 | . 2002 movs r0, #0×2
0000B9B8 | . 500CF854 ldr.w r5, [r4, r12]
0000B9BC | . 9106 str r1, [sp, #0x18]
0000B9BE | . 2103 movs r1, #0×3
0000B9C0 | . 682A ldr r2, [r5]
0000B9C2 | . 9271 str r2, [sp, #0x1c4]
0000B9C4 | . 2201 movs r2, #0×1
0000B9C6 | .EB04F7FD blx.socket
0000B9CA | . 1A84F8DF ldr.w r1, [pc, #0xa84]
0000B9CE | . 5863 ldr r3, [r4, r1]
0000B9D0 | . 6018 str r0, [r3]
0000B9D2 | .EAD4F7FD blx.__errno
0000B9D6 | . 6800 ldr r0, [r0]
……
我们现在的目的是想动态的把它补丁成如下函数:
int main(void)
{
static const char gikstr[] = “gik”;// 0x006B6967
return puts(gikstr);
}
人肉编译成如下形式:
_main :
push.w{ r4, r5, r6, r7, r8, r9, r10, r11, lr }
add r0, pc, #imm//待计算
blx #imm//待计算
pop.w{ r4, r5, r6, r7, r8, r9, r10, r11, pc }
_gikstr:
.long 0x006B6967
原始代码和目标代码都有了,下面我们用gikdbg.art加载目标程序,然后写入我们的自定义代码,目的是得到如下图所示的新的main函数:
4-ping-modifing
操作过程如下:
1) 第一条指令与原始指令一样,直接跳过;
2) 选中地址B9A8然后执行右键Assemble或者快捷键空格弹出指令输入框输入add r0, pc, #0×10,这里0×10的计算过程在步骤4中说明;
3) 选中地址B9AC然后执行右键Assemble或者快捷键空格弹出指令输入框输入blx #-0x2B00就会汇编成blx puts的调用,参数 -0x2B00的计算过程如下:
表达式“addr : blx #imm”代表的意义是调用addr + 4(thumb, 如果是arm指令则为8, 这是当前地址与当前PC寄存器值的对应关系) + imm处的代码,本例是B9AC,我们的目的地址是puts,在plt表里面找到puts的代码如下:
ART CPU
Address Hex dump Command Comments
00008EB0 / > E28FC600 add r12, pc, #0×0.puts
00008EB4 | .E28CCA05 add r12, r12, #0×5000
00008EB8 \.E5BCF348 ldr pc, [r12, #840]!
可以看到它的地址是8EB0,建立方程就是B9AC + 4 + imm = 8EB0, 计算得到imm = -2B00, 因此我们的植入代码为blx #-0x2B00;
4) 最后一条指令是4个字节的thumb2指令,因此需要到地址B9B8才可以正常插入,这之间的代码用nop填充,这样整个新main函数的结束地址为B9BC,那么我们可以考虑将字符串“gik”的数据写入这个地址,并让puts的参数指向该地址,我们在步骤2中使用的是add r0, pc, #imm的方式得到这个地址的,imm是如何确定的?首先pc的值是当前地址 + 4,因此有B9A8 + 4 + imm = B9BC,计算得到imm = 0×10,所以步骤2写入指令是add r0, pc, #0×10;
最终修改好的代码如下:
6-ping-modified
为了输出我们的“gik”(4字节的十六进制数为006B6967)字符串,我们需要把地址B9BC的内容改掉:
5-ping-modifymem
一切准备就绪,选中B9B0,执行F4,我们就执行puts(“gik”)了:
7-ping-putsed
执行F9让程序正常退出,我们得到了新main函数的输出:
8-ping-hotpatched-exit
其他说明:
1) 非 /system/bin路径的程序,你可以在程序列表右键执行OpenEx打开它;
2) 如果你设备上没有ping程序,你可以找一个有引入puts函数的程序,或者自行写一个;
3) 如果你设备上的ping程序的main函数与我提供的不一致,你需要自己计算热补丁指令中imm的值;
4) 应用热补丁之后,当F7或者F8到其他模块又返回主模块时显示的代码又恢复了,这是本地代码,远程代码还是热补丁的状态,算是一个缺陷,后续更新加入同步内存代码的功能;
5) 由于设备,系统差异太大,兼容性Bug也许很多,请各位同学尽可能提供详尽的信息以帮助我们解决修复它,简单的一句“Bug很多”,“问题很多”这样的反馈真心没用,神仙拿到这样的反馈也没辙啊!
剩下更多的细节,同学们可以前往
http://gikir.com/product.php 下载使用,自行摸索更多已经提供的功能。另外,在使用gikdbg.art的过程中有任何改进意见和Bug,欢迎反馈给我们以帮助我们将他开发得更加完善。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课