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 = aktiviert

    Was 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.

    http://en.wikipedia.org/wiki/NX_bit



  • 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! 🙂


Anmelden zum Antworten