【问题标题】:Save the changes of ptrace() PTRACE_POKEDATA call保存 ptrace() PTRACE_POKEDATA 调用的更改
【发布时间】:2017-04-09 00:52:00
【问题描述】:

我正在使用ptrace(PTRACE_POKETEXT, pid, addr, (orig ^ flip_mask)); 来更改实时进程的数据,但是一旦调用终止,所做的更改就会消失,即使在终止之后也可以永久保留PTRACE_POKETEXT 更改ptrace 电话?

void run_pro1 (pid_t child_pid) {
    srand(time(0));    
    int wait_status;
    unsigned icounter = 0;
    procmsg("debugger started\n");
    wait(&wait_status); 
    while (WIFSTOPPED(wait_status)) {
        icounter++;
        struct user_regs_struct regs;
        ptrace(PTRACE_GETREGS, child_pid, 0, &regs);       
        unsigned instr = ptrace(PTRACE_PEEKTEXT, child_pid,  regs.rax , 0);      
        unsigned *instr3 ;
        instr3 = &instr;                           
        unsigned instr2 = instr ^ (1UL << (1 << (rand()%32)));         
        ptrace(PTRACE_POKETEXT, child_pid, instr, instr2);        
        unsigned *instr4 ;
        instr4 = &instr2;        
        cout<<"addrctn="<< *instr3 <<endl;
        cout<<"addrctn="<< *instr4 <<endl; 
       if (ptrace(PTRACE_SINGLESTEP, child_pid, 0, 0) < 0) {
            perror("ptrace");
            return;
        }        /* Wait for child to stop on its next instruction */
        ptrace(PTRACE_CONT, child_pid, 0, 0);
        wait(&wait_status);             //break;      
    }   
    procmsg("the child executed %u instructions\n", icounter);
}

【问题讨论】:

  • 更改不应消失。
  • 它消失的唯一原因是您戳的过程重新分配了变量。您必须更改该过程的代码以防止这种情况发生。
  • 您能否展示您正在跟踪的进程的代码以及您如何使用ptrace?
  • 亲爱的 Barmar,非常感谢您的回复,我刚刚发布了跟踪子 pid 的跟踪器进程的代码
  • “永久”是什么意思?

标签: c++ operating-system ptrace


【解决方案1】:

我认为,您的主要问题是您调用 ptrace 两次。第一次传递PTRACE_SINGLESTEP 时,它告诉它只继续一条指令。然而,紧接着你调用PTRACE_CONT,它告诉它继续直到下一个信号。最终结果是您的程序根本没有单步执行。它只是运行。

您的代码存在几个次要问题。首先是你总是用零作为信号参数调用这两个函数。实际上,您正在屏蔽来自程序的信号。

此外,您正在调用 PEEK 和 POKE TEXT,并将其存储在名为“instr”的变量中。所有这些都没有任何区别,但它们建议您认为您正在处理指令。您从中读取的内存来自rax,它很少指向指令,并且可能通常根本不指向任何映射的东西。这也意味着您可能正在做一些与您认为自己正在做的事情不同的事情,这可能是您的问题的原因。

【讨论】:

  • 亲爱的Shacshar,能否请您用代码写下您的建议,非常感谢,因为我尝试了您所说的,但子进程仍然没有显示任何更改
【解决方案2】:

POKETEXT 的参数是错误的。第三个参数应该是一个地址,但你给了instr,这是旧值,而不是读取它的地址。要替换您读取的值,它应该是:

ptrace(PTRACE_POKETEXT, child_pid, regs.rax, instr2);

Schachar Shemesh 在他的回答中也有很好的观点,但我认为这解决了你所问的具体问题。

【讨论】:

  • 亲爱的Barmar,我已经尝试过你的建议,但仍然没有保存更改,子进程运行没有问题
  • 我不知道RAX这个寄存器是干什么用的,你确定这是要戳的正确地址吗?
  • 我尝试修改以下寄存器:AL/AH/AX/EAX/RAX:累加器 BL/BH/BX/EBX/RBX:基本索引(用于数组)CL/CH/CX /ECX/RCX:计数器(用于循环和字符串) DL/DH/DX/EDX/RDX:扩展累加器的精度(例如结合 32 位 EAX 和 EDX 用于 32 位代码中的 64 位整数运算) .CS: 代码 DS: 数据 SS: 堆栈 ES: 额外数据 FS: 额外数据 #2 GS: 额外数据 #3
  • 如果要修改程序,应使用Program Counter寄存器作为地址。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
  • 2012-11-01
  • 2014-08-12
  • 1970-01-01
  • 2012-06-21
  • 2013-01-16
相关资源
最近更新 更多