Iat fragen

Hi Leutz

ich habe mal ein frage was genau die IAT (import address table )ist meines erachtens sind da die addressen drinn um funktion bzw apis aufzurufen.

beispiel:


00404254 $- FF25 28504000 JMP DWORD PTR DS:[<&user32.GetDlgItemTex>; user32.GetDlgItemTextA


hier jumpt der doch zur dll user32 api procaddresse 77D6AC06

DS:[00405028]=77D6AC06 (user32.GetDlgItemTextA)
Local calls from 0040413B, 004041BE

Wie genau arbeitet iidking der nimmt doch auch die addresse von einer ausgewählten dll und ausgewählten funktion die addresse und speichert die in der ziel.exe.

ich benutze für mein inline patcher die find kernel32 funktion und getprocaddress funktion

Code:
;This is yoda's code with some small changes and commenting
GetKernelBaseAddress:            ;returns 0 on error
    mov edi,[esp+4]                ;Get the value of the first parameter, which is the address of the top of the stack
    and edi,0FFFF0000h            ; wipe the LOWORD !
    .WHILE TRUE
       .IF word ptr [edi]==IMAGE_DOS_SIGNATURE
          mov esi,edi
          add esi,[esi+03Ch]
          .IF  dword ptr [esi]==IMAGE_NT_SIGNATURE
             .BREAK
          .ENDIF
       .ENDIF
       sub edi,010000h
       .IF edi<070000000h        ;The kernel32.dll would be no lower than this address
          mov edi,0BFF70000h
          .BREAK
       .ENDIF
    .ENDW
    xchg eax,edi
    ret 4
    
GetProcedureAddress:
    ; check PE Signarue
    mov esi,[esp+4h]            ;DllBaseAddress
    cmp word ptr [esi],IMAGE_DOS_SIGNATURE
    jnz @@error
    add esi,[esi+3Ch]
    cmp dword ptr [esi],IMAGE_NT_SIGNATURE
    jnz @@error
    
    ; get the string length of the target Api
    mov edi,[esp+8h]            ;szapi
    mov ecx,150
    xor al,al
    repnz scasb
    mov ecx,edi
    sub ecx,[esp+8h]            ;ecx = szAPI length
    
    ; trace the export table
    mov edx,[esi+78h]            ;edx = xport table
    add edx,[esp+4h]
    assume edx:ptr IMAGE_EXPORT_DIRECTORY
    mov ebx,[edx].AddressOfNames;ebx = addressOfNames array pointer
    add ebx,[esp+4h]
    xor eax,eax                
    .REPEAT
           mov edi,[ebx]
           add edi,[esp+4h]            
           mov esi,[esp+8h]            
           push ecx                
           repz cmpsb
           .IF ZERO?
            add esp,4
              .BREAK
           .ENDIF
           pop ecx
           add ebx,4
           inc eax   
    .UNTIL eax==[edx].NumberOfNames
    
    ; did we found sth ?
    .IF eax==[edx].NumberOfNames
           jmp @@error
    .ENDIF
    
    ; find the corresponding Ordinal
    mov esi,[edx].AddressOfNameOrdinals
    add esi,[esp+4h]
    push edx                    ;save the export table pointer
    mov ebx,2
    xor edx,edx
    mul ebx
    pop edx
    add eax,esi
    xor ecx,ecx
    mov word ptr cx,[eax]        ;ecx = api Ordinal
    
    mov edi,[edx].AddressOfFunctions;get the address of the api
    xor edx,edx
    mov ebx,4
    mov eax,ecx
    mul ebx
    add eax,[esp+4h]
    add eax,edi
    mov eax,[eax]
    add eax,[esp+4h]
    jmp @@got_proc_address
    
    assume edx:nothing    
        
@@error:
       xor eax,eax   
@@got_proc_address:
    ret    8

aber leider schlagen die av´s alarm und es läuft nur auf der windows version auf der die ziel.exe gepatcht wurde also muss ich die iat patchen.

könnte mir einer ein source posten in masm?

ich weis nur so weit:

mapping die ziel.exe
schreibe die section
und schreibe die iat mit den function und hier komme ich nicht weiter

mfg
ragdog
 
*ein paar Satzzeichen ausgeb*

Also zu deiner ersten Frage, ja in der IAT stehen die Adressen drin, die das Programm benoetigt.

Der Rest deines Textes ergibt fuer mich leider keinen Sinn, selbst wenn ich mir die Satzzeichen dazu denke ;).

