如何修改EIP的tracee forked procee?
How to modify EIP's tracee forked procee?
我正在开发一个 Linux 应用程序,它包含 ptrace 以观察另一个由 fork() 系统调用创建的进程。
严格来说:我想对分叉进程(智利进程或 "tracee")实施故障注入。
如下图所示:
tracer 使用PTRACE_GETREGS 请求从tracee 获取regs (struct_user_regs) 结构。之后,tracer 修改tracee 的EIP 值(当内核切换到tracee 时,命令执行将违反所谓的控制流错误CFE)。然后 PTRAC E_CONT 请求将发送给 tracee 以继续执行。
不幸的是,在修改了EPI的tracee之后,tracee由于(segmentation fault)而没有继续执行。
怎么给tracee EIP一个合适的值?
这是代码
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include<sys/user.h>
#include<sys/reg.h>
#include<stdlib.h>
#include<stdio.h>
#include <asm/ptrace-abi.h>
int main()
{
pid_t child;
int status;
int sum=0;
struct user_regs_struct regs;
child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
printf("hello world 1\n");
printf("hello world 2\n");
raise (SIGINT); // just to move control to the tracer
printf("hello world 3\n");
printf("hello world 4\n");
printf("hello world 5\n");
exit(EXIT_SUCCESS);
}
else {
wait(NULL);
ptrace(PTRACE_GETREGS, child,NULL, ®s);
printf("\n EIP @ 0x %#lx\n",regs.eip);
//get the tracee EIP
long int new_eip=ptrace(PTRACE_PEEKTEXT, child,regs.eip,NULL);
//chabge EIP and poke it again
new_eip += ???; // make change that let to jump to another tracee instruction address (say to print hello world 5)
ptrace(PTRACE_POKETEXT, child,regs.eip,new_eip);
ptrace(PTRACE_CONT, child, NULL, NULL);
}
return 0;
}
有什么想法吗?
感谢您的帮助。
您不是在修改 EIP,而是在 EIP 的指令值中添加一些内容,并且可能导致错误的地址引用。要更改 EIP,请使用 PTRACE_SETREGS
wait(NULL);
ptrace(PTRACE_GETREGS, child,NULL, ®s);
printf("\n EIP @ 0x %#lx\n",regs.eip);
regs.eip += ???;
ptrace(PTRACE_SETREGS, child, NULL, ®s);
ptrace(PTRACE_CONT, child, NULL, NULL);
是的,它完全是特定于平台的。我阅读了很多描述 ptrace 系统调用的材料,以及我们如何使用它来捕获在 ptrace 向挂起的 tracee 发送一些请求(如 PTRACE_CONT)后将要执行的下一条指令的 EIP。
我总是看到 EIP 值是这样的:
80484a6:
80484a7:
80484ac:
80484b2:
80484b4:
80484b6:
80484b8:
我测试了一个简单的代码(只是打印EIP的值和对应执行的指令)。
但结果如下所示:
EIP: b773cbe0 Instruction executed: c3595a5d
EIP: b773cbe1 Instruction executed: ccc3595a
EIP: b773cbe0 Instruction executed: c3595a5d
hello world 5
EIP: b773cbe0 Instruction executed: c3595a5d
EIP: b773cbe1 Instruction executed: ccc3595a
EIP: b773cbe0 Instruction executed: c3595a5d
hello world 6
EIP: b773cbe0 Instruction executed: c3595a5d
EIP: b773cbe1 Instruction executed: ccc3595a
EIP: b773cbe0 Instruction executed: c3595a5d
这是什么 (b773cbe0) ??!!!
我移动到 gdb 并使用此命令行查看转储文件 (objdump -d a.out)
结果与之前的结果有所不同
8048864: 8b 6c 24 20 mov 0x20(%esp),%ebp
8048868: 8d b3 0c ff ff ff lea -0xf4(%ebx),%esi
804886e: e8 41 fb ff ff call 80483b4 <_init>
8048873: 8d 83 08 ff ff ff lea -0xf8(%ebx),%eax
8048879: 29 c6 sub %eax,%esi
804887b: c1 fe 02 sar [=12=]x2,%esi
804887e: 85 f6 test %esi,%esi
8048880: 74 23 je 80488a5 <__libc_csu_init+0x55>
8048882: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
8048888: 83 ec 04 sub [=12=]x4,%esp
804888b: ff 74 24 2c pushl 0x2c(%esp)
804888f: ff 74 24 2c pushl 0x2c(%esp)
8048893: 55 push %ebp
8048894: ff 94 bb 08 ff ff ff call *-0xf8(%ebx,%edi,4)
804889b: 83 c7 01 add [=12=]x1,%edi
804889e: 83 c4 10 add [=12=]x10,%esp
80488a1: 39 f7 cmp %esi,%edi
80488a3: 75 e3 jne 8048888 <__libc_csu_init+0x38>
80488a5: 83 c4 0c add [=12=]xc,%esp
80488a8: 5b pop %ebx
80488a9: 5e pop %esi
80488aa: 5f pop %edi
80488ab: 5d pop %ebp
80488ac: c3 ret
80488ad: 8d 76 00 lea 0x0(%esi),%esi
我真的很困惑。
我正在开发一个 Linux 应用程序,它包含 ptrace 以观察另一个由 fork() 系统调用创建的进程。
严格来说:我想对分叉进程(智利进程或 "tracee")实施故障注入。
如下图所示:
tracer 使用PTRACE_GETREGS 请求从tracee 获取regs (struct_user_regs) 结构。之后,tracer 修改tracee 的EIP 值(当内核切换到tracee 时,命令执行将违反所谓的控制流错误CFE)。然后 PTRAC E_CONT 请求将发送给 tracee 以继续执行。
不幸的是,在修改了EPI的tracee之后,tracee由于(segmentation fault)而没有继续执行。 怎么给tracee EIP一个合适的值?
这是代码
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include<sys/user.h>
#include<sys/reg.h>
#include<stdlib.h>
#include<stdio.h>
#include <asm/ptrace-abi.h>
int main()
{
pid_t child;
int status;
int sum=0;
struct user_regs_struct regs;
child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
printf("hello world 1\n");
printf("hello world 2\n");
raise (SIGINT); // just to move control to the tracer
printf("hello world 3\n");
printf("hello world 4\n");
printf("hello world 5\n");
exit(EXIT_SUCCESS);
}
else {
wait(NULL);
ptrace(PTRACE_GETREGS, child,NULL, ®s);
printf("\n EIP @ 0x %#lx\n",regs.eip);
//get the tracee EIP
long int new_eip=ptrace(PTRACE_PEEKTEXT, child,regs.eip,NULL);
//chabge EIP and poke it again
new_eip += ???; // make change that let to jump to another tracee instruction address (say to print hello world 5)
ptrace(PTRACE_POKETEXT, child,regs.eip,new_eip);
ptrace(PTRACE_CONT, child, NULL, NULL);
}
return 0;
}
有什么想法吗? 感谢您的帮助。
您不是在修改 EIP,而是在 EIP 的指令值中添加一些内容,并且可能导致错误的地址引用。要更改 EIP,请使用 PTRACE_SETREGS
wait(NULL);
ptrace(PTRACE_GETREGS, child,NULL, ®s);
printf("\n EIP @ 0x %#lx\n",regs.eip);
regs.eip += ???;
ptrace(PTRACE_SETREGS, child, NULL, ®s);
ptrace(PTRACE_CONT, child, NULL, NULL);
是的,它完全是特定于平台的。我阅读了很多描述 ptrace 系统调用的材料,以及我们如何使用它来捕获在 ptrace 向挂起的 tracee 发送一些请求(如 PTRACE_CONT)后将要执行的下一条指令的 EIP。 我总是看到 EIP 值是这样的:
80484a6:
80484a7:
80484ac:
80484b2:
80484b4:
80484b6:
80484b8:
我测试了一个简单的代码(只是打印EIP的值和对应执行的指令)。 但结果如下所示:
EIP: b773cbe0 Instruction executed: c3595a5d
EIP: b773cbe1 Instruction executed: ccc3595a
EIP: b773cbe0 Instruction executed: c3595a5d
hello world 5
EIP: b773cbe0 Instruction executed: c3595a5d
EIP: b773cbe1 Instruction executed: ccc3595a
EIP: b773cbe0 Instruction executed: c3595a5d
hello world 6
EIP: b773cbe0 Instruction executed: c3595a5d
EIP: b773cbe1 Instruction executed: ccc3595a
EIP: b773cbe0 Instruction executed: c3595a5d
这是什么 (b773cbe0) ??!!! 我移动到 gdb 并使用此命令行查看转储文件 (objdump -d a.out) 结果与之前的结果有所不同
8048864: 8b 6c 24 20 mov 0x20(%esp),%ebp
8048868: 8d b3 0c ff ff ff lea -0xf4(%ebx),%esi
804886e: e8 41 fb ff ff call 80483b4 <_init>
8048873: 8d 83 08 ff ff ff lea -0xf8(%ebx),%eax
8048879: 29 c6 sub %eax,%esi
804887b: c1 fe 02 sar [=12=]x2,%esi
804887e: 85 f6 test %esi,%esi
8048880: 74 23 je 80488a5 <__libc_csu_init+0x55>
8048882: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
8048888: 83 ec 04 sub [=12=]x4,%esp
804888b: ff 74 24 2c pushl 0x2c(%esp)
804888f: ff 74 24 2c pushl 0x2c(%esp)
8048893: 55 push %ebp
8048894: ff 94 bb 08 ff ff ff call *-0xf8(%ebx,%edi,4)
804889b: 83 c7 01 add [=12=]x1,%edi
804889e: 83 c4 10 add [=12=]x10,%esp
80488a1: 39 f7 cmp %esi,%edi
80488a3: 75 e3 jne 8048888 <__libc_csu_init+0x38>
80488a5: 83 c4 0c add [=12=]xc,%esp
80488a8: 5b pop %ebx
80488a9: 5e pop %esi
80488aa: 5f pop %edi
80488ab: 5d pop %ebp
80488ac: c3 ret
80488ad: 8d 76 00 lea 0x0(%esi),%esi
我真的很困惑。