I've asked a couple others places but no one yet has been able to get my program to work correctly. So please hear me out!
I'm writing a simple linux tracing debugger that will trace a child application and catch any signals it receives. If it receives a signal and stops or crashes, I want to print out the registers of the child at that point.
I have tried using PTRACE_TRACEME and PTRACE_ATTACH, so far PTRACE_TRACEME seems to be the one I should use.
I can run the program in GNU debugger and see that some registers are modified if I put too much data into a variable and it changes some of the registers to match the data I use to overflow it. When I run my test program the registers look quite normal and I run it through other tracing tools such as ltrace and strace to check for things too.
ptrace.c
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#define BIN "/tmp/test"
int main(int ac, char *ag[])
{
char buf[64];
int eax, ebx, ecx, edx, esi, edi, esp, eip;
pid_t child;
struct user_regs_struct r;
memset(buf, 'p', sizeof(buf));
child = fork();
if(child == 0)
{
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl(BIN, BIN, buf, NULL);
}
else
{
int sig, stat;
if(WIFSIGNALED(stat))
{
wait(&stat);
ptrace(PTRACE_GETREGS, child, 0, &r);
eax = r.eax;
ebx = r.ebx;
ecx = r.ecx;
edx = r.edx;
esi = r.esi;
edi = r.edi;
esp = r.esp;
eip = r.eip;
printf("eax 0x%x\nebx 0x%x\necx 0x%x\nedx 0x%x\nesi 0x%x\nedi 0x%x\nesp 0x%x\neip 0x%x\n", eax, ebx, ecx, edx, esi, edi, esp, eip);
}
}
ptrace(PTRACE_DETACH, child, 0, 0);
return 0;
}
ice.c
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char buf[32];
strcpy(buf, argv[1]);
return 0;
}
gnu debugger output:
Code:
tommy@otto:/tmp$ gdb /tmp/test
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) run `perl -e 'print "p" x 64'`
Starting program: /tmp/test `perl -e 'print "p" x 64'`
Program received signal SIGSEGV, Segmentation fault.
0x70707070 in ?? ()
(gdb) info registers
eax 0x0 0
ecx 0xbfa2470f -1079884017
edx 0x41 65
ebx 0xb7ee9ff4 -1209098252
esp 0xbfa24740 0xbfa24740
ebp 0x70707070 0x70707070
esi 0x80483a0 134513568
edi 0x80482d0 134513360
eip 0x70707070 0x70707070
eflags 0x10246 [ PF ZF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) q
The program is running. Exit anyway? (y or n) y
tommy@otto:/tmp$
ptrace program output:
Code:
tommy@otto:/tmp$ ./pt
eax 0x0
ebx 0x0
ecx 0x0
edx 0x0
esi 0x0
edi 0x0
esp 0xbffd9580
eip 0xb7fbc810
tommy@otto:/tmp$
Now you see what I'm looking for as output and you see what I've got?
I've tried using PTRACE_SINGLESTEP but maybe I'm just not putting it in the right places in the code.. that is why I defiantly need help with this code.
I am trying to...
1) Execute a program (fork() and make it a child) and trace it with ptrace()
2) Catch any signals the child receives
3) Display the extended registers of the child process when the signal is received
I have read all the documentation supplied but if you all know how to do this I would appreciate a clear cut answer for myself and everyone else.. I'm sure we're not the only ones even to attempt this small feat.
Much appreciated all, TIA!