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

标签 c system-calls ls calloc ptrace

我一直在遵循一些关于如何使用 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的全部内容都是-1。这进一步表明我对 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] = '\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;
}

任何帮助将不胜感激!

最佳答案

感谢@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

关于c - 使用 ptrace 反转 ls 读数似乎不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40387270/

相关文章:

C - 在内存中创建文件

c - DEFINE_SPINLOCK(...) spinlock_t 参数错误

linux - 使用带有数值的系统调用有什么意义?

c - 使用系统调用打印结果

linux - 在 .sh bash 脚本文件中使用 awk

c - 如何处理 ls | C 中的 "pipe"命令

c - yy_top_state() 似乎因 flex 而失败

c - 关于 C 语言规范的文档

c++ - "Undefined Behavior"真的允许*任何事情*发生吗?

linux - 列出带有 .bar 扩展名但不带有 .foo.bar 扩展名的目录中的所有文件