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
    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
    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
    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
    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
    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
    mov eax,-1
      pop ebp
      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