首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Ptrace重置断点

Ptrace重置断点
EN

Stack Overflow用户
提问于 2016-02-21 07:41:05
回答 1查看 258关注 0票数 0

在使用Ptrace命中断点后,我在重置进程时遇到了问题。我实际上是在用python包装this code

我在64位的Ubuntu上运行这个程序。

我理解重置该位置的数据并递减指令指针的概念,但在我收到陷阱信号并执行此操作后,我的进程并未结束。代码片段:

代码语言:javascript
复制
# 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

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

EN

回答 1

Stack Overflow用户

发布于 2016-02-23 10:45:58

我最终写了一个C程序,尽可能精确地复制python代码:

代码语言:javascript
复制
#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

我将get和set方法改为如下所示,将返回类型设置为void指针:

代码语言:javascript
复制
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)

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35530469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档