IDAPYTHON pour nommer les appels indirects aux fonctions

Après avoir recherché partout et fatigué tout le monde via IRC, je n’ai pas trouvé de solution sympa pour résoudre automatiquement les noms de fonction dans IDA quand les appels à celles-ci ne sont pas déclarées dans l’IAT.

Bon, j’ai perdu un lecteur ou deux, Je m’explique;

Par exemple, si je veux faire un programme windows qui pond une messagebox, cet appel de fonctions sera déclarée dans l’IAT et la DLL responsable de la fonction pour ce popup sera elle aussi déclarée et chargée à l’initialisation de l’executable. Cette publicité inattendue est peu souhaité par l’écrivain de malware. Celui-ci préfère éviter de déclarer les fonctions qu’il utilise. Et c’est du travail de se cacher.

J’ai pondu un petit exemple dans le github : https://github.com/Th4nat0s/Chall_Tools/tree/master/asm/hellostealth

Ce n’est pas le but aujourd’hui d’expliquer comment retrouver l’offset d’une fonctions en parsant la table d’EAT d’une dll; Mais en deux mots;  Ici je retrouve les adresse des fonctions à partir d’un hash de leur nom grâce à une petite procédure qui parse l’EAT de la dll chargée en mémoire (un grand classique).

Grosso modo dans tous les cas il faut passer par les étapes suivantes :

 ; Récupère la base addresse de Kernel32 
    invokel _getdll,HASH_KERNEL32.DLL
 ; Récupère l'offset de la fonctions LoadLibraryA
    invokel _getfunction, eax, HASH_LOADLIBRARYA
    mov [FN_LOADLIBRARY], EAX
 ; Charge user32.dll
    invokel [FN_LOADLIBRARY],str_user32
 ; Récupère l'addresse de base de user32.dll  
    invokel _getdll,HASH_USER32.DLL
 ; Récupère l'offset le la fonctions
    invokel _getfunction, eax, HASH_MESSAGEBOXA
    mov [FN_MSGBOX], EAX
  ; Appelle la popup discretos
    invokel [FN_MSGBOX], 0, txt1, txt1, 0
  ; Appel de fonction "Traditionnel" pour quitter  
  invoke _ExitProcess@4, NULL

Une fois compilé, notre appel à MSGBOX est totalement incognito dans la table d’import

$ rabin2 -i nop.exe 
[Imports]
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=kernel32.dll_ExitProcess

1 imports

Et dans ida, rien n’est résolu et nous on ne sait pas trop ce qu’il se passe.

public start
start proc near
push    1C9513FBh
call    sub_40205A
push    0BF89D44Eh
push    eax
call    sub_4020AE
mov     dword_40301A, eax
push    offset aUser32_dll ; "user32.dll"
call    dword_40301A
push    1015679Ah
call    sub_40205A
push    2181CB52h
push    eax
call    sub_4020AE
mov     dword_40301E, eax
push    0
push    offset aHelloDeclared ; "Hello Declared"
push    offset aHelloDeclared ; "Hello Declared"
push    0
call    dword_40301E
push    0               ; uExitCode
call    ExitProcess
start endp

Et pour cause… Rien n’est initialisé, les appels sont cachés.

.data:00403000 aHelloDeclared  db 'Hello Declared',0   ; DATA XREF: start+41o
.data:00403000                                         ; start+46o
.data:0040300F aUser32_dll     db 'user32.dll',0       ; DATA XREF: start + 1Ao
.data:0040301A dword_40301A    dd 0                    ; DATA XREF: start+15w
.data:0040301A                                         ; start+1Fr
.data:0040301E dword_40301E    dd 0                    ; DATA XREF: start+3Aw
.data:0040301E                                         ; start+4Dr

La solution facile dans ce cas là, si l’auteur du malware est sympas et charge tous les offset de fonctions dans une procédure pas loin du démarrage, c’est de dumper le process dans olly après résolution. A partir de là les offsets sont remplis.

.data:00403000 aHelloDeclared  db 'Hello Declared',0   ; DATA XREF: start+41o
.data:00403000                                         ; start+46o
.data:0040300F aUser32_dll     db 'user32.dll',0       ; DATA XREF: start+1Ao
.data:0040301A dword_40301A    dd 7C801D7Bh            ; DATA XREF: start+15w
.data:0040301A                                         ; start+1Fr
.data:0040301E dword_40301E    dd 7E4507EAh            ; DATA XREF: start+3Aw
.data:0040301E                                         ; start+4Dr

Si on utilise olly on peut connaitre l’offset de la dite fonction et se transformer en Champollion. (View > Executable Modules > Bouton Droit > Show File in all module)

Screen Shot 2014-05-22 at 1.11.32

Bon là ca va il y en a que deux fonctions à trouver, mais avec un petit droppeur ou un malware, au bout de la 50eme c’est assez pénible. D’ou le script du jour.

Etape 1, sauver la liste de “All Names”  dans c:\temp\export.txt.

Etape 2, Se rendre ensuite dans IDA avec Python d’actif , mettre le curseur dans une fonction et faire Shift + F7 puis sélectionner ce script magique :  https://github.com/Th4nat0s/Chall_Tools/blob/master/ollylink.py

Etape 3, hurler de joie, ce qui était non renommé et inconnu en Dword_ et qui a trouvé correspondance dans une table d’export est enfin nommé. IDA fait le reste pour mettre les commentaires adaptés.

[+] Loaded 8071 DLL functions
[+] IDA Got 4 Data Ref in 3 Subfunctions in Seg 402000
[+] Find 2 Api call out of 2 unknown ref
public start
start proc near
push    1C9513FBh
call    sub_40205A
push    0BF89D44Eh
push    eax
call    sub_4020AE
mov     LoadLibraryA, eax
push    offset aUser32_dll ; "user32.dll"
call    LoadLibraryA
push    1015679Ah
call    sub_40205A
push    2181CB52h
push    eax
call    sub_4020AE
mov     MessageBoxA, eax
push    0
push    offset aHelloDeclared ; "Hello Declared"
push    offset aHelloDeclared ; "Hello Declared"
push    0
call    MessageBoxA
push    0               ; uExitCode
call    ExitProcess
start endp
.data:00403000 aHelloDeclared  db 'Hello Declared',0   ; DATA XREF: start+41o
.data:00403000                                         ; start+46o
.data:0040300F aUser32_dll     db 'user32.dll',0       ; DATA XREF: start+1Ao
.data:0040301A ; HMODULE __stdcall LoadLibraryA(LPCSTR lpLibFileName)
.data:0040301A LoadLibraryA    dd 7C801D7Bh            ; DATA XREF: start+1w
.data:0040301A                                         ; start+1Fr
.data:0040301E ; int __stdcall MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
.data:0040301E MessageBoxA     dd 7E4507EAh            ; DATA XREF: start+3Aw
.data:0040301E                                         ; start+4Dr

Voila qui est mieux.

This entry was posted in Asm, Reverse and tagged , , . Bookmark the permalink.

2 Responses to IDAPYTHON pour nommer les appels indirects aux fonctions

  1. the-maux says:

    Nice, gain de temps énorme sur certain ctf avec ce mignon petit script.

  2. thanatos says:

    Dummys après m’avoir tabassé sur mon orthographe vient de m’informer de l’existence de :

    http://zairon.wordpress.com/2014/05/15/hardcoded-dll-export-address-python-approach/

Leave a Reply to thanatos Cancel reply

Your email address will not be published. Required fields are marked *

AlphaOmega Captcha Classica  –  Enter Security Code