Was ist idking? (Ich glaub daraus ergibt sich dann auch was die ziel.exe ist)
Was ist die "find kernel32 funktion" und die "getprocaddress funktion"?
 
hier ist ein schöner Artikel dazu:
http://sandsprite.com/CodeStuff/Understanding_imports.html
(Ich gehe davon aus, dass, du weißt, wie du den PE Anfang herausbekommst)

Man muss also erstmal herausfinden, wo die DataDirectory ist, der erste Eintrag verweis auf ExportDirectory, der zweite auf die ImportDirectory
Code:
+0 PE
 4 WORD  Machine;
 6 WORD  NumberOfSections;    
 8 DWORD   TimeDateStamp;
 C DWORD   PointerToSymbolTable;    
10 DWORD   NumberOfSymbols;
14 WORD  SizeOfOptionalHeader;    
16 WORD  Characteristics;

18 Optional Header

18 WORD    Magic;    
1a UCHAR   MajorLinkerVersion;    
1b UCHAR   MinorLinkerVersion;
1c DWORD   SizeOfCode;    
20 DWORD   SizeOfInitializedData;
24 DWORD   SizeOfUninitializedData;    
28 DWORD   AddressOfEntryPoint;
2c DWORD   BaseOfCode;    
30 DWORD   BaseOfData;    //    // NT additional fields.
   //    
34 DWORD   ImageBase;    
38 DWORD   SectionAlignment;
....

   IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
   /* IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 */

78 DWORD ExportDirectory VA
7c DWORD ExportDirectory Size
80 DWORD ImportDirectory VA
84 DWORD ImportDirectory Size
also PE Angangsadresse+80h -> da ist die Adresse der ImportDirectory.

Die ImportDirectory selbst ist eine Liste, die so aufgebaut ist:
Code:
    +--------------------------------+
    | Import Directory               |
    | +0 DWORD   OriginalFirstThunk; |
    |  4 DWORD   TimeDateStamp;      |
    |  8 DWORD   ForwarderChain;     |
    |  c DWORD   Name;               |
    | 10 DWORD   FirstThunk;         |
    | Import Directory               |
    | +0 DWORD   OriginalFirstThunk; |
    |  4 DWORD   TimeDateStamp;      |
    |  8 DWORD   ForwarderChain;     |
    |  c DWORD   Name;               |
    | 10 DWORD   FirstThunk;         |
    |  usw.                          |
    +--------------------------------+
usw. Ende ist durch einen leeren Eintrag (5 DWORDs mit 00 gefüllt) gekennzeichnet.
In dieser Struktur kannst du TimeDateStamp und ForwarederChain vernachlässigen.
Name: der RVA verweist auf einen Eintrag mit DLL Namen. Also irgendwo ist dieser gespeichert und im vierten DWORD der ImportDirectoryStruktur steht ein RVA darauf.
OriginalFirstThunk und FirstThunk sind wieder RVA Verweise auf Tabellen. Und eigentlich diese Tabellen nennt man IAT.

Die einzelnen Einträge in der IAT beinhalten die relativen Adressen
der Strings oder eine "Erkennungsnummer" der Funktion. Ist das hochwertigste
Bit gesetzt,handelt es sich um eine "Erkennungsnummer", z.B
0x80000001. Wenn ein Eintrag 00 00 00 00 beträgt, so bedeutet es das
Ende des IAT/LookupTable-Abschnittes für diese DLL.
Siehe den Link oben für bessere Darstellung.

Bildlich kann man es sich so vorstellen:
FirstThunk Wert: 020000 (RVA!).
Also IAT an RVA 20000.
Beispieleinträge in dieser IAT:
Code:
30000,30040,3004A, 000000
an diesen Adressen stehen:
Code:
30000: 00 00 45 78 69 74 50 72 6F 63  65 73 73   ..ExitProcess
30040: 00 00  B7 02 6C 73 74 72 63 6D 70 41       ..lstrcmpA
...
Nochmal: ImportDirectoryAdresse->ImportDiryctoryListe
jeder Eintrag in der Liste
Verweis auf IAT
unwichtiger Wert
unwichtiger Wert
Verweis auf DLL Namen
Verweis aus IAT

