C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 05-18-2009, 11:52 AM   #1
Registered User
 
Join Date: May 2009
Posts: 11
Tracing execution with Ptrace

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!
tommyb05 is offline   Reply With Quote
Old 05-18-2009, 12:01 PM   #2
Senior software engineer
 
brewbuck's Avatar
 
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   Reply With Quote
Old 05-18-2009, 12:19 PM   #3
and the hat of vanishing
 
Salem's Avatar
 
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   Reply With Quote
Old 05-18-2009, 12:21 PM   #4
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,381
Quote:
Originally Posted by Salem View Post
> 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
I'm obviously missing some context here. What buffer overflow?

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   Reply With Quote
Old 05-18-2009, 03:43 PM   #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   Reply With Quote
Old 05-19-2009, 09:14 PM   #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   Reply With Quote
Old 05-20-2009, 02:02 AM   #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   Reply With Quote
Old 05-20-2009, 09:38 AM   #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   Reply With Quote
Old 05-20-2009, 09:52 AM   #9
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
Quote:
Originally Posted by tommyb05 View Post
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?
Huh? The crash happens in the child process, so you should receive the signal in the parent process (as well as in the child process).

--
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   Reply With Quote
Old 05-20-2009, 10:51 AM   #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   Reply With Quote
Reply

Tags
debugger, execution, linux, ptrace, tracing

Thread Tools
Display Modes

Forum Jump

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


All times are GMT -6. The time now is 09:13 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22