Simply disassemler with ptrace request

1

I am trying to learn how breakpoints software works with pctrace (inserting INT3) in the code.

For this I have followed a series of examples from different sites to create a simple disassembler, and I have been doing a kind of merge with them according to what interested me.

The main code is here: https://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints/

The code requires that you pass the address where you want to insert the breakpoint manually.

I am using the example: http://www.alexonlinux.com/wp-content/uploads/2008/03/sleeper.c

Then, using objdump -d, I get the address between the two prints and pass it to the disassembler.

The result I get is this:

debugger started
In debugger process 15819
In debuggie process 15820
Child started. EIP = 0xb7f41000
Original data at 0x08048429: 0xffffffff
After trap, data at 0x08048429: 0xffffffff
Time before debugger falling asleep: 1593599313

As seen, Original and After data are the same but this is wrong, After trap should be 0xffffffcc.

The prints are not printed either:

printf ("~~~~~~~~~~~~> Before breakpoint \ n");
// The breakpoint
printf ("~~~~~~~~~~~~> After breakpoint \ n")

I cannot understand why it is not replacing well, the insertion I am doing:

    / * Write the trap instruction 'int 3' into the address * /
    unsigned data_with_trap = (data & 0xFFFFFF00) | 0xCC;
    ptrace (PTRACE_POKETEXT, child_pid, (void *) addr, (void *) data_with_trap);
    // Finish Placing breakpoint ...

Does anyone see any problem whit this code?

Part of the whole code:

 void run_debugger(pid_t child_pid)
    {
        int wait_status;
        struct user_regs_struct regs;
            printf("debugger started\n");
            printf( "In debugger process %ld\n", (long)getpid() );   
    
        wait(&wait_status);
    
        ptrace(PTRACE_GETREGS, child_pid, 0, &regs);
        printf("Child started. EIP = 0x%08x\n", regs.eip);
    
    
            // Placing breakpoint...
            unsigned addr = 0x8048429;
            unsigned data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0);
            printf("Original data at 0x%08x: 0x%08x\n", addr, data);
    
            /* Write the trap instruction 'int 3' into the address */
            unsigned data_with_trap = (data & 0xFFFFFF00) | 0xCC;
            ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data_with_trap);
            // Finish Placing breakpoint...
    
    
        unsigned readback_data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0);
        printf("After trap, data at 0x%08x: 0x%08x\n", addr, readback_data);
    
    
    
        printf( "Time before debugger falling asleep: %ld\n", (long)time( NULL ) );
        sleep( 5 );
        printf( "Time after debugger falling asleep: %ld. Resuming debuggie...\n", (long)time( NULL ) );
    
    
    
        ptrace(PTRACE_CONT, child_pid, 0, 0);
    
        wait(&wait_status);
        if (WIFSTOPPED(wait_status)) {
            printf("Child got a signal: %s\n", strsignal(WSTOPSIG(wait_status)));
        }
        else {
            perror("wait");
            return;
        }
    
        ptrace(PTRACE_GETREGS, child_pid, 0, &regs);
        printf("Child stopped at EIP = 0x%08x\n", regs.eip);
    
        /* Remove the breakpoint by restoring the previous data
        ** at the target address, and unwind the EIP back by 1 to
        ** let the CPU execute the original instruction that was
        ** there.
        */
        ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data);
        regs.eip -= 1;
        ptrace(PTRACE_SETREGS, child_pid, 0, &regs);
    
        /* 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 {
            printf("Unexpected signal\n");
        }
    }
    
    void do_debuggie( void )
    {
            char* argv[] = { NULL };
            char* envp[] = { NULL };
    
            printf( "In debuggie process %ld\n", (long)getpid() );
    
            if (ptrace( PTRACE_TRACEME, 0, NULL, NULL ))
            {
                    perror( "ptrace" );
                    return;
            }
    
            execve( "sleeper", argv, envp );
    }
    
    
    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)
             do_debuggie();
            // argv[1];
        else if (child_pid > 0)
            run_debugger(child_pid);
        else {
            perror("fork");
            return -1;
        }
    
        return 0;
    }

Thank you!

disassembly
ptrace
asked on Stack Overflow Jul 1, 2020 by conjim

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0