简体   繁体   中英

Using ptrace to reverse ls readout doesn't seem to work

I've been following some instructions on how to use ptrace that are found here . I am on ubuntu 14.04, x64, and I have been altering bits of the example code to work with my x64 machine, such as eax to rax, and changing 4s to 8s where appropriate. The forth example is supposed to reverse the output of ls, but it does not. I get this:

bin       Debugger.depend  dummy1.s       main_tut2.cpp  main_tut4.cpp  obj
Debugger.cbp  Debugger.layout  main_tut1.cpp  main_tut3.cpp  main_tut5.cpp
bin       Debugger.depend  dummy1.s       main_tut2.cpp  main_tut4.cpp  obj
Debugger.cbp  Debugger.layout  main_tut1.cpp  main_tut3.cpp  main_tut5.cpp

And I believe I should be getting it reversed if my code works correctly, something like this:

jbo ppc.4tut_niam ppc.2tut_niam s.1ymmud dneped.reggubeD nib
ppc.5tut_niam ppc.3tut_niam ppc.1tut_niam tuoyal.reggubeD pbc.reggubeD
jbo ppc.4tut_niam ppc.2tut_niam s.1ymmud dneped.reggubeD nib
ppc.5tut_niam ppc.3tut_niam ppc.1tut_niam tuoyal.reggubeD pbc.reggubeD

I have found an error in the code printed in the page I linked above ( here ) which is 20 lines up from the bottom in my code, but I think I have corrected that. This is the incorrect line:

                str = (char *)calloc((params[2] + 1) * sizeof(char));

It has one arguement but needs two. I believe it should be:

                str = (char *)calloc(params[2] + 1, (params[2] + 1) * sizeof(char));

But if I have that wrong, I would be happy to be corrected. I also tried:

                str = (char *)calloc(1, (params[2] + 1) * sizeof(char));

I'm still not sure which would be correct, if either...

Is this the reason why it's not working? Or is it something else, maybe another problem relating to being on x64 that I haven't accounted for? Bonus points for anyone who can tell me what calloc is doing in this instance and why the second arguement is as it is.

EDIT:

I have just tried printing str both before and after the reversal... it's just a bunch of question marks. When I debug, it seems the entire contents of str is -1s. This further suggests that something is wrong with my call to calloc()...

Anyway, here is my version of the code:

#include <iostream>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>         // For fork()
//#include <linux/user.h>   // For constants ORIG_EAX for 32bit etc
#include <sys/user.h>       // For constants ORIG_RAX for 64bit etc
#include <sys/reg.h>
#include <sys/syscall.h>    // For SYS_write etc
#include <cstring>          // For strlen()

/** ptrace(enum __ptrace_request,   // behaviour of ptrace
           pid_t pid,               // Process ID
           void *addr,              // Address to read in user area
           void *data);             //
**/

/**
PTRACE_TRACEME,   PTRACE_PEEKTEXT, PTRACE_PEEKDATA, PTRACE_PEEKUSER,   PTRACE_POKETEXT,
PTRACE_POKEDATA,  PTRACE_POKEUSER, PTRACE_GETREGS,  PTRACE_GETFPREGS,  PTRACE_SETREGS,
PTRACE_SETFPREGS, PTRACE_CONT,     PTRACE_SYSCALL,  PTRACE_SINGLESTEP, PTRACE_DETACH
**/

const int long_size = sizeof(long);

void reverse(char *str) {

    int i, j;
    char temp;

    for (i = 0, j = strlen(str) - 2; i <= j; i++, j--) {
        temp = str[i];
        str[i] = str[j];
        str[j] = temp;
    }
}

void getData(pid_t child, long addr, char *str, int len) {

    char *laddr;
    int i, j;
    union u {
        long val;
        char chars[long_size];
    } data;

    i = 0;
    j = len / long_size;
    laddr = str;

    while(i < j) {
        data.val = ptrace(PTRACE_PEEKDATA, child, addr + i * 8, NULL);
        memcpy(laddr, data.chars, long_size);
        i++;
        laddr += long_size;
    }

    j = len % long_size;

    if (j != 0) {
        data.val = ptrace(PTRACE_PEEKDATA, child, addr + i * 8, NULL);
        memcpy(laddr, data.chars, j);
    }

    str[len] = '\0';
}

void putData(pid_t child, long addr, char *str, int len) {

    char *laddr;
    int i, j;
    union u {
        long val;
        char chars[long_size];
    } data;

    i = 0;
    j = len / long_size;
    laddr = str;

    while(i < j) {
        memcpy(data.chars, laddr, long_size);
        ptrace(PTRACE_POKEDATA, child, addr + i * 8, data.val);
        i++;
        laddr += long_size;
    }

    j = len % long_size;

    if (j != 0) {
        memcpy(data.chars, laddr, j);
        ptrace(PTRACE_POKEDATA, child, addr + i * 8, data.val);
    }
}

int main()
{
    pid_t child;
    child = fork();

    if (child == 0) {

        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl("/bin/ls", "ls", NULL);

    } else {

        long orig_rax;
        long params[3];
        int status;
        char *str, *laddr;
        int toggle = 0;

        while(1) {

            wait(&status);
            if (WIFEXITED(status))
                break;

            orig_rax = ptrace(PTRACE_PEEKUSER, child, 8 * ORIG_RAX, NULL);

            if (orig_rax == SYS_write) {

                if (toggle == 0) {

                    toggle = 1;
                    params[0] = ptrace(PTRACE_PEEKUSER, child, 8 * RBX, NULL);
                    params[1] = ptrace(PTRACE_PEEKUSER, child, 8 * RCX, NULL);
                    params[2] = ptrace(PTRACE_PEEKUSER, child, 8 * RDX, NULL);
                    str = (char *)calloc(params[2] + 1, (params[2] + 1) * sizeof(char));

                    getData(child, params[1], str, params[2]);
                    reverse(str);
                    putData(child, params[1], str, params[2]);

                } else {

                    toggle = 0;
                }
            }

            ptrace(PTRACE_SYSCALL, child, NULL, NULL);
        }
    }

    execl("/bin/ls", "ls", NULL);

    return 0;
}

Any assistance would be greatly appreciated!

So thanks to @melpmene and @MarkPlotnick for the answers. I have struggled to figure out some of the other answers covering the same topic, and another resource I found that suggested how to convert the x32 code to x64 code wasn't entirely accurate (at least for my system), so here is what I needed to do:

1)

str = (char *)calloc(params[2] + 1 * sizeof (char))

should be

str = (char *)calloc(params[2] + 1, sizeof (char))

2)

EBX, ECX and EDX should be replaced by RDI, RSI and RDX

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM