![]() |
| | #1 |
| Registered User Join Date: May 2009
Posts: 11
| Tracing execution with Ptrace 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;
}
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;
}
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$ Code: tommy@otto:/tmp$ ./pt eax 0x0 ebx 0x0 ecx 0x0 edx 0x0 esi 0x0 edi 0x0 esp 0xbffd9580 eip 0xb7fbc810 tommy@otto:/tmp$ 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! |
| tommyb05 is offline | |
| | #2 |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,381
| I don't understand what you are trying to do there with perl. The gdb output is garbage, the result of perl itself crashing. The output of your ./pt program looks correct. Upon the call to exec(), the registers should be cleared. Everything looks fine (except your indentation).
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot |
| brewbuck is offline | |
| | #3 |
| and the hat of vanishing Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,214
| > The gdb output is garbage, the result of perl itself crashing. It's the buffer overflow. Check all those 0x70 (ie, lower case "p") which have found their way into EBP and EIP
__________________ If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut. Up to 8Mb PlusNet broadband from only £5.99 a month! |
| Salem is offline | |
| | #4 | |
| Senior software engineer Join Date: Mar 2007 Location: Portland, OR
Posts: 5,381
| Quote:
EDIT: Nevermind, I see it now. I have no idea why the OP would expect the registers to look the same in those two cases.
__________________ "Congratulations on your purchase. To begin using your quantum computer, set the power switch to both off and on simultaneously." -- raftpeople@slashdot | |
| brewbuck is offline | |
| | #5 |
| Registered User Join Date: May 2009
Posts: 11
| The problem was putting PTRACE_CONT in the right spot, right after the fork() statement.. so thats fixed. Now its not catching the signals of the child, bleh ![]() Anyone got any ideas? |
| tommyb05 is offline | |
| | #6 |
| Registered User Join Date: May 2009
Posts: 11
| Does anyone here know how to achieve my goal (which you can find if you read above)? |
| tommyb05 is offline | |
| | #7 |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| So, you are definitely achieving: 1. fork, exec and ptrace. 2. catch all signals the child receives - well, the first signal (according to here: ptrace(2): process trace - Linux man page) is a sigtrap, since the child process performs execl. 3. Display extended registers. Not sure what you mean by extended registers, but you are certainly displaying the registers you have a printf for. So the problem is probably that you didn't RTFM, and as a consequence, you are catching "the wrong signal". You may want to use PTRACE_CONT to continue the child process after the SIG_TRAP, rather than detach and exit. -- Mats
__________________ Compilers can produce warnings - make the compiler programmers happy: Use them! Please don't PM me for help - and no, I don't do help over instant messengers. |
| matsp is offline | |
| | #8 |
| Registered User Join Date: May 2009
Posts: 11
| Thanks. I'm catching the signals now, but I'm crashing the program before the signal is caught? Is there a way to catch the signal before I crash it with the overflow? |
| tommyb05 is offline | |
| | #9 | |
| Kernel hacker Join Date: Jul 2007 Location: Farncombe, Surrey, England
Posts: 15,686
| Quote:
-- Mats
__________________ Compilers can produce warnings - make the compiler programmers happy: Use them! Please don't PM me for help - and no, I don't do help over instant messengers. | |
| matsp is offline | |
| | #10 |
| Registered User Join Date: May 2009
Posts: 11
| If happens as soon as I run the child process as the code is wrote. But I found if I use WIFSTOPPED instead of WIFSIGNALED to see the current signal, things work out. |
| tommyb05 is offline | |
![]() |
| Tags |
| debugger, execution, linux, ptrace, tracing |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Execution Time - Rijandael encryption | gamer4life687 | C++ Programming | 5 | 09-20-2008 09:25 PM |
| Use of threads or state machines to synchronize command execution | daluu | C# Programming | 0 | 10-06-2007 01:25 PM |
| Arbitrary Code Execution | CrazyNorman | C++ Programming | 3 | 04-10-2007 02:33 PM |
| What is the best way to record a process execution time? | hanash | Linux Programming | 7 | 03-15-2006 07:17 AM |
| Initiating command prompt execution | bluecoder | Windows Programming | 2 | 07-26-2002 07:00 PM |