2012-03-31 9 views
6

Ich möchte eine einfache C-Methode, um Hex-Bytecode auf einer Linux-64-Bit-Maschine ausführen zu können. Hier ist das C-Programm, das ich habe:Wie bekomme ich c-Code, um Hex-Bytecode auszuführen?

char code[] = "\x48\x31\xc0"; 
#include <stdio.h> 
int main(int argc, char **argv) 
{ 
     int (*func)(); 
     func = (int (*)()) code; 
     (int)(*func)(); 
     printf("%s\n","DONE"); 
} 

Der Code, den ich zu laufen versuche ("\x48\x31\xc0") I erhalten durch diese einfache Montage Programm writting (es ist eigentlich nicht wirklich etwas tun)

.text 
.globl _start 
_start: 
     xorq %rax, %rax 

und dann Kompilieren und Objdumping, um den Bytecode zu erhalten.

Wenn ich jedoch mein C-Programm ausführen, erhalte ich einen Segmentierungsfehler. Irgendwelche Ideen?

+5

Selbst wenn Ihr Datensegment ausführbar ist oder Sie nicht haben NX aktiviert ist, was erwarten Sie, dies zu tun? Es führt eine Anweisung und dann die Anweisung danach aus (die Sie nicht steuern) und dann die Anweisung danach, bis sie Speicher erreicht, der nicht legitimen Code oder Code darstellt, der einen segfault auslöst. –

+1

Sie müssen Byte-Code für ein "ret" hinzufügen, da der indirekte Funktionsaufruf, den Sie tun, ein "Aufruf" sein sollte, der die Rückkehradresse auf den Stapel schiebt. Atleast, das ist meine beste Vermutung, ich habe noch nie so etwas gesehen. – Chris

+0

Ich erwarte, dass dies nichts tut, aber ich möchte, dass es ohne Absturz laufen kann. – Nosrettap

Antwort

13

Hier ist ein einfaches Beispiel.

main.c:

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

int main() 
{ 
    /*                
     mov rax, 60   ; sys_exit 
     mov rdi, 2 
     syscall             
    */ 
    char code[] = { 
     0x48, 0xb8, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x48, 0xbf, 0x02, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x0f, 0x05 
    }; 

    void *buf; 

    /* copy code to executable buffer */  
    buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC, 
       MAP_PRIVATE|MAP_ANON,-1,0); 
    memcpy (buf, code, sizeof(code)); 

    /* run code */ 
    ((void (*) (void))buf)(); 

    return 0; 
} 

Run dies mit

./main ;echo $? 

Ich wählte eine _exit (2) in der Versammlung zu tun, um es einfach zu überprüfen, ob der Code ordnungsgemäß ausgeführt wird. In der Praxis möchten Sie am Ende des Codes ein Ret hinzufügen, um die Kontrolle zurückzugeben.

+0

Ja, das "ret" ist wichtig, um in die aufrufende Funktion zurückzukehren. – Chris

+1

Danke für die Hilfe. Ich möchte nur hinzufügen, dass objdump -d können Sie den Byte-Code für eine ausführbare Datei erhalten. – Jeff

4

Ihr Maschinencode kann in Ordnung sein, aber Ihre CPU-Objekte.

Moderne CPUs verwalten Speicher in Segmenten. Im Normalbetrieb lädt das Betriebssystem ein neues Programm in ein Programmtext--Segment und richtet einen Stapel in einem Daten--Segment ein. Das Betriebssystem weist die CPU an, keinen Code in einem Datensegment auszuführen. Ihr Code befindet sich in code[] in einem Datensegment. Also der Segfault.

2

Dies wird einige Anstrengungen erfordern.

Ihre code Variable wird im .data Abschnitt Ihrer ausführbaren gespeichert:

$ readelf -p .data exploit 

String dump of section '.data': 
    [ 10] H1À 

H1À ist der Wert Ihrer Variablen.

Der .data Abschnitt ist nicht ausführbar:

$ readelf -S exploit 
There are 30 section headers, starting at offset 0x1150: 
Section Headers: 
    [Nr] Name    Type    Address   Offset 
     Size    EntSize   Flags Link Info Align 
[...] 
    [24] .data    PROGBITS   0000000000601010 00001010 
     0000000000000014 0000000000000000 WA  0  0  8 

Alle 64-Bit-Prozessoren ich vertraut bin mit Unterstützung nicht ausführbaren Seiten nativ in den Seitentabellen. Die meisten neueren 32-Bit-Prozessoren (diejenigen, die PAE unterstützen) bieten in ihren Seitentabellen genügend zusätzlichen Speicherplatz für das Betriebssystem, um nicht ausführbare Hardware-Seiten zu emulieren. Sie müssen entweder ein altes Betriebssystem oder einen alten Prozessor ausführen, um eine .data Sektion zu erhalten, die als ausführbar markiert ist.

Da dies nur Flags in der ausführbaren Datei sind, sollten Sie in der Lage sein, das Flag X durch einen anderen Mechanismus zu setzen, aber ich weiß nicht, wie es geht. Und Ihr Betriebssystem möglicherweise nicht sogar lassen Sie Seiten, die beide schreibbar sind und ausführbar.

Verwandte Themen