2017-12-07 3 views
0

Letztes Mal versuche ich einfache genetische Fuzzer zu schreiben (unter strikten Mac OS, nur zum Spaß). Meine Idee ist so etwas wie die:Mac OS (10.13.1) task_for_pid für gegabelten Prozess "(os/kern) failure"

-> Hauptprogramm, das Verfahren

Gabelsteuerung - Binärcode> gegabelt Prozesslast von der Festplatte und springen hinein.

-> Eltern für Aufgabe fragen (task_for_pid (mach_task_self(), childPID, & Aufgabe))

-> Eltern versuchen, Fallen zu fangen (0xcc), zu überprüfen, ob wir es vorher gewesen war, genau wie AFL Werke (natürlich vereinfacht)

-> Kind lädt einige rohe Binärcode (in meinem Beispiel hat System V ABI sein)

-I-Fehler erhalten, wie unten:

16:10|domin568[15] ~/Desktop/experiments/Instrumentation $ ./run.sh 
PARENT 3866 
task_for_pid() failed with message (os/kern) failure ! 
CHILD 3867 

run.sh:

#!/bin/sh 
clang -sectcreate __TEXT __info_plist Info.plist -o server server.c 
codesign -s instrument ./server 
./server 

"Instrument" ist an meinem Schlüsselbund vorhanden ist, und immer vertrauen für die Code-Gesang, so dass ich denke, es ist Fall sein should't.

Info.plist

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
<dict> 
    <key>SecTaskAccess</key> 
    <array> 
     <string>allowed</string> 
     <string>debug</string> 
    </array> 
</dict> 
</plist> 

Natürlich mein Code nur nützlich für die speziellen Fall ist, wird versucht, eine Funktion Fuzz, die Eingabezeichenfolge und vergleichen Sie es mit anderen Zeichenfolge ist.

server.c:

#include <stdio.h> 
#include <sys/mman.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <signal.h> 
#include <sys/ptrace.h> 
#include <mach/mach.h> 
#include <stdlib.h> 
int main (int argc,char ** argv) 
{ 
    pid_t pid = fork(); 
    pid_t parentPID, childPID; //maybe it's not really safe, nevermind 
    int status; 
    if (pid == 0) 
    { 
     printf ("CHILD %i\n",getpid()); 
     childPID = getpid(); 

     FILE * f = fopen(argv[1],"rb"); 
     if (f == NULL) 
     { 
      return -2; 
      puts ("Cannot open file specified\n"); 
     } 
     int from,to = 0; 
     sscanf(argv[2],"%x",&from); 
     sscanf(argv[3],"%x",&to); 
     if (from >= to) 
     { 
      puts ("R u out of your mind ? check your range of bytes within the file... \n"); 
      return -3; 
     } 
     int fileSize = to - from; 
     void * mem = mmap (NULL,fileSize,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE,fileno(f),0); 
     if (mem == MAP_FAILED) 
     { 
      puts ("[!] Cannot allocate memory for file"); 
      return -4; 
     } 
     printf ("[-] File mapped to virtual memory : [%p]\n",mem); 

     int (*pFunc)(char * str) = (int(*)(char *))(mem+from); 

     int ret = pFunc("AAAAA"); 
     printf ("Returned : %d\n",ret); 


    } 
    else 
    { 
     printf ("PARENT %i\n",getpid()); 
     parentPID = getpid(); 

     kern_return_t kret; 
     mach_port_t task; 
     mach_port_t target_exception_port; 
     kret = task_for_pid (mach_task_self(),childPID,&task); 
     if (kret != KERN_SUCCESS) 
     { 
      printf ("task_for_pid() failed with message %s !\n",mach_error_string(kret)); 
      sleep(100000); 
     } 

     //save the set of exception ports registered in the process 

     exception_mask_t  saved_masks[EXC_TYPES_COUNT]; 
     mach_port_t   saved_ports[EXC_TYPES_COUNT]; 
     exception_behavior_t saved_behaviors[EXC_TYPES_COUNT]; 
     thread_state_flavor_t saved_flavors[EXC_TYPES_COUNT]; 
     mach_msg_type_number_t saved_exception_types_count; 

     task_get_exception_ports(task, 
         EXC_MASK_ALL, 
         saved_masks, 
         &saved_exception_types_count, 
         saved_ports, 
         saved_behaviors, 
         saved_flavors); 

     //allocate and authorize a new port 

     mach_port_allocate(mach_task_self(), 
        MACH_PORT_RIGHT_RECEIVE, 
        &task); 

     mach_port_insert_right(mach_task_self(), 
         target_exception_port, 
         target_exception_port, 
         MACH_MSG_TYPE_MAKE_SEND); 

     //register the exception port with the target process 

     task_set_exception_ports(task, 
         EXC_MASK_ALL, 
         target_exception_port, 
         EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, 
         THREAD_STATE_NONE); 

     ptrace (PT_ATTACHEXC, childPID,0,0); 
    } 

    return 0; 
} 

