c - ptrace(PTRACE_PEEKDATA, ...) 错误 : data dump

标签 c linux ubuntu ptrace

我想从正在运行的进程中获取指令并使用 ptrace 更改它。当变量 instr(包含当前指令 - PTRACE_PEEKDATA)未签名时一切正常,但当我将其更改为 long int 时出现错误(内存转储)。 ptrace(PTRACE_PEEKDATA, ...) 返回 long int 所以这应该不是问题。我在 Ubuntu 上工作。

我哪里做错了?我是新手,所以这可能会很愚蠢。

我的代码:

#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <stdlib.h>
#include <wait.h>

int main()
{
    int status; 
    char *pid_char;
    pid_t PID;
    struct user_regs_struct  reg; /* register */
    long int instr;
    unsigned changedInstr;


    printf("Tracee PID: ");
    scanf("%s", pid_char);
    PID = atoi(pid_char);
    printf("\n");

    /* PTRACE STARTS */
    ptrace(PTRACE_ATTACH, PID, NULL, NULL);
    waitpid(PID, &status, 0); 

    ptrace(PTRACE_GETREGS, PID, NULL, &reg);

    instr = ptrace(PTRACE_PEEKDATA, PID, reg.rip, NULL);
    printf("Current Instruction: %llx\n", instr);

    scanf("%u", &changedInstr);
    ptrace(PTRACE_POKEDATA, PID, reg.rip, &changedInstr);

    ptrace(PTRACE_DETACH, PID, NULL, NULL);

    return 0;
}

最佳答案

在 x86_64 上,PTRACE_PEEKDATA 返回 8 个字节,PTRACE_POKEDATA 从其 addr 参数指向的地址开始传输 8 个字节。 使用 long 或 unsigned long 应该没问题。

如果附加到 nanosleep 系统调用中的进程,指令流如下所示:

(gdb) disass /r
Dump of assembler code for function __nanosleep_nocancel:
   0x00007ffff7ad92e9 <+0>: b8 23 00 00 00  mov    $0x23,%eax
   0x00007ffff7ad92ee <+5>: 0f 05   syscall 
=> 0x00007ffff7ad92f0 <+7>: 48 3d 01 f0 ff ff   cmp    $0xfffffffffffff001,%rax
   0x00007ffff7ad92f6 <+13>:    73 31   jae    0x7ffff7ad9329 <nanosleep+73>
   0x00007ffff7ad92f8 <+15>:    c3  retq  

执行完 instr = ptrace(PTRACE_PEEKDATA, PID, reg.rip, NULL);, instr 如果是 unsigned long 则为 3173fffff0013d48,如果是 unsigned long 则为 f0013d48

在您的程序中,changedInstr 是无符号的,ptrace(PTRACE_POKEDATA, PID, reg.rip, &changedInstr); 将传输 的 4 个字节changedInstr 后跟堆栈上与其相邻的任何内容的 4 个字节,可能是其他局部变量的一部分。如您所见,这 4 个字节可能是无害的或会使目标进程出现异常的内容。

在这种情况下,如果您想在 reg.rip 中编写 4 字节指令,应该这样做

unsigned changedInstr;
...
instr = ptrace(PTRACE_PEEKDATA, PID, reg.rip, NULL);
scanf("%u", &changedInstr);
instr = (instr & ~0xFFFFFFFFul) | changedInstr
ptrace(PTRACE_POKEDATA, PID, reg.rip, &instr);

关于c - ptrace(PTRACE_PEEKDATA, ...) 错误 : data dump,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53213591/

相关文章:

c - 使用 openssl C API 解析 asn1 文档

c - 帮助系统的数据库或格式?

c - 如何检查文件描述符是否有任何可用数据?

c++ - rdtsc 计时器在 linux 中不准确吗?

linux - 将 tmpfs 视为 grep 的设备

java - 该方法必须覆盖父类(super class)方法

postgresql - 如何从 Ubuntu 命令行将用户添加到 PostgreSQL?

python - Pycharm Professional 与 WSL : Cannot read environment variables set with ~/. 配置文件

c - 在 C 中实现回溯时如何知道参数的数量

linux - 了解 access_process_vm linux 内核?