GetProcAddress Ersatz + suchen der Kernel32 Baseadresse

  • Habe mal in Olly mit Exports rumgespielt und es etwas vertieft :)
    Sind letztendlich 2 Codestücke geworden:
    einmal ein "GetProcAdress" API Ersatz - liefert Adresse einer Funktion (basiert nicht auf verstecktem "GetProcAdress" Aufruf, sondern scannt die Exports)


    und als "Bonus" das Ermitteln der Kernel32 DLL Position im Speicher.
    Beides auf XP SP2 und Vista SP1 getestet (läuft, trotz Vista ASLR *g* ).
    Die Codestücke sind komplett adressunabhängig und können somit an beliebieger Position laufen. Das Ganze ist zwar in MASM, da hier aber keine Macros&Co genutzt werden, sollte eine Umsetzung in InlineASM/NASM/TASM/FASM keine gro�en Schwierigkeiten machen.


    Wozu das gut ist:
    ich denke da in erster Linie an Codeinjections/Inlinepatchs (die REler wissen schon,was gemeint ist ;) ). Man kann es auch für eigene Packer/Protectoren/Crypter nutzen (InlineAsm sei dank - den Code selber kann man auch direkt als "Raw" Bytes hineinkopieren) - dann tauchen weder LoadLibrary noch GetProcAdress in den Imports auf. Kurz gesagt: die Leute, die mit dem Code etwas anfangen können, wissen es auch einzusetzen :)


    Ermitteln der Kernel32 Basis:
    Voraussetzung: Man ist am EP. Alternativ: Stack kurzfristig "freiräumen" (ESP+X machen) um den "startzustand wiederherzustellen oder einfach den Code anpassen. Prinzip: Windows PE Loader "callt" die Anwendung. Daher hat man (am EP) auf dem Stack eine Rücksprungadresse in die Kernel32 DLL. Damit kann man einiges anfangen *g*

    Code
    1. pop eax ;Auf dem Stack ist Return to Kernel32 - kann man nutzen ;) push eax and eax,0FFFFF000h ;die ersten Bits löschen (Eregebnis: vielfaches von 4) std mov edi,eax mov eax,00905a4dh ;M Z 90 00 mov ecx,01000000h ;sollte reichen repne scasd ;nach MZ 90 00 scannen - alse Kernel32 Basisadresse lea eax,[edi+4] cld ;nun ist in EAX die Kernel32 Base

    OllyDbg Bytecode zum C&P

    Code
    1. 58 50 25 00 F0 FF FF FD 8B F8 B8 4D 5A 90 00 B9 00 00 00 01 F2 AF 8D 47 04 FC

    und hier GetProcErsatz. Prinzip: joa, das übliche Parsen des PE Headers. Am verständlichsten ist es wohl, wenn man sich dazu eine PE-Dokumentaion/Referenz anschaut (wie man zu ExportEntries kommt und wie diese aufgebaut sind).
    Parameterübergabe: EAX==DLL Basisadresse
    ESI == API String und in ECX die String länge.
    Rückgabe: in EAX die Funktionsadresse oder im Fehlerfall eine -1(==0FFFFFFFF)

    Code
    1. version2:;erwartet: DLL Base in EAX,in ECX Stringlänge, in ESI string adresse;rückgabe: Adresse in EAX oder -1push ebpmov edx,[eax+3ch]lea edx,dword ptr [eax+edx+78h];nun EDX=Exportdirektory VAmov edx,[edx] ;RVA holenadd edx,eax ;VA zeiger auf ExportDirectory Eintragpush edxmov ebp,[edx+18h] ;Anzahl der Namenmov edx,[edx+20h] ;in EDX: zeiger auf *AdressOfNamesadd edx,eax ;Erster Eintrag des AdressOfNames Arrayscldsearch: mov edi,dword ptr [edx+ebp*4-4] add edi,eax push ecx push esi repe cmpsb pop esi pop ecx jz found dec ebp jnz search ;nicht gefunden: mov eax,-1 pop ebp pop ebp ;ebp wiederherstellen+Stackframe retfound:;nun in EBP Funktionsnummerpop edx ;zeiger auf ExportDirectory Eintragmov edx,dword ptr [edx+1Ch] ;*AdressOfFuntions RVAadd edx,eax ;AdressOfFunctions VAmov edx,[ebp*4-4+edx]; lese Adresse der Funktion aus der *AdressOfFuntions add eax,edxpop ebpret

    OllyDbg Bytes zum C&P

    Code
    1. 55 8B 50 3C 8D 54 02 78 8B 12 03 D0 52 8B 6A 18 8B 52 20 03 D0 FC 8B 7C AA FC 03 F8 51 56 F3 A6
    2. 5E 59 74 09 4D 75 EF B8 FF FF FF FF C3 5A 8B 52 1C 03 D0 8B 54 AA FC 03 C2 5D C3

    Im Anhang eine Testanwendung die beide Codes nutzt (zeigt eine "Hello" Nachricht - die Anwendung hat allerdings keinen einzigen Importeintrag, was man unschwer in LordPE prüfen kann). Läuft unter XP,Vista. Läuft nicht unter win2k (da will der PE Loader mindestens ein Importeintrag haben, sofern ich mich erinnere). Source ist auch beigelegt.


    PS: bei "richtig_klein.exe" handelt es sich um eine Spielerei (ich konnte es nicht lassen und hab manuell aus der bestehenden Exe was zusammengeschustert, so dass die Exe nur 512Bytes belegt und trotzdem noch die Nachricht ausgibt).

  • Sieht gut aus, aber unter 64 Bit kackt das Programm ab (alle Versionen) :D Ich werds mal Debuggen.

    Edit: Okay der Fehler ist schon direkt am Anfang.

  • Schade, hab leider kein 64 Bit Vista zum Testen. Wie sieht denn der Header im 64 Bitter aus? Ich meine den MZ 90 00 Part. Eventuell wird auch nicht mehr die Rücksprungadresse auf dem Stack abgelegt.


    läuft denn der GetProcAddress Part (einfach den Code bis "401045: CLD" überspringen und in EAX manuell die Kernel32 Basis eingtragen) ?


    PS: habe den oben Code etwas korrigiert. Jetzt wird im Fehlerfall der Stackframe wiederhergestellt und wirklich -1 zurückgeliefert.

    Code
    1. mov eax,-1
    2. pop ebp
    3. pop ebp ;ebp wiederherstellen+Stackframe

    Anhang updated.

  • Ja, wenn ich den Code bis CLD überspringe und die Kernel32 ImageBase in EAX editiere, läuft das Programm. Allerdings wird die Caption der MessageBox noch nicht richtig gesetzt:



    Ahso sehe grade du übergibst einfach 0 naja, dann ists klar :P