c - 跟踪过程的寄存器值没有改变

标签 c linux ptrace

我正在尝试读取正在运行的进程的寄存器值。这是我要跟踪的过程的代码:

#include <stdio.h>

int x=0;

int main(){
    while(1){
        x++;
        printf("%d\n",x);
    }
    return 0;
}

这是我用来执行此操作的 ptrace 程序:

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

void dumpRegs(int pid){
    printf("------------------------\n");
    struct user_regs_struct regs;
    ptrace(PTRACE_GETREGS,pid,NULL, &regs);
    printf("rbx: %lx.\n", regs.rbx);
    printf("r15: %lx.\n",regs.r15);
    printf("r14: %lx.\n",regs.r14);
    printf("r13: %lx.\n",regs.r13);
    printf("r12: %lx.\n",regs.r12);
    printf("rbp: %lx.\n",regs.rbp);
    printf("rbx: %lx.\n",regs.rbx);
    printf("r11: %lx.\n",regs.r11);
    printf("r10: %lx.\n",regs.r10);
    printf("r9: %lx.\n",regs.r9);
    printf("r8: %lx.\n",regs.r8);
    printf("rax: %lx.\n",regs.rax);
    printf("rcx: %lx.\n",regs.rcx);
    printf("rdx: %lx.\n",regs.rdx);
    printf("rsi: %lx.\n",regs.rsi);
    printf("rdi: %lx.\n",regs.rdi);
    printf("orig_rax: %lx.\n",regs.orig_rax);
    printf("rip: %lx.\n",regs.rip);
    printf("cs: %lx.\n",regs.cs);
    printf("eflags: %lx.\n",regs.eflags);
    printf("rsp: %lx.\n",regs.rsp);
    printf("ss: %lx.\n",regs.ss);
    printf("fs_base: %lx.\n",regs.fs_base);
    printf("gs_base: %lx.\n",regs.gs_base);
    printf("ds: %lx.\n",regs.ds);
    printf("es: %lx.\n",regs.es);
    printf("fs: %lx.\n",regs.fs);
    printf("gs: %lx.\n",regs.gs);
}

int main(int argc, char **argv){
    printf("begin\n");
    int pid=atoi(argv[1]);//the pid of the process
    int status;
    ptrace(PTRACE_ATTACH,pid);//attach to process
    waitpid(pid,&status,0);

    do{
        ptrace(PTRACE_SINGLESTEP,pid);
        dumpRegs(pid);
    }while(getchar()!='q');

    ptrace(PTRACE_DETACH,pid);//attach to process
    printf("end\n");

    return 0;
}

代码很好地附加到进程上,我可以看出来,因为它停止打印 x 的值,而且我也可以在 top 和 htop 中看到它,但无论 do...while 循环有多少次迭代通过,dumpRegs 的输出保持不变。我认为即使在这样一个简单的过程中,至少有一些寄存器会改变它们的值,所以我想我一定是做错了什么。我已经在下方发布了输出示例。

输出:

rbx: 9.
r15: 9.
r14: 7ff23e124600.
r13: 1.
r12: 9.
rbp: 559d2ee03010.
rbx: 9.
r11: 246.
r10: 64.
r9: 8.
r8: 1.
rax: fffffffffffffe00.
rcx: 7ff23de65730.
rdx: 9.
rsi: 559d2ee03010.
rdi: 1.
orig_rax: 1.
rip: 7ff23de65730.
cs: 33.
eflags: 246.
rsp: 7ffcee0ce6f8.
ss: 2b.
fs_base: 7ff23e318700.
gs_base: 0.
ds: 0.
es: 0.
fs: 0.
gs: 0.

我在 64 位 Debian 上运行它并使用 gcc 进行编译。

最佳答案

我是这样调用 ptrace 的:

ptrace(PTRACE_SINGLESTEP,pid);

但是需要这样调用:

ptrace(PTRACE_SINGLESTEP,pid,NULL,NULL);

如果您不包含 NULL 参数,PTRACE_SINGLESTEP 将返回 -1。 我还在分离之前添加了一个 PTRACE_CONT。

这是更新后的代码:

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

int x=0;

void dumpRegs(int pid){
    printf("------------------------\n");
    printf("%d\n",x);
    struct user_regs_struct regs;
    ptrace(PTRACE_GETREGS,pid,NULL, &regs);
    printf("cs: %lx.\n",regs.cs);
    printf("ds: %lx.\n",regs.ds);
    printf("eflags: %lx.\n",regs.eflags);
    printf("es: %lx.\n",regs.es);
    printf("fs: %lx.\n",regs.fs);
    printf("fs_base: %lx.\n",regs.fs_base);
    printf("gs: %lx.\n",regs.gs);
    printf("gs_base: %lx.\n",regs.gs_base);
    printf("orig_rax: %lx.\n",regs.orig_rax);
    printf("r10: %lx.\n",regs.r10);
    printf("r11: %lx.\n",regs.r11);
    printf("r12: %lx.\n",regs.r12);
    printf("r13: %lx.\n",regs.r13);
    printf("r14: %lx.\n",regs.r14);
    printf("r15: %lx.\n",regs.r15);
    printf("r8: %lx.\n",regs.r8);
    printf("r9: %lx.\n",regs.r9);
    printf("rax: %lx.\n",regs.rax);
    printf("rbp: %lx.\n",regs.rbp);
    printf("rbx: %lx.\n", regs.rbx);
    printf("rbx: %lx.\n",regs.rbx);
    printf("rcx: %lx.\n",regs.rcx);
    printf("rdi: %lx.\n",regs.rdi);
    printf("rdx: %lx.\n",regs.rdx);
    printf("rip: %lx.\n",regs.rip);
    printf("rsi: %lx.\n",regs.rsi);
    printf("rsp: %lx.\n",regs.rsp);
    printf("ss: %lx.\n",regs.ss);
}

int main(int argc, char **argv){
    printf("begin\n");
    int pid=atoi(argv[1]);//the pid of the process
    int status;
    ptrace(PTRACE_ATTACH,pid);//attach to process
    waitpid(pid,&status,0);

    do{
        x++;
        printf("%d",ptrace(PTRACE_SINGLESTEP,pid,NULL,NULL));
        dumpRegs(pid);
    }while(getchar()!='q');

    printf("%d",ptrace(PTRACE_CONT,pid,NULL,NULL));
    ptrace(PTRACE_DETACH,pid);//attach to process
    printf("end\n");

    return 0;
}

关于c - 跟踪过程的寄存器值没有改变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51575582/

相关文章:

c++ - Windows WMI - 获取多个 MAC 地址

linux - Shell脚本在特定时间杀死进程,输入进程名称和时间

linux - 如何从存储库生成 .deb 包

php - 通过绝对路径在 PHP 中包含文件的问题

c - 在开始时停止子进程

c - 在 GCC 中实现编译时只读函数指针表

C 数组声明语法

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

检查 C 中的 soduku,为什么我的代码不起作用?

c++ - GDB strace 显示它尝试在无效地址进行 ptrace