Warum dieser Fehler ausgibt? Ist es der Fall, wie fork unter OSX funktioniert? Was ist das Problem da draußen? Ich bin kein Experte, wie Osx darunter funktioniert, vielleicht habe ich etwas verpasst. Danke für die Hilfe :) !

Dominik

+0

1. Haben Sie die Berechtigung "SecTaskAccess" (https: // developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man8/taskgated.8.html) in Ihrer Info.plist? 2. Ist Ihre ausführbare Datei signiert? 3. Ihr Prozess muss möglicherweise als root ausgeführt werden, aber ich bin mir nicht sicher, da der Zugriff auf untergeordnete Prozesse ohne Root-Berechtigungen funktionieren kann. – pmdj

+0

Ja, ich habe das alles getan. Wenn ich eine Aufgabe für Finder möchte, erzeugt es keinen Fehler. Wie ich denke, es funktioniert nicht, da childPID für Eltern in der Zeit unbekannt ist, wird die task_for_pid() aufgerufen. Ich weiß nicht, wie ich es anders machen soll. Wie kann ich Code ausführen und als Debugger in einem Programm in Mac OS steuern (wie in der GDB)? Ich habe versucht, gdb Quellcode zu lesen, aber es ist ziemlich schwer für mich zu verstehen, wie es dort gemacht wird. – Domin568

+0

Ok, es ist also nur ein Experiment, aber ich denke immer noch, dass Sie das Folgende überprüfen sollten, bevor Sie sich mit dem Problem "task_for_pid" beschäftigen. Zuerst die Binärdatei, die von Ihrem Child-Prozess zur Ausführung gemappt wurde, müssen Sie sicherstellen, dass die Funktion 'from' keine faulen Symbole oder unaufgelöste Symbole aufruft, weil dydd hier nicht funktionieren würde. Beachten Sie, dieses Ereignis 'printf' ist ein faules Symbol und sollte daher nicht verwendet werden. Zweitens, entsprechend Ihrer Ausgabe, ist es möglich, dass der Kindprozess nicht einmal erstellt wurde, als der Elternteil task_for_pid ausprobiert hat. Überlegen Sie, ob Sie diese beiden Prozesse synchronisieren wollen. – Zohar81

Antwort

0

Sie rufen pid_t pid = fork(); deshalb die PID des Child-Prozesses in den übergeordneten Prozess wird in pid Variable nicht in der childPID gespeichert.

Die Variable childPID wird im untergeordneten Prozess nur gemäß Ihrem Beispielcode initialisiert.

Der task_for_pid() Aufruf verwendet childPID - im Grunde verwenden Sie einen nicht initialisierten Speicher.

+0

Vielen Dank, es war das kleine Missverständnis, wie fork() funktioniert. Jetzt kann ich an meinen Kindprozess binden :) – Domin568

0

Neben dem Problem in der anderen Antwort der Verwendung von nicht initialisierten pid erwähnt, sieht es aus wie Sie nicht die Datei als Eingabe Argument übergeben, was das Kind Prozess führt sofort zu beenden und zu einem Zombie (da Eltern warten nicht denn es ist pid) und Sie können task_for_pid zu beenden Prozess nicht ausführen (obwohl es immer noch in der Prozesstabelle aufgeführt ist)

Grundsätzlich müssen Sie zwischen Eltern und Kind sorgfältiger synchronisieren, aber als ersten Schritt, um die Problem, ich würde empfehlen, sleep vor der Überprüfung, ob die Datei ordnungsgemäß geöffnet ist, sollte der Fehler in task_for_pid auflösen.

+0

@mrdvlpr, das ist richtig, aber in der Frage wird gezeigt, dass das Laufskript einfach 'server' ohne irgendwelche Parameter aufruft, was bewirkt, dass das Kind sofort ablegt, weil' argv [1] 'ist NULL .. – Zohar81