【问题标题】:Ptrace reset a breakpointPtrace 重置断点
【发布时间】:2016-02-20 23:41:04
【问题描述】:

在使用 Ptrace 达到断点后,我无法重置进程。我基本上是在 python 中包装 this code
我在 64 位 Ubuntu 上运行它。

我理解在该位置重置数据并递减指令指针的概念,但是在我得到陷阱信号并这样做之后,我的过程还没有完成。 代码sn-p:

# Continue to bp
res = libc.ptrace(PTRACE_CONT,pid,0,0)
libc.wait(byref(wait_status))

if _wifstopped(wait_status):
    print('Breakpoint hit. Signal: %s' % (strsignal(_wstopsig(wait_status))))
else:
    print('Error process failed to stop')
    exit(1)

# Reset Instruction pointer
data = get_registers(pid)
print_rip(data)
data.rip -= 1
res = set_registers(pid,data)

# Verify rip
print_rip(get_registers(pid))
# Reset Instruction
out = set_text(pid,c_ulonglong(addr),c_ulonglong(initial_data))

if out != 0:
    print_errno()

print_text(c_ulonglong(addr),c_ulonglong(get_text(c_void_p(addr))))

我从这段代码返回后立即运行 PTRACE_DETACH。 当我运行它时,它会命中父进程成功返回的断点,但子进程不会恢复并完成其代码。 如果我注释掉对断点函数的调用,它只是将 ptrace 附加到进程,然后将其分离,程序运行良好。
该程序本身只是一个小型 c 程序,可以打印 10 次到一个文件。

Full code is in this paste

有人看到我的断点代码有错误吗?

【问题讨论】:

    标签: python-3.x ctypes ptrace


    【解决方案1】:

    我最终编写了一个与 python 代码尽可能完全相同的 C 程序:

    #include <stdio.h>
    #include <stdarg.h>
    #include <stdlib.h>
    #include <string.h>
    #include <signal.h>
    #include <syscall.h>
    #include <sys/ptrace.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/reg.h>
    #include <sys/user.h>
    #include <unistd.h>
    #include <errno.h>
    #include <time.h>
    
    void set_unset_bp(pid){
            int wait_status;
            struct user_regs_struct regs;
            unsigned long long addr = 0x0000000000400710;
            unsigned long long data = ptrace(PTRACE_PEEKTEXT,pid,(void *)addr,0);
            printf("Orig data: 0x%016x\n",data);
            unsigned long long trap = (data & 0xFFFFFFFFFFFFFF00) | 0xCC;
            ptrace(PTRACE_POKETEXT,pid,(void *)addr,(void *)trap);
            ptrace(PTRACE_CONT,pid,0,0);    
            wait(&wait_status);
            if(WIFSTOPPED(wait_status)){
                    printf("Signal recieved: %s\n",strsignal(WSTOPSIG(wait_status)));
            }else{
                    perror("wait");
            }
    
            ptrace(PTRACE_POKETEXT,pid,(void *)addr,(void *)data);
            ptrace(PTRACE_GETREGS,pid,0,&regs);
            regs.rip -=1;
            ptrace(PTRACE_SETREGS,pid,0,&regs);
            data = ptrace(PTRACE_PEEKTEXT,pid,(void *)addr,0);
            printf("Data after resetting bp data: 0x%016x\n",data);
            ptrace(PTRACE_CONT,pid,0,0);
    }
    
    int main(void){
            //Fork child process
            extern int errno;
            int pid = fork();
            if(pid ==0){//Child
                    ptrace(PTRACE_TRACEME,0,0,0);   
                    int out = execl("/home/chris/workspace/eliben-debugger/print","/home/chris/workspace/eliben-debugger/print",0);
                    if(out != 0){ 
                            printf("Error Value is: %s\n", strerror(errno));
                    }
            }else{ //Parent
    
                    wait(0);
                    printf("Got stop signal, we just execv'd\n");
                    set_unset_bp(pid);
                    printf("Finished setting and unsetting\n");    
                    wait(0);
                    printf("Got signal, detaching\n");
                    ptrace(PTRACE_DETACH,pid,0,0);
                    wait(0);
                    printf("Parent exiting after waiting for child to finish\n");
            }
            exit(0);    
    }  
    

    在将输出与我的 Python 输出进行比较后,我注意到根据 python,我的原始数据是 0xfffffffffffe4be80x00000000fffe4be8
    这让我相信我的返回数据被截断为 32 位值。

    我将 get 和 set 方法更改为类似这样,将返回类型设置为 void 指针:

    def get_text(addr):
        restype = libc.ptrace.restype
        libc.ptrace.restype = c_void_p
        out = libc.ptrace(PTRACE_PEEKTEXT,pid,addr, 0)
        libc.ptrace.restype = restype
        return out
    
    def set_text(pid,addr,data):
        return libc.ptrace(PTRACE_POKETEXT,pid,addr,data)
    

    还不能告诉你它是如何工作的,但我能够让子进程在陷阱之后成功执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-05
      相关资源
      最近更新 更多