2015-08-08 30 views
5

Ich versuche zu lernen Shellcode innerhalb eines Programms auszuführen, aber ich kann nicht einmal den einfachsten Code ausführen. Der folgende Code soll nur das Terminal verlassen, wenn es laufen gelassen:Eine Zeichenkette als Funktion übergeben

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

char exitcode[] = "\xb0\x01\x31\xdb\xcd\x80"; 

int main() { 
    int (*func)(); 
    func = (int (*)())exitcode; 
    (int)(*func)(); 
    return 0; 
} 

Aber alles, was ich bekommen, ist eine segfault. GDB sagt, es passiert, wenn das Programm auf den Speicherort von exitcode zugreift [at (int) (* func)(); ], aber ich bin mir nicht sicher, warum dies ein Problem verursacht. Ich betreibe ein 64-Bit Linux Mint OS. Jede Hilfe wird sehr geschätzt.

+0

Wenn der Speicher für den Shellcode in einem nicht ausführbaren Bereich ist, wird dies nicht funktionieren. Die meisten modernen Betriebssysteme werden dies wahrscheinlich nicht erlauben. Sie sollten auch sicherstellen, dass der Shellcode für Ihre Architektur korrekt ist. –

+1

Ist das für C oder C++? Semantik und mögliche Antworten können sich unterscheiden. – Olaf

+0

Einen Objektzeiger auf einen Funktionszeiger werfen ist _undefined behaviour_. Alles kann passieren – Olaf

Antwort

6

Moderne Betriebssysteme verwenden Speicherschutz. Seiten des Speichers haben Zugriffsrechte wie Dateien: lesbar, beschreibbar, ausführbar. Ihr Datensegment Ihres Programms befindet sich normalerweise auf einer nicht ausführbaren Seite. Wenn Sie versuchen, es auszuführen, führt dies zu einem Segfault.

Wenn Sie dynamisch geschriebenen Binärcode von Ihrem Programm unter Linux ausführen möchten, müssen Sie zuerst eine Seite mit mmap() zuordnen, in die Sie schreiben können. Geben Sie Ihren Code dort ein und ändern Sie ihn in schreibgeschützt, ausführbar mit mprotect(). DANN kannst du dort springen.

Sie könnten zum Beispiel read this article für Details.

EDIT: Wenn es sich um Sicherheitsverletzungen handelt, beachten Sie, dass der Stack heutzutage auch nicht ausführbar ist ... also werden all diese alten "Hacking-Tutorials" nicht mehr funktionieren. Wenn Sie an neueren Techniken interessiert sind, lesen Sie über zurück orientierte Programmierung.

0

Ihre Shellcode ist:

mov $0x1,%al 
xor %ebx,%ebx 
int $0x80 

Es gibt zwei Probleme:

  1. Syscall 0x1 ist ein sys_write auf 64-Bit (aber auf 32-Bit es ist sys_exit)
  2. Sie sollten zuweisen zu% rax, nicht% al. % rax enthält Reste in hohen Bits.
4

Der Code muss als ausführbarer Code markiert sein. Eine Möglichkeit besteht darin, diesen binären Maschinencode in einen ausführbaren Puffer zu kopieren.

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

char exitcode[] = "\xb0\x01\x31\xdb\xcd\x80"; 

int main(int argc, char **argv) 
{ 
    void *buf; 

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

    /* run code */ 
    int i = ((int (*) (void))buf)(); 
    printf("OK. returned: %d", i); 
return 0; 
} 
0

Ich hatte dieses Problem und suchte viel, um es zu lösen.

Sie müssen diesen Code verwenden, um Ihren C-Code zu kompilieren (Um Stapelschutz zu deaktivieren und es ausführbar machen):

gcc -fno-stack-protector -z execstack -o hello hello.c 

Getestet in Kali 32/64 Bit. Kein segfault mehr.

Viel Glück