2013-07-23 21 views
5

Unten habe ich eine x64 - Baugruppe geschrieben, die 'Hello, World!' aus einem Syscall unter Mac OS X 10.8. Es assembliert und läuft perfekt, wenn es eigenständig ausgeführt wird.Testen von Shellcode von C - Bus Fehler 10

; Assemble and link with: 
; nasm -f macho64 -o HelloWorld.o HelloWorld.s 
; ld -arch x86_64 -o HelloWorld HelloWorld.o 

global start 

section .text 

start: 

    push rbp 
    mov rbp, rsp 

    jmp short String 

    xor rdi, rdi 
    mov di, 0x01 

StringRet: 
    pop rsi 

    xor rdx, rdx 
    mov dl, 0xE 

    mov r8b, 0x02 
    shl r8, 24 
    or r8, 0x04 
    mov rax, r8 

    syscall   ; System call for write(4) 

    xor edi, edi 

    mov r8b, 0x02 
    shl r8, 24 
    or r8, 0x01 
    mov rax, r8 

    syscall   ; System call for exit(1) 

    mov rsp, rbp 
    pop rbp 

String: 

    call StringRet 
    db 'Hello, World!' 

Das Problem, das ich habe, ist, wenn ich versuche, diesen Code als Shell-Code aus einem c-Programm ausführen. Ich benutzte Otool, um die folgenden Maschinenopcodes zu erhalten.

otool -t HelloWorld.o 

char code[] = "\x55\x48\x89\xe5\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c" 
       "\x89\xc0\x48\x31\xff\x66\xbf\x01\x00\xeb\x1e\x5e\x48\x31\xd2\xb2" 
       "\x0e\x0f\x05\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89" 
       "\xc0\x31\xff\x0f\x05\x48\x89\xec\x5d\xe8\xdd\xff\xff\xff\x48\x65" 
       "\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21"; 

Und unten ist das c-Programm, das ich verwende, um dies auszuführen. Aber ich bekomme immer einen Bus-Fehler: 10.

; Compile: 
; gcc -o HelloWorldTest HelloWorldTest.c 

char code[] = "\x55\x48\x89\xe5\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c" 
       "\x89\xc0\x48\x31\xff\x66\xbf\x01\x00\xeb\x1e\x5e\x48\x31\xd2\xb2" 
       "\x0e\x0f\x05\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89" 
       "\xc0\x31\xff\x0f\x05\x48\x89\xec\x5d\xe8\xdd\xff\xff\xff\x48\x65" 
       "\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21"; 

int main() 
{ 
    int (*ret)(); 

    ret = (int(*)())code; 

    (int)(*ret)(); 

    return 0; 
} 

Wenn ich mit GDB Schritt durch ich KERN_PROTECTION_FAILURE recht, wenn die Ausführung an den Shellcode übergeben wird.

Aktualisiert Frage:

Die oben von Carl Norum gelöst wurde, war es zu Speicherschutz durch. Ich habe ein anderes Problem, ist aber ähnlich wie oben. Anstatt den Shell-Code in der gleichen Datei zu haben, möchte ich den Shell-Code aus einer TXT-Datei lesen und ausführen. Im Folgenden habe ich versucht, einen Speicherbereich als PROT_EXEC zu markieren und den Inhalt der .txt-Datei darin einzulesen und auszuführen. Aber es wird nicht funktionieren, ich bekomme den gleichen Fehler, KERN_PROTECTION_FAILURE, Ich habe versucht mit mprotect und mmap einen Abschnitt des Speichers als PROT_EXEC zu markieren.

#include <stdio.h> 
#include <sys/mman.h> 
#include <string.h> 
#include <stdlib.h> 

int (*ret)(); 

unsigned char* buf; 

int main() 
{ 
    FILE* file; 
    file = fopen("text.txt", "rb"); 

    unsigned int len = ftell(file); 

    buf = (char*)malloc(len); 
    fread(buf, 1, len, file); 

    fclose(file); 

    mprotect(&buf, len, PROT_EXEC); 

    // I also tried mmap, but same error. 
    /*void *ptr = mmap(0, 1024, PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); 

    if (ptr == MAP_FAILED) 
    { 
     perror("mmap"); 
     exit(-1); 
    } 

    memcpy(ptr, buf, 1024);*/ 

    ret = buf; 

    ret(); 

    return 0; 
} 

