1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
| [root@localhost int3_on_call_ret]# cat debuger.c #include <stdio.h> #include <stdarg.h> #include <stdlib.h> #include <signal.h> #include <syscall.h> #include <sys/ptrace.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/reg.h> #include <sys/user.h> #include <unistd.h> #include <errno.h> #include <string.h>
void run_target(const char* programname) { printf("target started. will run '%s'\n", programname);
/* Allow tracing of this process */ if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) { perror("ptrace"); return; }
/* Replace this process's image with the given program */ execl(programname, programname, (char *)NULL); }
void run_debugger(pid_t child_pid) { int wait_status; struct user_regs_struct regs;
printf("debugger started\n");
/* Wait for child to stop on its first instruction */ wait(&wait_status);
/* Obtain and show child's instruction pointer */ ptrace(PTRACE_GETREGS, child_pid, 0, ®s); printf("Child started. RIP = 0x%016x\n", regs.rip);
//修改指令 size_t addr = 4005e2; // hello 这里会调用一个CALLQ指令: 参考 objdump -d hello size_t data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0); size_t trap = (data & 0xFFFFFFFFFFFFFF00) | 0xCC;
/* 写入 INT 3 指令 */ ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)trap);
/* Let the child run to the breakpoint and wait for it to reach it */ ptrace(PTRACE_CONT, child_pid, 0, 0);
//wait to breakpoint wait(&wait_status); if (WIFSTOPPED(wait_status)) { printf("Child got a signal: %s\n", strsignal(WSTOPSIG(wait_status))); } else { perror("wait"); return; }
/* 恢复指令 */ ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data);
/* IP寄存器值 减1 */ ptrace(PTRACE_GETREGS, child_pid, 0, ®s); regs.rip -= 1; ptrace(PTRACE_SETREGS, child_pid, 0, ®s);
/* The child can continue running now */ ptrace(PTRACE_CONT, child_pid, 0, 0);
wait(&wait_status); if (WIFEXITED(wait_status)) { printf("Child exited\n"); } else if(WIFSIGNALED(wait_status)) { printf("signal !!!\n"); } else { printf("Unexpected signal. %s \n", strsignal(WSTOPSIG(wait_status))); } }
int main(int argc, char** argv) { pid_t child_pid;
if (argc < 2) { fprintf(stderr, "Expected a program name as argument\n"); return -1; }
child_pid = fork(); if (child_pid == 0) { run_target(argv[1]); } else if (child_pid > 0) { run_debugger(child_pid); } else { perror("fork"); return -1; }
return 0; }
[root@localhost int3_on_call_ret]#
|