2016-08-05 41 views
0

Ich arbeite an einer Linux-Anwendung, die ptrace enthält, um einen anderen Prozess zu beobachten, der durch den Systemaufruf fork() erstellt wurde.Wie man EIP's Tracee Forked Procee ändert?

Streng genommen: Ich möchte eine Fehlerinjektion in den gegabelten Prozess implementieren (chile process oder "tracee").

Wie Sie in der Abbildung unten sehen:

enter image description here

enter image description here

der Tracer wird die regs (struct_user_regs) Struktur von der Tracee von PTRACE_GETREGS Anfrage mit. Danach ändert der Tracer den EIP-Wert des Tracees (wenn der Kernel in tracee wechselt, wird die Reihenfolge der Ausführung gegen den sogenannten Kontrollflussfehler CFE verstoßen). dann sendet die PTRAC E_CONT-Anfrage an tracee, um die Ausführung fortzusetzen.

Leider, nach der Änderung der EPI-Tracee, führt das Tracee seine Ausführung aufgrund (Segmentierungsfehler) nicht fort. Wie kann ich dem Tracee EIP einen anderen geeigneten Wert geben?

hier ist der Code

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include<sys/user.h> 
#include<sys/reg.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include <asm/ptrace-abi.h> 

int main() 

{ 

    pid_t child; 
    int status; 
    int sum=0; 
    struct user_regs_struct regs; 


    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 

     printf("hello world 1\n"); 
     printf("hello world 2\n"); 
     raise (SIGINT); // just to move control to the tracer 
     printf("hello world 3\n"); 
     printf("hello world 4\n"); 
     printf("hello world 5\n"); 

     exit(EXIT_SUCCESS); 
    } 
    else { 

      wait(NULL); 
      ptrace(PTRACE_GETREGS, child,NULL, &regs); 
      printf("\n EIP @ 0x %#lx\n",regs.eip); 
      //get the tracee EIP 
      long int new_eip=ptrace(PTRACE_PEEKTEXT, child,regs.eip,NULL); 
      //chabge EIP and poke it again 
      new_eip += ???; // make change that let to jump to another tracee instruction address (say to print hello world 5) 
      ptrace(PTRACE_POKETEXT, child,regs.eip,new_eip); 
      ptrace(PTRACE_CONT, child, NULL, NULL); 

      } 

    return 0; 
} 

Irgendwelche Gedanken? Vielen Dank für Ihre Hilfe.

+0

Sie müssen Ihren Code anzeigen, wenn Sie erwarten, dass jemand herausfindet, was Sie falsch machen. – Barmar

+0

@Barmar, Code wurde hinzugefügt :) –

+0

Mit dem Debugger wie Gdb oder Qt Debugger kann ich nicht die Tracee debuggen. –

Antwort

1

Sie ändern die EIP nicht, Sie fügen dem Wert der Anweisung bei EIP etwas hinzu und führen möglicherweise zu einer falschen Adressreferenz. Um EIP zu ändern, verwenden PTRACE_SETREGS

 wait(NULL); 
     ptrace(PTRACE_GETREGS, child,NULL, &regs); 
     printf("\n EIP @ 0x %#lx\n",regs.eip); 
     regs.eip += ???; 
     ptrace(PTRACE_SETREGS, child, NULL, &regs); 
     ptrace(PTRACE_CONT, child, NULL, NULL); 
+0

Ja, Sie haben Recht. Aber was ist der geeignete Wert, um es zum EIP hinzuzufügen, um auf den nächsten oder einen beliebigen Befehl zu zeigen. Ich habe es versucht: unsigned instruction_ = ptrace (PTRACE_PEEKTEXT, Kind, regs.eip.NULL); dann, regs.eip + = sizeof (Anweisung); Ich erklärte auch die Anweisung_ als lang int, aber es hat auch nicht funktioniert. –

+0

Fügen Sie die Anzahl der Bytes in einer Anweisung hinzu. Das hängt von der CPU-Architektur ab und hängt sogar davon ab, was der Befehl an der aktuellen EIP ist, wenn die Anweisungen unterschiedliche Längen haben. – Barmar

0

Ja, es ist völlig plattformspezifisch. Ich habe viele Materialien gelesen, die ptrace syscall beschrieben haben und wie wir es verwenden können, um die EIP der nächsten Anweisung zu erfassen, die ausgeführt wird, nachdem ptrace eine Anfrage (wie PTRACE_CONT) an die suspendierte Spur gesendet hat. Ich sehe immer, dass der EIP-Wert so etwas wie diese:

80484a6: 
80484a7: 
80484ac: 
80484b2: 
80484b4: 
80484b6: 
80484b8: 

ich einen einfachen Code testen (nur den Wert von EIP drucken und dem entsprechenden ausgeführten Befehl). aber das Ergebnis war, wie Sie weiter unten:

EIP: b773cbe0 Instruction executed: c3595a5d 
EIP: b773cbe1 Instruction executed: ccc3595a 
EIP: b773cbe0 Instruction executed: c3595a5d 
hello world 5 
EIP: b773cbe0 Instruction executed: c3595a5d 
EIP: b773cbe1 Instruction executed: ccc3595a 
EIP: b773cbe0 Instruction executed: c3595a5d 
hello world 6 
EIP: b773cbe0 Instruction executed: c3595a5d 
EIP: b773cbe1 Instruction executed: ccc3595a 
EIP: b773cbe0 Instruction executed: c3595a5d 

, was das ist (b773cbe0) ?? !!! zog ich die Dump-Datei mit dieser Befehlszeile (objdump -d a.out) das Ergebnis etwas anders mit früheren Ergebnissen

8048864: 8b 6c 24 20    mov 0x20(%esp),%ebp 
8048868: 8d b3 0c ff ff ff  lea -0xf4(%ebx),%esi 
804886e: e8 41 fb ff ff   call 80483b4 <_init> 
8048873: 8d 83 08 ff ff ff  lea -0xf8(%ebx),%eax 
8048879: 29 c6     sub %eax,%esi 
804887b: c1 fe 02    sar $0x2,%esi 
804887e: 85 f6     test %esi,%esi 
8048880: 74 23     je  80488a5 <__libc_csu_init+0x55> 
8048882: 8d b6 00 00 00 00  lea 0x0(%esi),%esi 
8048888: 83 ec 04    sub $0x4,%esp 
804888b: ff 74 24 2c    pushl 0x2c(%esp) 
804888f: ff 74 24 2c    pushl 0x2c(%esp) 
8048893: 55      push %ebp 
8048894: ff 94 bb 08 ff ff ff call *-0xf8(%ebx,%edi,4) 
804889b: 83 c7 01    add $0x1,%edi 
804889e: 83 c4 10    add $0x10,%esp 
80488a1: 39 f7     cmp %esi,%edi 
80488a3: 75 e3     jne 8048888 <__libc_csu_init+0x38> 
80488a5: 83 c4 0c    add $0xc,%esp 
80488a8: 5b      pop %ebx 
80488a9: 5e      pop %esi 
80488aa: 5f      pop %edi 
80488ab: 5d      pop %ebp 
80488ac: c3      ret  
80488ad: 8d 76 00    lea 0x0(%esi),%esi 

Ich bin wirklich verwirrt über diese GDB und angesehen.

+0

@Barmar, was ist das (b773cbe0)? und warum gibt es ein anderes Ergebnis? –