Dies ist die text.txt Datei, in dem ich zu lesen, ist es der gleiche Hallo Welt Code:

\x55\x48\x89\xe5\xeb\x33\x48\x31\xff\x66\xbf\x01\x00\x5e\x48\x31\xd2\xb2\x0e\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c\x89\xc0\x0f\x05\x31\xff\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89\xc0\x0f\x05\x48\x89\xec\x5d\xe8\xc8\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0a 

Da ich den Inhalt der txt-Datei in PROC_EXEC Speicher kopieren bin ich verstehe nicht, warum ich KERN_PROTECTION_FAILURE bekomme.

+0

Hat die neue Textdatei mit dem Zeichen Backslash enthalten , x, 5, 5 usw.? Oder enthält es die Zeichen '\ x55'' (Ziffer 7 IIRC)? –

+0

Ja, es enthält, \ x, die .txt-Datei ist genau wie oben gezeigt. –

+0

Sie müssen den Rückgabewert von "malloc" in einem C-Programm nicht umwandeln. –

Antwort

8

Ihr Programm versucht den Shellcode von einem Speicherseiten auszuführen, der mit "execute disable" markiert ist. Dies ist die Standardeinstellung für den Speicher im Datenbereich. Deshalb sehen Sie die KERN_PROTECTION_FAILURE. Sie müssen den Shellcode im Textteil setzen:

__attribute__((section("__TEXT,__text"))) 
char code[] = ... 

Danach tun, Ihr Programm funktioniert:

$ clang -Wall -Wextra -pedantic -O2 example.c -o example 
$ ./example 
Hello, World! 

Anmerkung der Redaktion: Sie haben nicht die Typumwandlung auf Ihre Funktionszeiger Aufruf benötigen. Nur ret(); wird gut. Sie müssen mindestens den (int) Teil loswerden, um ohne Warnungen zu kompilieren.

Edit:

Hier ist ein Programm, das, ohne dass Sie arbeitet Gymnastik Abschnitt-Überschreibung zu tun:

#include <sys/mman.h> 
#include <inttypes.h> 
#include <unistd.h> 

char code[] = "\x55\x48\x89\xe5\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c" 
       "\x89\xc0\x48\x31\xff\x66\xbf\x01\x00\xeb\x1e\x5e\x48\x31\xd2\xb2" 
       "\x0e\x0f\x05\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89" 
       "\xc0\x31\xff\x0f\x05\x48\x89\xec\x5d\xe8\xdd\xff\xff\xff\x48\x65" 
       "\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0a"; 

int main() 
{ 
    int (*ret)() = (int (*)())code; 
    void *page = (void *)((uintptr_t)code & ~(getpagesize() - 1)); 

    mprotect(page, sizeof code, PROT_EXEC); 

    ret(); 

    return 0; 
} 

Beispiel läuft:

$ clang -O2 -Wall -Wextra example.c -o example 
$ ./example 
Hello, World! 
$ gcc -O2 -Wall -Wextra example.c -o example 
$ ./example 
Hello, World! 
+0

Vielen Dank, es funktioniert mit clang wie in Ihrem Beispiel. Wie könnte ich das von gcc aus ausführen? Wenn ich "__attribute __ ((Abschnitt (" __ TEXT, __ Text ")))" vor char code [] "setze, bekomme ich einen Fehler," Sektionstyp oder Attribute der globalen Variable 'code' stimmt nicht mit dem vorherigen Abschnittsspezifizierer überein ". –

+0

Warum möchten Sie gcc verwenden, wenn Sie clang verwenden können? Lass es mich hier ausprobieren. –

+0

Kein Grund, ich habe nie vorher geklingelt. Ich möchte nur sehen, wie ich diese Art von Fehler von gcc beheben würde. –