10.3. 执行转移

转移正在运行的进程执行到我们控制的代码。首先是如何放置我们想执行的代码?
那么需要了解进程的布局和执行流。最基本的工具是符号表,符号映射到vma。
objdump --syms ./example | grep main
08048450 g F .text 00000082 main
main函数是最好的倾倒区域给任意代码,因为它的代码永远不会再次运行。当然还
有很多区域当作倾倒区域,例如如果程序有帮助函数区域,一般不会使用

然后是如何修改执行过程?这里需要知道ptrace的知识和vm如何遍历可执行文件。
在X86平台,有个vm寄存器用来保存下个指令的vma。一旦一个指令完成,vm处理在
eip(vm寄存器)的指令,并将eip加上当前指令长度。有些其它跳转指令,比如jmp
引起eip被修改到操作数指定的地址。理论上我们放置一些自己的代码在0x08048450,
为了执行我们的代码,通过ptrace的PTRACE_SETREGS和PTRACE_GETREGS函数,他们
允许第三方程序获取和设置另外一个进程的寄存器。这个寄存器包含eip。步骤如下:
a。调用PTRACE_GETREGS获取当前的寄存器信息
b。设置其中的eip为我们代码的地址
c。调用PTRACE_SETREGS来设置寄存器
d。继续执行原进程

然后一旦我们的代码执行完毕如何恢复原来的执行?我们需要修改我们的注入代码
可以在最后加入int 0x3,在Linux下引起异常或断点SIGTRAP来激活调试器。如果进程
正在被跟踪,那么它将被wait()捕获。
nop
nop
nop
nop
nop
nop

move $0x1, %eax
int $0x3
nop
步骤多了些:
a。调用PTRACE_GETREGS
b。保存这些寄存器,用于恢复
c。设置eip寄存器到注入代码的地址
d。调用PTRACE_SETREGS修改寄存器
e。继续执行,但是使用wait()函数监视信号,如果wait函数返回信号
aa。调用PTRACE_GETREGS
bb。如果eip减去保存的eip等于注入代码大小-1.表示注入代码执行到最后
那么到下一步f
cc。否则,继续执行
f。在注入代码完成后,调用PTRACE_SETREGS恢复步骤b保存的值。