Ausführen von Binärcode
-
Hallo, ich habe folgendes vor: Ich möchte ausführbaren Code während der Laufzeit eines Programmes erzeugen und ausführen. Dazu habe ich das hier beispielhaft versucht.
#include <stdio.h> const unsigned char array[8] = { 0x66, 0xb8, 0x05, 0x00, 0x00, 0x00, 0xc3, 0x00 }; /* Der Inhalt von array entspricht: section .text global _test _test: mov eax, 5 ret */ int main(int argc, char **argv) { printf("Hallo\n"); int (*myfunc)(); myfunc = array; int i = myfunc(); printf("Zurück: i = %d", i); return 0; }
Dieser Code führt zu einem Speicherzugriffsfehler. Kann mir das jemand erklären?
-
Hallo so sollte es gehen.
Voraussgesetzt der Shellcode funktioniert.#include <stdio.h> int main(int argc, char **argv) { char sh[] = "\x66\xb8\x05\x00\x00\x00\xC3\x00"; int (*call)(); call = &sh; (*call)(); return 0; }
Sonst Assemblier dir mal meinen[Nur für Windows] (aber nicht vergessen die Speicher Adressen zu ändern sonst geht es nicht. )
BITS 32 global _start _start: jmp get_text msg_box: pop ebx xor eax,eax push eax push ebx push ebx push eax mov ebx , 0x7e3a07ea ; MessageBoxA call ebx cmp eax , 1 ; wenn der Ok Button von der MessageBox angeklickt wurde dann soll das Programm beendet werden je quit jmp cont quit: xor eax,eax push eax mov eax,0x7c81cb12 ; ExitProcess call eax cont: get_text: call msg_box db "ok"
So kriegst du die DLL Funktionsadressen
#include <windows.h> #include <stdio.h> #include <conio.h> int main() { short wiederhole; HINSTANCE handle; char dll_name[2000]; char funktions_name[2000]; FARPROC addr; int ret; do { wiederhole = 0; clrscr(); fflush(stdin); printf("Namen der DLL Datei eingeben [Bsp. kernel32.dll]: "); gets(dll_name); printf("Gesuchten Funktions namen eingeben: "); gets(funktions_name); fflush(stdin); handle = LoadLibrary ( dll_name ); if ( handle == 0 ) { printf("\n"); printf("Fehler konnte DLL nicht laden die DLL muss im Programm Ordner liegen !"); } addr = GetProcAddress( handle, funktions_name ); if ( addr != 0 ) { printf("0x%x \n",addr); ret= FreeLibrary ( handle ); if ( ret == 0 ) { printf("Konnte DLL nicht freigegeben\n"); } else { printf("DLL wurde freigegeben\n"); } } else { printf("\n"); printf("Die gesuchte Funktion konnte in der DLL Datei nicht gefunden werden ! \n"); } printf("\n"); printf("Neue Suche ? 1 = Ja , 2 = Nein \n"); scanf ("%d" , &wiederhole , stdin); } while ( wiederhole == 1); return 0; } //---------------------------------------------------------------------------
Und hier noch mein shellcode compiler
#include <iostream> #include <fstream> #include <vector> using namespace std; int main(int argc, char* argv[]) { // Shellcode testen #define d #ifdef dbg char s[]= "\xeb\x50\x5b\x53\xb8\x7b\x1d\x80\x7c\xff" "\xd0\xe8\x35\x00\x00\x00\x5b\x53\x50\xba" "\x40\xae\x80\x7c\xff\xd2\xe8\x18\x00\x00" "\x00\x5b\x68\x00\x00\x00\x00\x53\xff\xd0" "\xe8\x00\x00\x00\x00\x31\xc0\x50\xb8\x12" "\xcb\x81\x7c\xff\xd0\xe8\xe3\xff\xff\xff" "\x63\x61\x6c\x63\x2e\x65\x78\x65\x00\xe8" "\xc6\xff\xff\xff\x57\x69\x6e\x45\x78\x65" "\x63\x00\xe8\xab\xff\xff\xff\x6b\x65\x72" "\x6e\x65\x6c\x33\x32\x2e\x64\x6c\x6c\x00"; int(*f)(); f = ( int (*) () ) & s; (*f)(); #endif #define abc #ifdef abc int i=0; int counter=10; char *file_name = "0"; unsigned char var; long file_size; cout<<"Name der Maschienencode Datei [Maschiendencode Dateiendung ist immer .bin]: "; cin>>file_name; ofstream dat ("Shellcode.txt"); ifstream datei ( file_name ); if ( !datei.good() ) { cout<<"Die Datei existiert nicht !"<<endl; system("PAUSE"); return 0; } datei.seekg ( 0 , ios::end ); file_size = datei.tellg(); datei.seekg ( 0 , ios::beg ); vector<char>save(file_size); datei.read( reinterpret_cast<char*> ( & save[0] ) , file_size ); datei.close(); for(int i=0 ; i< file_size ; i++) { if ( i ==counter) dat<<endl; counter+=10; } var=save[i]; dat <<"\\x" << hex << static_cast<unsigned int>(var); if ( var == '\x00' ) { dat <<"0" ; } } dat.close(); cout<<"Fertig ! "<<endl; #endif system("PAUSE"); return 0; }
Ist vielleicht nicht optimal aber funktioniert
Und schau mal dort vorbei -> http://projectshellcode.com/
-
ret -> wohin genau?
Hilfe: u.a. Debugger, http://www.int80h.org/bsdasm/#the-assembler
-
array[8] liegt in einem Daten"segment". Das ist das (erste) Problem.
-
Wenn du Linux benutzt dann musst du dein Binary ohne stackprotector Compilieren.
gcc -fno-stack-protector -o file file.c ( Versuch mal ob es so bei dir geht )
[ASLR kann man auch umgehen, aber versuch das erst mal so ans laufen zu bekommen]Und deaktivier mal ASLR (Hinterher aber wieder aktivieren nicht vergessen):
echo 0 > /proc/sys/kernel/randomize_va_space
0 = deaktiviert
1 = aktiviertWas auch geht mit mmap einen Virtuellen Speicherbereich erstellen.
PROT_EXEC sollte dir helfen dein vorhaben durchzuführen.http://linux.die.net/man/2/mmap
Oddderrr du lädst dir den gcc-3.4 runter der hat kein Stackprotector.
-
Danke für Eure schnelle Hilfe. Ich habe die Lösung gefunden. Der Code in array war für 16-Bit-Systeme assembliert. Mein Linux läuft aber im 32-Bit-Modus.
Folgendes funktioniert wie gedacht:#include <stdio.h> const unsigned char array[6] = { 0xb8, 0x05, 0x00, 0x00, 0x00, 0xc3 }; /* array entspricht BITS 32 mov eax, 5 ret mit nasm. */ int main(int argc, char **argv) { printf("Hallo\n"); int (*myfunc)(); myfunc = array; int i = myfunc(); printf("Zurück: i = %d\n", i); return 0; }
Tatsächlich scheint man mit einem Funktionsaufruf ja problemlos ins Datensegment und zurück zu kommen. Ziemlich unsicher, oder?
-
Aus diesem Grund dürfte dein Code in Systemen mit NX-Bit nicht funktionieren.
-
Unter Windows könnte man folgendes machen (siehe Beiträge hier http://www.c-plusplus.net/forum/249829-full):
abc.w schrieb:
@AntonWert: Das geht ungefähr in drei-vier Schritten, Speicher allokieren (1), Deine Daten, die ja ausführbaren Code darstellen, rüberkopieren (2), den Speicherbereich als ausführbar "einstellen" und Funktionspointer darauf (3) setzen:
{ void (*my_func)(void) = NULL; void *pMem = NULL; void *pDeineDaten = NULL; DWORD ManyBytes = 4096; DWORD OldProtect = 0; ... /* pDeineDaten mit Daten füllen */ pMem = VirtualAlloc(NULL, ManyBytes, MEM_COMMIT, PAGE_READWRITE); memcpy(pMem, pDeineDaten, ManyBytes); VirtualProtect(pMem, ManyBytes, PAGE_EXECUTE, &OldProtect); my_func = (void (*)(void))pMem; my_func(); }
Viel Glück beim Debuggen!
Immer noch aktuell: Viel Glück beim Debuggen!