Indicates that this process is to be traced by its parent. Any signal (except SIGKILL) delivered to this process will cause it to stop and its parent to be notified via wait(). Also, all subsequent calls to exec() by this process will cause a SIGTRAP to be sent to it, giving the parent a chance to gain control before the new program begins execution. A process probably shouldn’t make this request if its parent isn’t expecting to trace it. (pid, addr, and data are ignored.)
returns true if the child process was stopped by delivery of a signal; this is possible only if the call was done using WUNTRACED or
when the child is being traced (see ptrace(2)).
#include"stdio.h" #include"stdlib.h" #include"unistd.h" #include"sys/types.h" #include<sys/ptrace.h> #define procmsg(s...) printf(s) #define TODO do {\ printf("TODO: %s\n", __FUNCTION__); \ exit(1); \ } while (0);
voidrun_target(char * programname){ procmsg("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, 0); } voidrun_debugger(pid_t child_pid) { int wait_status; unsigned icounter = 0; procmsg("debugger started\n");
/* Wait for child to stop on its first instruction after execl */ wait(&wait_status);
while (WIFSTOPPED(wait_status)) { icounter++; /* Make the child execute another instruction */ if (ptrace(PTRACE_SINGLESTEP, child_pid, 0, 0) < 0) { perror("ptrace"); return; }
/* Wait for child to stop on its next instruction */ wait(&wait_status); }
/* The whole purpose of this file is for GDB and GDB only.
Don’t read too much into it. Don’t use it for
anything other than GDB unless know what you are
doing. */
pntmsg("instruction 0x%08x in addr 0x%08x\n", readback, addr); // pause();
Ptrace(PTRACE_CONT, child_pid, 0, 0);
wait(&wait_status); if (WIFSTOPPED(wait_status)) { pntmsg("Child got a signal: %s\n", strsignal(WSTOPSIG(wait_status))); } else { perror("wait"); return; }
/* See where the child is now */ Ptrace(PTRACE_GETREGS, child_pid, 0, ®s); pntmsg("Child stopped at RIP = 0x%08x\n", regs.rip); pause();
1 2 3 4 5
[PNT] debugger started [CHD] target started. will run './victim' [PNT] instruction 0x01c7c7cc in addr 0x00401000 [PNT] Child got a signal: Trace/breakpoint trap [PNT] Child stopped at RIP = 0x00401001
可以看到 rip 移动了一位,需要移动回去,然后覆写这原来的位置,就能继续运行了
1 2 3 4 5 6 7 8 9 10 11 12
regs.rip -= 1; Ptrace(PTRACE_SETREGS, child_pid, 0, ®s); Ptrace(PTRACE_POKETEXT, child_pid, regs.rip, instr); pntmsg("icounter = %u, instr = 0x%08x, rip = 0x%08x\n", icounter, instr, regs.rip ); // pause(); /* Make the child execute another instruction */ Ptrace(PTRACE_SINGLESTEP, child_pid, 0, 0); pause(); /* Wait for child to stop on its next instruction */ wait(&wait_status);
/* 1. get regs 2. rollback rip and write back 3. single step 4. re-enable breakpoint */ intresume_from_breakpoint(pid_t pid, debug_breakpoint* dbp){ structuser_regs_structregs; int wait_status;
The DW_OP_fbreg operation provides a signed LEB128 offset from the address specified by the location description in the DW_AT_frame_base attribute of the current function. (This is typically a “stack pointer” register plus or minus some offset. On more sophisticated systems it might be a location list that adjusts the offset according to changes in the stack pointer as the PC changes.)
CU: ./traceproc2.c: File name Line number Starting address View Stmt traceproc2.c 5 0x401136 x traceproc2.c 6 0x401145 x traceproc2.c 9 0x40114e x (··· ··· ···) traceproc2.c 18 0x401196 x