2016-02-20 67 views
0

我在使用Ptrace命中斷點後重置進程時遇到了問題。我本質上是用python包裝this code
我在64位Ubuntu上運行這個。Ptrace重置斷點

我理解在位置重置數據和遞減指令指針的概念,但在獲取陷阱信號並執行此操作後,我的過程並未完成。 代碼片段:

# 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

是否有錯誤的人看到我的斷點的代碼?

回答

0

我最後寫一個C程序,這是因爲確切的Python代碼儘可能的重複:

#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輸出後,我注意到,根據蟒蛇我的原始數據是0xfffffffffffe4be80x00000000fffe4be8
這使我相信我的返回數據被截斷爲32位值。

我改變了我的get和set方法是這樣的,返回類型設置爲空指針:

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) 

不能告訴你它是如何工作,但我能得到孩子進程在陷阱之後成功執行。