2016-02-20 4 views
0

J'ai des difficultés à réinitialiser un processus après avoir atteint un point d'arrêt avec Ptrace. Je suis essentiellement l'emballage this code en python.
Je cours cela sur Ubuntu 64 bits.Ptrace réinitialise un point d'arrêt

Je comprends le concept de réinitialiser les données à l'emplacement et décrémenter le pointeur d'instruction, mais après avoir reçu le signal de piège et faire cela, mon processus ne se termine pas. Extrait de code:

# 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)))) 

Et je lance un PTRACE_DETACH juste après le retour de ce code. Lorsque je l'exécute, il atteint le point d'arrêt que le processus parent renvoie avec succès, mais l'enfant ne reprend pas et ne termine pas son code. Si je commente l'appel à la fonction breakpoint, il attache simplement ptrace au processus, puis le détache, et le programme s'exécute correctement.
Le programme lui-même est juste un petit programme c qui imprime 10 fois dans un fichier.

Full code is in this paste

Y at-il une erreur voit quelqu'un avec mon code de point d'arrêt?

Répondre

0

Je fini par écrire un programme C qui était aussi exacte un double du code python possible:

#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);  
} 

Après avoir comparé la sortie à ma sortie de Python, j'ai remarqué que, selon python mes données d'origine était 0xfffffffffffe4be8 et 0x00000000fffe4be8. Cela m'a amené à croire que mes données de retour étaient tronquées à une valeur de 32 bits.

j'ai changé méthodes get et set à quelque chose comme cela, la définition du type de retour à un pointeur vide:

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) 

ne peux pas vous dire comment cela fonctionne, mais je suis en mesure d'obtenir l'enfant processus s'exécutant avec succès après le piège.