使用 ptrace 反转 ls 读数似乎不起作用

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

我一直在遵循找到的一些关于如何使用 ptrace 的说明 here。我在 ubuntu 14.04,x64 上,我一直在更改示例代码的一些位以适用于我的 x64 机器,例如将 eax 更改为 rax,并在适当的地方将 4s 更改为 8s。第四个示例应该反转 ls 的输出,但它没有。我明白了:

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

而且我相信如果我的代码可以正常工作,我应该将其撤消,如下所示:

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

我发现在我上面链接的页面 (here) 中打印的代码有一个错误,该错误在我的代码中从底部向上 20 行,但我想我已经更正了。这是错误的行:

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

它有一个参数但需要两个。我认为应该是:

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

但如果我有错,我很乐意得到纠正。我也试过:

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

我仍然不确定哪个是正确的,如果...

这是它不起作用的原因吗?或者是其他问题,也许是另一个我没有考虑到的与 x64 相关的问题?如果有人能告诉我 calloc 在这种情况下做了什么,以及为什么第二个争论是这样的,任何人都会加分。

编辑:

我刚刚尝试在反转之前和之后都打印 str ...它只是一堆问号。当我调试时,似乎 str 的全部内容都是 -1s。这进一步表明我对 calloc()...

的调用有问题

无论如何,这是我的代码版本:

#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] = '[=15=]';
}

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;
}

如有任何帮助,我们将不胜感激!

感谢@melpmene 和@MarkPlotnick 的回答。我一直在努力找出涵盖同一主题的其他一些答案,而我发现的另一个资源建议如何将 x32 代码转换为 x64 代码并不完全准确(至少对于我的系统而言),所以这就是我需要做的事情:

1)

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

应该是

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

2)

EBX、ECX 和 EDX 应替换为 RDI、RSI 和 RDX