IAT besteht aus: Verweis auf String, Verweis auf String (oder Funktionsnummer).
Beim Laden der Exe analysiert der Windows PE Loader die IAT - er folgt den Stringverweisen, ermittelt die zugehörige Adresse der Funktion und schreibt sie wieder rein. Nach dem der PE Loader fertig ist, springt er zum OEP und wenn die Ausführung der Exe beginng, findet der Code schon fertige Verweise auf die Funktionen.


Im Idealfall kann man so verfahren: erstmal schauen, an welcher Adresse eine neue Section geadded werden könnte (damit hat man die RVA). Den RVA der Section merken!

Speicherblock reservieren und DLL Namen sowie zu importierende Funktionen (dabei 2 "hintbytes" vor dem Namen und die terminierenden 0 dazwischen nicht vergessen!) reinschreiben. Also nur die Strings. In einem Array sollte man sich noch die Position dieser Strings merken (Bezugspunkt ist der Anfang des Speicherblocks)

Hinter den Strings folgt der IAT-Eintrag: dieser setzt sich so zusammen: RVA der neuen Section+ position im Speicherblock
(also z.B für RVA 6000: 6000 + 0, 6000+30, je nach dem wo die Strings stehen).
Nun hat man die Hälfte der Arbeit geschafft.

Dann sucht man die ImportDirectoryListe, geht sie durch (bis man 5 leere DWORDs findet) und erstellt einen eigenen Eintrag:
Code:
00 00 00 00 (OriginalFirstThunk braucht man nicht)
00 00 00 00 (timestamp auch nicht)
00 00 00 00 (chain auch nicht)
00 00 60 00 Verweis auf den DLL Namen
00 00 60 XX Verweis auf die IAT

00 00 00 00  neues Ende
00 00 00 00
00 00 00 00
00 00 00 00 
00 00 00 00
Nun muss man nur noch
ImportDirectory Size
korrigieren (vorhergige Größe+5*4)

Im Nichtidealfall ist aber kein Platz mehr da, um einen neuen ImportDirectory Eintrag hinzuzufügen. Man muss also zuerst die alten Einträge in seine Section kopieren und dann den neuen hinzufügen. Nun ändert man
ImportDirectoryVA = neue Adresse
und ImportDirectory Size = neue Größe

Nicht vergessen ImageSize anzupassen und alles, was zum SectionAdden dazugehört.

Code: kannst Dir gerne aus Un2Pec was zusammenschustern, wenn Du willst. Ich würde es aber lieber selber schreiben ;)

So ähnlich arbeitet übrigens auch IIDKing. Die alte Version konnte afaik nur einen ImportDirectoryEintrag hinzufügen, wenn noch Platz übrig war.
 
Fast vergessen: nicht durch unterschiedliche Namen im Artikel und dem angehängen PE Format verwirren lassen. Der Artikel geht zwar mehr auf die Struktur ein, aber im PE Format sind die Einträge als DWORDs und mit Positionen deklariert, was für MASMler doch bequemer ist.

Zum:
0 DWORD OriginalFirstThunk;
10 DWORD FirstThunk;

Beide verweisen ja auch eine IAT. Der Unterschied ist nur, dass bei OriginalFirstThunk (im Artikel als LookupTable bezeichnet) die Verweise auf die Strings so verbleiben - hier ändert der PE Loader von Windows nichts. Nur FirstThunk - IAT wird "modiziert". Daher kann man den OriginalFirstThunk Wert auch auf 0 setzen (was viele Linker auch machen).

Ich kann nur emfpehlen, eine kleine MASM Exe mit LordPE/PETools und parallel dazu in Olly anzuschauen (dabei aber den OriginalFirstThunk Verweis nehmen, weil diese noch "jungfräulich" sind und den FirstThunks vor dem laden entsprechen).
Dann wird vielleicht vieles auch verständlicher.
 
Zurück
Oben