0

I can't figure out why this happens, my code is this and it's from this question, i only change the type of addr and data in usigned long long int (the computer is x64 and the program run in the WLS). the minimum reproducible example is the one below:

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
#include <syscall.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>



 void procmsg(const char* format, ...)
   {
    va_list ap;
    fprintf(stdout, "[%d] ", getpid());
    va_start(ap, format);
    vfprintf(stdout, format, ap);
    va_end(ap);
   }

   void run_target(const 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, (char *)NULL);
 }

 void run_debugger(pid_t child_pid)
 {
        
    int wait_status;
    struct user_regs_struct regs;

    procmsg("debugger started\n");

    /* Wait for child to stop on its first instruction */
    wait(&wait_status);

    /* Obtain and show child's instruction pointer */
    ptrace(PTRACE_GETREGS, child_pid, 0, &regs);
    procmsg("Child started. RIP = 0x%016x\n", regs.rip);

    
    unsigned long long int addr = 0x0000000008001169;//0x004000da;
    unsigned long long int data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr,NULL);
    procmsg("Original data at 0x%08x: 0x%08x\n", addr, data);

    //test
    unsigned long long int data_u = data;
    procmsg("test data_u: 0x%08x\n", data_u);

    /* Write the trap instruction 'int 3' into the address */
    unsigned long long int data_with_trap = (data & 0xFFFFFFFFFFFFFF00) | 0xCC;
    procmsg("Data with trap : 0x%016llx \n",data_with_trap);
    ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data_with_trap);

    /* See what's there again... */
    unsigned long long int readback_data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0);
    procmsg("After trap,set breakpoint, data at 0x%016llx: 0x%016llx\n", addr, readback_data);

    /* Let the child run to the breakpoint and wait for it to
    ** reach it
    */
    ptrace(PTRACE_CONT, child_pid, 0, 0);

    //wait to breakpoint
    wait(&wait_status);
    if (WIFSTOPPED(wait_status)) {
        procmsg("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, &regs);
    procmsg("Child stopped at RIP = 0x%016x\n", regs.rip);

    /* 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.
    */
    int result = ptrace(PTRACE_POKETEXT, child_pid, (void*)addr, (void*)data);
    procmsg("poketext origin  back result %d\n", result);
/* See what's there again... */
     readback_data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)addr, 0);
     procmsg("After restore, data at 0x%llx: 0x%llx\n", addr, readback_data);
     int offset = 0;
     for(offset = 1; offset < 25; offset++) {
       readback_data = ptrace(PTRACE_PEEKTEXT, child_pid, (void*)(addr+offset), 0);
       procmsg("After restore, data at 0x%llx: 0x%llx\n", addr+offset, readback_data);
     }




    regs.rip -= 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)) {
        procmsg("Child exited\n");
    } else if(WIFSIGNALED(wait_status)) {
    procmsg("signal !!!\n");
    }
    else {
        procmsg("Unexpected signal. %s \n",  strsignal(WSTOPSIG(wait_status)));
    }
 } 

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)
        run_target(argv[1]);
    else if (child_pid > 0)
        run_debugger(child_pid);
    else {
        perror("fork");
        return -1;
    }

    return 0;
}

The output of the code above is :

[3220] debugger started
[3221] target started. will run 'Debugee1'
[3220] Child started. RIP = 0x0000000063fa1100
[3220] Original data at 0x08001169: 0xffffffff
[3220] test data_u: 0xffffffff
[3220] Data with trap : 0xffffffffffffffcc 
error : Bad address 
error : Bad address 
[3220] After trap,set breakpoint, data at 0x0000000008001169: 0xffffffffffffffff
Debugee program waiting 
Debugee program exit 
wait: Bad address

Now the problem is this line :

[3220] Original data at 0x08001169: 0xffffffff
[3220] After trap,set breakpoint, data at 0x0000000008001169: 0xffffffffffffffff

when i go read and after to write back the data with the int3 istruction (0xCC) and read back again the result is always 0xffffffffffffffff (aka -1 so the ptrace fail to read and write) I also know that that adress is correct beacuse i use objdump. some ideas ??

colo
  • 101
  • 8
  • 2
    On error ptrace returns -1 and sets errno. – stark Oct 27 '20 at 12:20
  • i check it and the result : *error : Bad address*, that's all. i also try to query it on google but with no result – colo Oct 27 '20 at 12:52
  • 1
    Why do you think addr contains a valid address? – stark Oct 27 '20 at 13:32
  • i use objdump utility in order to take the right address. – colo Oct 27 '20 at 13:45
  • I don't know about WSL, but on actual Linux, there is [ASLR](https://en.wikipedia.org/wiki/Address_space_layout_randomization) and the actual address at runtime will not match the addresses that appear in the binary. Try printing out some function addresses at runtime and see if they match what you found from objdump. – Nate Eldredge Oct 27 '20 at 13:47
  • https://stackoverflow.com/q/45493756/1216776 – stark Oct 27 '20 at 13:48
  • thanks @stark for you support and the link, and also thanks @ Nate, at this point how i can access to memory using ptrace if i can't know a priori where the program will loadead ? there is a way to know the address space address range during the execution ? – colo Oct 27 '20 at 14:05
  • Run in gdb, print the address, continue the program, then pass the address to your program as a command line argument. – stark Oct 27 '20 at 14:09
  • ok thanks @stark but how i can trace a program that is under gdb ? i should detach it from gdb and then attach it to my program with ptrace or i can archive both? – colo Oct 27 '20 at 14:13
  • You probably need to detach. A better way might be dlsym. See https://jvns.ca/blog/2018/01/09/resolving-symbol-addresses/ – stark Oct 27 '20 at 14:22
  • thanks, i will try both the solutions with gdb and i will post what happened – colo Oct 27 '20 at 14:44

0 Answers0