IDA - The Interactive Disassembler - part 3

Dans cette 3eme partie nous allons voir l'export de notre travail. Il est possible à IDA de produire un fichier .asm à partir du menu / produce / Asm File. Le fichier obtenu, n'est pas directement compilable il faut arranger quelques détails, et selon la complexité du programme il est fort probable pour que ca ne soit pas du tout compilable, mais il peux toujours etre interressant d'extraire des parties, ou des fonctions que l'on recopiera dans une autre source.

En reprenant le listing du code du crackme etudié dans la 2eme partie, nous allons pouvoir admirer le beau boulot que fait IDA, puisque nous allons pouvoir recompiler ce listing en un vrai programmme, tel que l'original.
Bien sur ce programme est très simple donc la ca sera assez facile mais pour des programmes plus complexe c'est beaucoup plus dur voire impossible (quoique).

Avant tout
U n petit détail que je n'ai pas preciser pour faire un peu plus propre dans la déclaration des variables du listing. Les 2 buffers pour le serial et le name sont declaré comme suit :

SerialBuffer db 0 ; ; DATA XREF: _CheckProc+36o
; _CheckProc+4Do
db 0 ;
db 0 ;
db 0 ;
etc... selon le nbr de char

Il est évident que c'est un tableau de caractères, donc pour faire plus propre on se place sur le nom de la variable et on clique sur le boutton de la barre d'outil avec une étoile qui permet de transformer en tableau.
Laissez les options par défaut. Vous obtenez :

DATA:0040200D NameBuffer db 40h dup(0) ; DATA XREF: _CheckProc+9o
DATA:0040200D ; _CheckProc+20o

Ce qui est beaucoup plus lisible :)

Export en .asm et extraction d'une ressource
Il n'y rien de special à retoucher sous IDA, nous ferons les modifs sur le fichier .asm et on peux donc exporter le fichier avce le Menu / produce / asm file. Bien sur il fodra que les modifications que vous y avez apportés respectent les valeurs originelles. Nous obtenons, le code dans un fichier .asm, Maintenant si le programme comporte des ressources comme dans cet exemple il va falloir les dumper du programme original vers un fichier .RES que nous pourrons linker avce le code, ce qui me semble la solution la plus simple. Pour extraire une ressource d'un programme on peux utiliser un extracteur de resource et l'exporter dans un fomat .RC ou .RES (le .RC necessitera une manipulation supplementaire afin de produire un fichier .RES lequel nous pouvons linker) moi j'utilise Resources Hacker un excellent petit outil qui permet directement d'étraire au format .res. Une fois le fichier .asm et .res obtenu on peux passer à l'étape suivante.


Arrangement et compilation sous Tasm


Maintenant, on peux essayer de compiler notre source afin de voir les erreurs que nous indique le compilateur et tenter de les corriger.
Voyons les erreurs du crackme, qui sont trés simple à éliminer. Il nous manque la directive specifiant le type d'instructions du processeur, il suffit de rajouter .386 tout en debut. Il se peux que vous obteniez en debut tout une liste de definitions de constantes windows, vous pouvez pour eclaircir la source les effacer et remplacer par l'inclusion du fichier qui contient ces definissions de constante :

include WINDOWS.INC

Ensuite les problemes qui surviennent proviennent tous d'erreurs de déclaration de fonctions comme par exemple Undefined symbol: SetDlgItemTextA

Pour corriger ca on va lister toutes les API utilisés et les déclarer en debut de source comme suit

global GetModuleHandleA :PROC
global DialogBoxParamA :PROC
global ExitProcess :PROC
global GetDlgItem :PROC
global SetFocus :PROC
global SendMessageA :PROC
global EndDialog :PROC
global GetDlgItemTextA :PROC
global MessageBoxA :PROC
global SetDlgItemTextA :PROC

Voila tout est près on peux compiler avec Tasm et linker avce la ressource, je n'ai pas essayé sous Masm mais c'est surement possible, peut être avec quelques modifs supplementaires...

Voici mon exemple qui contient le fichier .asm produit par IDA, le fichier .res dumpé du programme original et le batch pour la compilation. Download me

Je tiens à répéter que cela n'est pas aussi simple sur d'autres programmes, voir surement impossible. Mais si vous arrivez à recompiler le prog je vous laisse imaginer les possibilitées qui s'ouvre à vous. Notamment un petit truc interressant : la compilation en mode debugging, qui aura pour effet d'ajouter quelques info dans l'exe
(NDOracle: Cf. Tutorial d'Anubis sur la structure du PE) qui pourront être lues par un debugger comme Soft-Ice où vous pourrez alors switcher du code asm à la source qui s'affichera sous Soft-Ice avec les commentaires, variables, fonctions, etc...

Juste pour le fun voici comment faire:

- on recompile le programme avec les options de debugging, pour ca il suffit d'ajouter la commande /zi pour tasm32 et /v pour tlink32 ,comme par exemple:

tasm32 /ml /m3 /zi idaa.asm >> debug.txt
tlink32 -x /Tpe /aa /c /V4.0 /o /v idaa.obj,Crackme1.exe,,c:\tasm\lib\import32.lib,,ress.res >> debug.txt

- On lance le symbol loader de Softice

Par le menu / File / open module on ouvre le programme que l'on vient de compiler. En s'assurrant que la source qui nous à servit à le compiler se situe dans le même répertoire, sinon Softice nous dira qu'il ne peux pas la trouver et proposera soit d'effectuer une recherche manuelle soit de ne pas y preter attention.

Et on charge le programme, avec l'icone représenté par un rouage mecanique. Le loader va s'occuper de générer un fichier .NMS et de charger la source dont le nom a été specifié lors de la compilation et l'ajout des debugs infos.

Et hop nous voila sous Softice dans la source asm :

EAX=00401000   EBX=00000000   ECX=81985AD4   EDX=81985B14   ESI=81985AB4        
EDI=00000000 EBP=0063FF78 ESP=0063FE3C EIP=00401000 O d I S z a P c
CS=01B7 DS=01BF SS=01BF ES=01BF FS=12D7 GS=0000
--------------------------------------------------------------------------------
* ES:DI void * = 0x00000000

  
--------------------------------------------------byte--------------------------
0030:00000000 00 00 00 00 65 04 70 00-16 00 CD 09 65 04 70 00 ....e.p.....e.p.
0030:00000010 65 04 70 00 54 FF 00 F0-79 EA 00 F0 21 EA 00 F0 e.p.T...y...!...
0030:00000020 00 00 00 D0 D2 08 A6 0A-3A 00 CD 09 52 00 CD 09 ........:...R...
0030:00000030 6A 00 CD 09 82 00 CD 09-9A 00 CD 09 65 04 70 00 j...........e.p.
0030:00000040 07 00 70 D0 4D F8 00 F0-41 F8 00 F0 E2 24 60 FD ..p.M...A....$`.
0030:00000050 39 E7 00 F0 40 02 B6 06-2D 04 70 00 28 0A B9 07 9...@...-.p.(...
0030:00000060 00 E0 00 F0 2F 00 8F 0A-6E FE 00 F0 04 06 B9 07 ..../...n.......
0030:00000070 1D 00 00 D0 A4 F0 00 F0-22 05 00 00 12 22 53 04 ........"...."S.
0030:00000080 A8 0F CA 00 45 04 CC 0F-F2 2F AF FC B2 22 83 FD ....E..../..."..
0030:00000090 03 00 D9 10 BC 0F CA 00-82 24 66 FD D0 0F CA 00 .........$f.....
----idaa.asm--------------------------------------------------------------------
00047: 
00048: public start 
00049:start proc near
00050: push 0 ; lpModuleName
00051: call GetModuleHandleA
00052: mov ds:hInstance, eax
00053: push 0 ; dwInitParam
00054: push offset DialogProc ; lpDialogFunc
00055: push 0 ; hWndParent
00056: push offset aMydialog ; lpTemplateName
00057: push ds:hInstance ; hInstance
00058: call DialogBoxParamA
00059: push eax ; uExitCode
00060: call ExitProcess
00061:start endp
00062:
00063:
00064:; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
00065:
00066:
00067:; BOOL DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
00068:; Attributes: bp-based frame
00069:
00070:DialogProc proc near ; DATA XREF: start+Eo 
00071:   
------------------------------------Crackme1------------------------------------
:!screendump
scd1.txt

C'est y pas beau ça mon gars ;)... On dispose des commentaires, des noms de variables, des nom de procédures, les noms des labels etc... Et bien sûr il est possible de tracer le code ainsi que de poser des BP sur ces labels et fonctions et de consulter ces variables avec les commandes habituelles de SI ;)

Allez un ptit screen sur la fonction DialogProc :

EAX=00000000   EBX=0063FBE2   ECX=00000000   EDX=00008C22   ESI=00008C06        
EDI=0063FB98 EBP=0063FBB0 ESP=0063FB94 EIP=0040102B o d I s z a P c
CS=01B7 DS=01BF SS=01BF ES=01BF FS=12D7 GS=1237
--------------------------------------------------------------------------------
* ES:DI void * = 0x54415000
--------------------------------------------------byte--------------------------
0030:00000000 00 00 00 00 65 04 70 00-16 00 CD 09 65 04 70 00 ....e.p.....e.p.
0030:00000010 65 04 70 00 54 FF 00 F0-79 EA 00 F0 21 EA 00 F0 e.p.T...y...!...
0030:00000020 00 00 00 D0 D2 08 A6 0A-3A 00 CD 09 52 00 CD 09 ........:...R...
0030:00000030 6A 00 CD 09 82 00 CD 09-9A 00 CD 09 65 04 70 00 j...........e.p.
0030:00000040 07 00 70 D0 4D F8 00 F0-41 F8 00 F0 E2 24 60 FD ..p.M...A....$`.
0030:00000050 39 E7 00 F0 40 02 B6 06-2D 04 70 00 28 0A B9 07 9...@...-.p.(...
0030:00000060 00 E0 00 F0 2F 00 8F 0A-6E FE 00 F0 04 06 B9 07 ..../...n.......
-----idaa.asm-------------------------------------------------------------------
00063: 
00064:; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ S U B R O U T I N E ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
00065:
00066:
00067:; BOOL DialogProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
00068:; Attributes: bp-based frame
00069:
00070:DialogProc proc near ; DATA XREF: start+Eo
00071:
00072:hWnd = dword ptr 8
00073:uMsg = dword ptr 0Ch
00074:wParam = dword ptr 10h
00075:lParam = dword ptr 14h
00076:
00077: enter 0, 0
00078: cmp [ebp+uMsg], WM_CLOSE
00079: jz short _CloseDlg ; Ferme le dialog
00080: cmp [ebp+uMsg], WM_INITDIALOG
00081: jz short _InitDlg ; Initialisation du dialog
00082: cmp [ebp+uMsg], WM_COMMAND
00083: jz short _Command ; Command actionn, sur le dialog
00084: mov eax, 0
00085: jmp short _LeaveProc
00086:; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
00087:
00088:_CloseDlg: ; CODE XREF: DialogProc+8j
00089: push 0 ; nResult
00090: push [ebp+hWnd] ; hDlg
00091: call EndDialog
00092: mov eax, 1
00093: jmp short _LeaveProc 
------------------------------------Crackme1------------------------------------
:!screendump scd2.txt

On peux switcher entre 3 types de sources : la source depuis le fichier .asm, un melange de celle-ci et du code asm classique, ou alors le code asm classique avce tout de meme les noms des labels. Pour changer de vue on tape src et on peux les faires défiler avce F3.

Screen mode de vue source asm et code classique mélangé:

EAX=00000000   EBX=0063FBE2   ECX=00000000   EDX=00008C22   ESI=00008C06        
EDI=0063FB98 EBP=0063FB90 ESP=0063FB90 EIP=0040103C o d I S z a p C
CS=01B7 DS=01BF SS=01BF ES=01BF FS=12D7 GS=1237
--------------------------------------------------------------------------------
* ES:DI void * = 0x54415000
--------------------------------------------------byte--------------------------
0030:00000000 00 00 00 00 65 04 70 00-16 00 CD 09 65 04 70 00 ....e.p.....e.p.
0030:00000010 65 04 70 00 54 FF 00 F0-79 EA 00 F0 21 EA 00 F0 e.p.T...y...!...
0030:00000020 00 00 00 D0 D2 08 A6 0A-3A 00 CD 09 52 00 CD 09 ........:...R...
0030:00000030 6A 00 CD 09 82 00 CD 09-9A 00 CD 09 65 04 70 00 j...........e.p.
0030:00000040 07 00 70 D0 4D F8 00 F0-41 F8 00 F0 E2 24 60 FD ..p.M...A....$`.
0030:00000050 39 E7 00 F0 40 02 B6 06-2D 04 70 00 28 0A B9 07 9...@...-.p.(...
0030:00000060 00 E0 00 F0 2F 00 8F 0A-6E FE 00 F0 04 06 B9 07 ..../...n.......
-----DialogProc+000-------------------------------------------------------------
00080 cmp [ebp+uMsg], WM_INITDIALOG 
01B7:00401035 817D0C10010000 CMP DWORD PTR [EBP+0C],00000110 
00081 jz short _InitDlg ; Initialisation du dialog
01B7:0040103C 7421 JZ _InitDlg (NO JUMP)
00082 cmp [ebp+uMsg], WM_COMMAND
01B7:0040103E 817D0C11010000 CMP DWORD PTR [EBP+0C],00000111
00083 jz short _Command ; Command actionn, sur le dialog
01B7:00401045 7432 JZ _Command
00084 mov eax, 0
01B7:00401047 B800000000 MOV EAX,00000000
00085 jmp short _LeaveProc
01B7:0040104C EB57 JMP _LeaveProc
_CloseDlg
00089 push 0 ; nResult
01B7:0040104E 6A00 PUSH 00
00090 push [ebp+hWnd] ; hDlg
01B7:00401050 FF7508 PUSH DWORD PTR [EBP+08]
00091 call EndDialog
01B7:00401053 E8A20F0000 CALL USER32!EndDialog
00092 mov eax, 1
01B7:00401058 B801000000 MOV EAX,00000001
00093 jmp short _LeaveProc
01B7:0040105D EB46 JMP _LeaveProc
_InitDlg
00097 push 3E8h ; Edit-box Name
01B7:0040105F 68E8030000 PUSH 000003E8
00098 push [ebp+hWnd] ; hDlg
01B7:00401064 FF7508 PUSH DWORD PTR [EBP+08]
00099 call GetDlgItem
01B7:00401067 E86A0F0000 CALL USER32!GetDlgItem
00100 push eax ; hWnd 
01B7:0040106C 50 PUSH EAX   
------------------------------------CRACKME1!CODE+0035--------------------------
:!screendump scd3.txt

Et code classique avec nom des labels


EAX=00000000   EBX=0063FBE2   ECX=00000000   EDX=00008C22   ESI=00008C06        
EDI=0063FB98 EBP=0063FB90 ESP=0063FB90 EIP=0040103C o d I S z a p C
CS=01B7 DS=01BF SS=01BF ES=01BF FS=12D7 GS=1237
--------------------------------------------------------------------------------
* ES:DI void * = 0x54415000
--------------------------------------------------byte--------------------------
0030:00000000 00 00 00 00 65 04 70 00-16 00 CD 09 65 04 70 00 ....e.p.....e.p.
0030:00000010 65 04 70 00 54 FF 00 F0-79 EA 00 F0 21 EA 00 F0 e.p.T...y...!...
0030:00000020 00 00 00 D0 D2 08 A6 0A-3A 00 CD 09 52 00 CD 09 ........:...R...
0030:00000030 6A 00 CD 09 82 00 CD 09-9A 00 CD 09 65 04 70 00 j...........e.p.
0030:00000040 07 00 70 D0 4D F8 00 F0-41 F8 00 F0 E2 24 60 FD ..p.M...A....$`.
0030:00000050 39 E7 00 F0 40 02 B6 06-2D 04 70 00 28 0A B9 07 9...@...-.p.(...
0030:00000060 00 E0 00 F0 2F 00 8F 0A-6E FE 00 F0 04 06 B9 07 ..../...n.......
-----DialogProc+000-------------------------------------------------------------
01B7:00401035 817D0C10010000 CMP DWORD PTR [EBP+0C],00000110 
01B7:0040103C 7421 JZ _InitDlg (NO JUMP) 
01B7:0040103E 817D0C11010000 CMP DWORD PTR [EBP+0C],00000111
01B7:00401045 7432 JZ _Command
01B7:00401047 B800000000 MOV EAX,00000000
01B7:0040104C EB57 JMP _LeaveProc
_CloseDlg
01B7:0040104E 6A00 PUSH 00
01B7:00401050 FF7508 PUSH DWORD PTR [EBP+08]
01B7:00401053 E8A20F0000 CALL USER32!EndDialog
01B7:00401058 B801000000 MOV EAX,00000001
01B7:0040105D EB46 JMP _LeaveProc
_InitDlg
01B7:0040105F 68E8030000 PUSH 000003E8
01B7:00401064 FF7508 PUSH DWORD PTR [EBP+08]
01B7:00401067 E86A0F0000 CALL USER32!GetDlgItem
01B7:0040106C 50 PUSH EAX
01B7:0040106D E8820F0000 CALL USER32!SetFocus
01B7:00401072 B800000000 MOV EAX,00000000
01B7:00401077 EB2C JMP _LeaveProc
_Command
01B7:00401079 8B4510 MOV EAX,[EBP+10]
01B7:0040107C 663DEA03 CMP AX,03EA
01B7:00401080 750A JNZ _TestNextId
01B7:00401082 FF7508 PUSH DWORD PTR [EBP+08]
01B7:00401085 E81F000000 CALL _CheckProc
01B7:0040108A EB14 JMP _LeaveProc2
_TestNextId
01B7:0040108C 663DEB03 CMP AX,03EB
01B7:00401090 750E JNZ _LeaveProc2
01B7:00401092 6A00 PUSH 00 
01B7:00401094 6A00 PUSH 00   
------------------------------------CRACKME1!CODE+0035--------------------------
:!screendump scd4.txt

Pour continuer dans l'export nous verrons dans la 4eme et derniere partie, à defaut de ne pouvoir recompiler la source, comment exporter tout de meme le listing de IDA vers Softice à l'aide des fichiers .MAP et du fabuleux plug-in 'ida2sice'.