Microsoft Windows Debugger (WinDbg)
http://www.microsoft.com/ddk/debugging/

Windbg est un debugger developpé par Microsoft et distribué gratuitement sur leur site.
Ce debugger est une tres bonne alternative au supreme SoftIce. Une alternative qui peux vous servir contre une protection anti-softice ou si vous êtes sous Windows XP, car même si depuis la sortie de DriverStudio Softice est devenu compatible avec ce system, il en a aussi perdu tout ses points forts pour le cracking pollué de bugs (plus de break a l'entry-point, apres un BP sur une api et un F12 pour quitter celle-ci et revenir dans notre programme softice ne reprend pas le controle, des problemes de BP, des commandes qui ne sont plus accessibles pour les system NT etc...) bref pour ces raisons je vous propose de decouvrir WinDbg, un debugger tres puissant avec une grande ressemblance avec softice au niveau de la syntaxe des commandes ce qui permet de ne pas etre trop deboussolé.

WinDbg possède de nombreuses fonctions (comme debug du kernel, debugging a partir d'un server, etc..) je ne rentrerais pas dans ces fonctionnalités inutiles pour le cracking standard d'une application. Je vous conseille de lire l'aide très complète de WinDbg dans laquelle vous pourrez trouver toutes les commandes et options.

L'interface Graphique

WinDbg est composé de plusieurs fenetres que l'on peux afficher via le Menu View ou à partir de la barre d'outils.

The Command Window (Command - ALT+1) :
C'est le fenetre principale dans laquel on tappe les commandes et dans laquel sera affiché tout ce qui se passe.

The Watch Window (Watch - ALT+2) :
Cette fenetre affiche les informations sur des variables globales, locales ou sur des registres on peux s'en servir pour suivre une variable precise.

The Locals Window (Locals - ALT+3) :
Cette fenetre affiche toutes les variables locales en cours

The Registers Window (Registers - ALT+4) :
Affiche tous les registres les flags du processeur.

The Memory Window (Memory - ALT+5) :
Affiche la mémoire sous la forme souhaité (byte, word, dword, ascii, etc..) à partir d'une adresse souhaité

The Calls Window (Call Stack - ALT+6) :
Affiche des informations sur la pile lors des call

The Disassembly Window (Disassembly - ALT+7) :
Affiche le code executable en assembleur

The Scratch Pad (Scratch Pad - ALT+8) :
Petite fenetre qui sert a prendre des notes, n'ayant aucun effet sur le debugging.

Libre à vous de personnaliser l'affichage de ces fenêtres et de customiser les couleurs et les options de police à partir du Menu View, voici un petit apercu en seance de debugging:

Lancement de la cible

On sélectionne la cible que l'on veut debugger par le menu par File / Open Executable, on peut aussi attacher un process tournant déja en mémoire par File / Attach to a Process.

Après ouverture dans la fenetre de commande vous devriez obtenir à peu pres ceci:

Symbol search path is: c:\
CommandLine: C:\netix\compil.exe
Symbol search path is: c:\
Executable search path is: c:\
ModLoad: 00400000 00405000 image00400000
ModLoad: 77f40000 77ff0000 ntdll.dll
ModLoad: 77e40000 77f35000 C:\WINDOWS\system32\kernel32.dll
ModLoad: 77d10000 77d9d000 C:\WINDOWS\system32\USER32.dll
ModLoad: 77c40000 77c80000 C:\WINDOWS\system32\GDI32.dll
ModLoad: 77da0000 77e3c000 C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77c90000 77d05000 C:\WINDOWS\system32\RPCRT4.dll
(300.740): Break instruction exception - code 80000003 (first chance)
eax=77fb642f ebx=7ffdf000 ecx=00000004 edx=77f67010 esi=00241eb4 edi=00241eb4
eip=77f6f570 esp=0012fb38 ebp=0012fc2c iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
*** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll -
ntdll!DbgBreakPoint:
77f6f570 cc int 3

Les 4 premières lignes affichent le chemin de l'executable, ainsi que les dossiers dans lesquels seront cherchés les informations de debuggingcomme des fichiers .dbg, les sources etc.. Ce qui ne nous interresse pas pour le cracking puisque vous n'avez normalement pas ces fichiers :)
Cependant nous verrons comment exporter de IDA un fichier .MAP et le transformer en fichier .DBG afin d'utiliser les labels, definis précédement sous IDA, avec windbg. Suivent les modules qui ont été chargés, image0040000 correspondant à notre programme, suivi des dll les plus courantes. (on peux charger une autre dll depuis la fenetre de commande).

Ensuite sont affichés tous les registres, par défaut à chaque fois que vous tracez une instruction, tous les registres seront affichés dans la fenetre de commandes, pour stopper cette option il suffit de tapper pr
(p pour step over et r pour registre , nous reviendrons sur ces commandes plus tard)

On voit un message d'erreur:
*** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll - ,
du fait que le debugger n'a pas trouvé les fichiers de debuggings, ce qui est tout a fait normal dans notre cas, ne vous inquitez pas.

Controle de la cible

Si le programme cible est actif vous n'aurez pas la possibilité de le controler ou de lancer des commandes.
Il faut avant tout le "freezer" (geler) en appuyant sur le boutton Break de la barre d'outil.
Ce qui aura pour effet de donner le contrôle au debugger (comme ctrl-d sous SoftIce)

Pour redonner le contrôle au programme il suffit de tapper la commande g ou d'appuyer sur la touche F5 du clavier.

Voici un petit recapitulatif des actions de bases pour controler le programme, avec en dernier la colone pour faire la comparaison avec les touches de softice.

Command Name
Command
WinDbg Menu
WinDbg Shortcut Key
SoftIce Shortcut Key
Break
-
Debug | Break
CTRL+BREAK
CTRL+D
Go
G (Go)
Debug | Go
F5
F5
Step Into
T (Trace)
Debug | Step Into
F8 - F11
F8
Step Over
P (Step)
Debug | Step Over
F10
F10
Step Out
g @$ra
Debug | Step Out
SHIFT+F11
F12
Go to Next Call
PC (Step to Next Call)
TC (Trace to Next Call)
-
-
Go to Next Branch
TB (Trace to Next Branch)
-
-
Trace and Watch
WT (Trace and Watch Data)
-
-
Trace to Next Branch
TB (Trace to Next Branch)
-
-
Go with Exception Handled
GH (Go with Exception Handled)
Debug | Go Handled Exception
-
Go with Exception Not Handled
GN (Go with Exception Not Handled)
Debug | Go Unhandled Exception
-
Run to Cursor
-
Debug | Run to Cursor
F7 - CTRL+F10
Restart
.restart (Restart Target Application)
Debug | Restart
CTRL+SHIFT+F5
Stop Debugging
-
Debug | Stop Debugging
SHIFT+F5

Les Breakpoints

Voici la liste des commandes pour controler les Breakpoints.
Les parametres optionnels sont mis entre crochets.( les crochets ne sont pas necessaires, quand on tape l'instruction sauf dans le cas ou l'on placerais une expression comme [2+1] ).
Je detaille ici les commandes avec les parametres les plus courants, pour plus de details consulter l'aide.

- BL (Breakpoint List) - Liste les breakpoints et leur statut

Syntaxe : bl [ID]

Cette commande liste avec leurs statut les breakpoint posés lors de la session de debugging, ID represente un chiffre optionnel qui identifie le breakpoint. Si ID n'est pas specifier tout les breakpoints seront listés. Plusieurs details permette de determiner le statut du breakpoint listé, voici la forme :

0 e 77d3add7 0001 (0001) 0:*** USER32!MessageBoxA

0 represente l'ID du breakpoint (son numero dans la liste)
e pour Enabled (actif) pour dire que le breakpoint est actif, la lettre d pour Disabled (desactivé) sera affiché si le breakpoint est desactivé
77d3add7 suit l'adresse virtuel du breakpoint, ici il est placé dans USER32.dll pour la fonction MessageBoxA
0001 decompte du nbr de passe avant que le breakpoint ne break (voir BP)
(0001) nbr de passe a effectué pour que le breakpoint ne break

- BP (Set Breakpoint) - Place un breakpoint

Syntaxe : bp[ID] [/f PredNum] [Address [Passes]] ["CommandString"]

Cette commande place un BreakPoint, on peux en placer sur une adresse, un label, une fonction combiné avec ou sans options.

[ID] : determine le numero du breakPoint tel qu'il apparaitra dans la liste, le chiffre doit etre collé a la commande (ex: bp2)

[/f PredNum] IA-64
: est un parametre resérvé uniquement pour les processeurs à architecture IA-64

[Address]
: Adresse ou le breakPoint est placé, si l'adresse n'est pas specifié, le breakpoint est placé sur l'adresse en cours

[Passes]
: Nbr de fois que le debugger passera sur le point du breakpoint avant de l'activer et de breaker

["CommandString"]
: Specifie une liste de commande à executer lors du breakpoint, Cette commande est effective seulement si le debugger à été lancé par la commande G (F5), si le debugger est en mode trace step cette commande ne sera pas effectué.
La commande doit etre encadré par des guillemets, plusieurs commandes peuvent etres separés par semicolon ( ; )

exemple : bp2 messageboxa 5 "r eax; dd esp; g"
Le breakpoint aura l'ID 2 ( bp2) , placé sur l'api MessageBoxA, il breakera au bout de la 5 passe sur cette fonction, et lors du break il affichera la valeur du registre eax ( r eax) ; affichera la memoire en double sur le registre esp ( dd esp) ; et redonnera la main au programme ( g ).

Il est possible de poser des BP conditionnels en placant la commande dans l'expression, voir plus bas la commande de condition.

- BA (Break on Access) - BreakPoint sur une zone memoire lorsque celle-ci est sollicité (comme bpm pour softice)

Syntaxe : ba[ID] Access Size [/f PredNum] [Address [Passes]] ["CommandString"]

La plupart des parametres sont les memes que pour BP, seuls 2 arguments supplementaire et obligatoires figure pour cette commande :

Access : determine le type d'acces à la mémoire

e (execute)
break lors de le rencontre d'une instruction a l'adresse specifié
r (read/write)
break lors de la lecture et ecriture à l'adresse specifié
w (write)
break lors de l'ecriture seulement
i (i/o)
break sur i/o d'un port a l'adresse specifié

Size : taille en byte de la memoire à surveillé, peut etre 1, 2 ou 4 bytes

Il n'est pas necessaire de separé l'acces et la taille par un espace

exemple : ba r4 401580
Breakpoint sur l'adresse memoire 401580 en lecture/ecriture sur 4 bytes (dword) (de 401580 à 401584)


- BC (Breakpoint Clear)
- Efface un breakpoint

Syntaxe : BC breakpoint

breakpoint : ID du breakpoint à effacer, pour effacer tous les breakpoints on utilise * à la place de l'ID

exemple : bc *


- BD (Breakpoint Disable) - Desactive un Breakpoint

Syntaxe : BD breakpoint

breakpoint : ID du breakpoint à desactiver, pour désactiver tous les breakpoints on utilise * à la place de l'ID

exemple : bd *

- BE (Breakpoint Enable) - Active un Breakpoint

Syntaxe : BE breakpoint

breakpoint : ID du breakpoint à activer, pour activer tous les breakpoints on utilise * à la place de l'ID

exemple : be *

Conditional Breakpoints :

Pour poser des breakpoint conditionnels on se sert d'une commande J (Execute If - Else) dont voici la syntaxe, que l'on placera dans le parametre commande

J Expression Command1 ; Command2
ou
J Expression 'Command1' ; 'Command2'

Expression : expression à tester, si le resultat est non-zero la command 1 est executé, si le resultat est zero la command2 est executé.
Command1 : commande d'action à executer, on peux placer plusieurs commande si on se sert de la syntaxe avec les '' entourant les commandes et separé par des semicolon, si c'est une commande unique les '' ne sont pas nécéssaire
Command2 : idem que Command1

exemple : bp messageboxa " j (eax != 0) g ; 'r eax; r edx' "
Dans cet exemple, on pose un BP sur MessageBoxA, si eax est different de 0 on continue ( g ), sinon on break et on affiche la valeur du registre eax et de edx ( 'r eax; r edx' )

Lire et modifier la mémoire

On peux lire et ecrire directement en mémoire localisé par une adresse ou le nom d'une variable. On peux acceder sous plusieurs format tel que : hexadecimal bytes, words, double words, quad-words; short, long, quad integers et unsigned integers; 10, 16, 32, et 64 byte real numbers, et en caracteres ASCII. On y accede via les commandes suivantes:

Pour specifier une plage de memoire on peux utliser 2 formes :
Adresse de depart et adresse de fin : 401000 401008 (plage contenu entre 401000 et 401008 soit 8 bytes)
Adresse de depart et taille de la plage avec la commande L suivi d'une valeur defini precedement : 401000 L8

D* (Display Memory)

Affiche la memoire situé à l'adresse preciser au format presicer à la place de * : exemple dd 405120 (affiche la memoire en format dword à partir de l'adresse 405120) autre exemple : db 401000 L8 (affiche la memoire de forme byte avec l'adresse de depart 401000 et de longueur 8 bytes; byte car nous avons specifier ce type par db, si nous avions mis dd, la plage memoire serait de 8 dword et non 8 bytes)

E* (Enter Values)

Modifie la memoire. exmple : eb 402150 12 ( ecrase le byte se trouvant à l'adresse 402150 avec la valeur 12 )

M (Move Memory)

Copie une portion de memoire vers une autre adresse

Syntaxe : m range address

range : plage de l'adresse à copier
address : adresse de depart ou la memoire sera copier

F (Fill Memory)
Remplit tout une plage de mémoire avec des valeurs

Syntaxe : f Range Pattern

range : plage d'adresse mémoire à remplir
Pattern : specifie un ou plusieurs byte avec lesquels remplir la memoire

exemple : f 401000 L50 'A' 'B' 'C'

Cette operation va remplir la plage memoire entre 401000 et 401050 des valeurs ascii A B et C se succedant.

C (Compare Memory)
Compare le contenu de 2 plages memoire

Syntaxe : c Range Address

Range : la premiere des 2 plage memoire à comparer
Address : adresse de depart de la 2eme plage memoire à comparer

exemple : c 401000 L10 402000
Compare la plage entre 401000 et 401010 avec la plage de meme taille debutant à l'adresse 402000

S (Search Memory)
Recherche une valeur dans une plage memoire (tres utile pour recherché un serial ou votre nom que vous avez entré)

Syntaxe1 : s [-Type] Range Pattern
Syntaxe2 : s -v Range Object

Type : Type de memoire à chercher :

Type
Description
w
Word (16 bits)
d
DWord (32 bits)
q
QWORD (64 bits)
a
ASCII string
u
Unicode string

Range : Plage memoire ou effectué la recherche, la plage ne peux ecceder 250 MO de taille.
Pattern : Valeur a retrouver, si on specifie une string on la placera entre guillemets
-v : oblige le debugger à rechercher des objets que le meme type d'objet specifier
Object : specifie l'adresse d'un Objet, pour determiner le type d'objet a chercher dans la plage

Si la valeur est retrouvé, le debugger affichera l'adresse de depart de celle ci

exemple : s -a 0012ff40 L20 "Hello"

Lire et modifier les registres et les flags

La commande R (Registers) permet de modifier un registre ou un flag, exemple : r eax = 5 ou r zf = 1
On peux aussi modifier les registres à partir de la fenetre des registres en selectionnant celui que l'on souhaite modifier, en double cliquant dans sa case valeur et en ecrivant la nouvelle valeur.

En tracant, tout les registres seront affichés dans le fenetre de commande, on peux stopper cette fonction en tappant PR p correspondant a la commande STEP (F10) et r pour registre annulant ainsi cette fonction en retappant cette commande on la reactive.

Modifier et rechercher du code assembleur

La commande # (Search for Disassembly Pattern) permet de rechercher un pattern (adresse, instruction, expression, valeur, registre ou tout autre text ) dans la fenetre du code désassemblé

Syntaxe : # [pattern] [address]

pattern : pattern a recherché dans le fentre du code désassemblé
address : adresse ou la recherche va commencer

voici quelques exemples, nous avons ce code:

00401000 6a00             push    0x0
00401002 e8c9010000 call image00400000+0x11d0 (004011d0)
00401007 a300304000 mov [image00400000+0x3000 (00403000)],eax
0040100c 6a00 push 0x0
0040100e 682b104000 push 0x40102b
00401013 6a00 push 0x0
00401015 6804304000 push 0x403004
0040101a ff3500304000 push dword ptr [image00400000+0x3000 (00403000)]
00401020 e875010000 call image00400000+0x119a (0040119a)
00401025 50 push eax

en tappant la commande # mov 401000, le debugger nous retournera :

00401007 a300304000       mov     [image00400000+0x3000 (00403000)],eax

Qui est la premiere adresse ou l'on rencontre le pattern 'mov', on peux tres bien rechercher une valeur comme A3 sui sera retourné à l'adresse 401007 comme la valeur hexa de l'instruction asm qui suit. Bref une commande tres pratique pour recherché tout et n'importe quoi dans le code désassemblé.

Pour modifier du code directement en assembleur on se sert de la commande A

A (Assemble)

Syntaxe : a [address]

adress : etant l'adresse de depart ou modifier le code, si l'on ne specifie pas d'adresse la modification commence à l'adresse courante, pour sortir du mode assembleur il suffit de presser la touche ENTRER sans entrer de nouvelle instruction.

Diverse commandes utiles

Il existe de tres nombreuses commandes sous Windbg, il serait fou de toute les lister mais voici quelques une souvent utilisés, pour plus de renseignement voir dans l'aide ou toutes les commandes sont decrites en details.

N : La base numerique utilsé par defaut par le debugger est l'hexadecimal, on peux en changer en tappant la commande N suivi de la base souhaité : n 10 (decimal), en tappant simplement n le debbugger affiche la base courante.

? : Permet Evaluer une expression, un registre, une variable.. Comme sous softice. exemple : ? eax, ? E52F

.cls : efface la fenetre des commande

!dh [Module Name] : Affiche le header du module specifier (generalement le nom de votre module sera image00400000)

LM : Liste les modules chargés

.load : charge une nouvelle DLL dans le debugger

x : affiche tous les symbols contenu dans un module exemple : x user32!mes* affichera toutes les fonctions contenu dans User32.dll commenecant par 'mes'

ENTER : (La touche) repete la commande precedente

.tlist : List tous les programme chargé en memoire

.reboot : Reboot le system en cas de gros plantage

.formats : Affiche dans plusieurs format une expression ou une valeur

.kill : Termine un processus


Philosophie de WindDbg

Voila les presentations sont faites, bien sur il faut un petit temps d'adaptation pour s'en servir efficacement, ce debugger possede beaucoup de fonctions et de possibilités, encore une fois allez faire un tour dans l'aide (tres complete) qui vous detaillera toutes les possibilté de celui-ci.

Sur le net il est tres dur de trouver des tutos de crack avec Windbg, voir impossible, c'est ce qui m'a aussi poussé a faire ce tutorial. Et j'espere que la pratique et l'utilisation de ce debugger se repandra un peu permettant d'elaborer des techniques, scripts et des plug-ins avancés. A mon humble avis ce debugger à sa place dans le monde du cracking, surtout pour ceux qui souhaite utiliser un debugger efficace sous XP et qui sont rebutté comme moi par DriverStudio.

Les commandes etant tres proche de celle de softice les habitué de SI n'auront aucun probleme à se servir de ce debugger et la methode de travail reste sensiblement la meme. Peut etre un peu moins simple à s'en servir du fait qu'il faille je pense quelques notions et base de cracking avant de se lancer dans ce debugger et de s'en servir efficacement... D'un autre coté le mode graphique et certaines options apparaitront plus conviviales aux yeux de certains.

Lors d'un BP sur une API, le debugger va breaker sous les dll system auquel appartienne l'api sollicité. C'est a dire que l'on se retrouve avant tout dans les dll du system avant d'etre dans notre module. Pour sortir des ces dll et aller dans notre module on peux faire comme sous SI et F12, sous WinDbg (SHIFT+F11) ou alors le boutton step out. On peux aussi tracer un peu avec F10 dans ces dll system ou l'on pourra ainsi voir les parametre pushé et etudier leurs valeurs avant que la fonction ne s'execute, ensuite nous rencontrerons un ret qui suffira de tracer et qui nous rammenera dans notre programme.

Sous Windbg quand on trace sur l'adresse de l'instruction courante, sera rajouté selon l'instruction des infos supplementaires comme l'evaluation d'une valeur, une valeur pointé par une adresse, le nom d'une fonction etc...

Apercu d'un crack avec WInDbg

Voici un mini-tutorial sur un petit crackme, pour montrer comment travailler avec Windbg. Bien sur, étant donné que j'ai exploré ce debugger par moi meme, sans avoir pu trouver un seul tutorial et d'autres experiences de cracking complete avec cet outil et qu'il reste relativement nouveau pour moi, je n'ai pas la pretention de donner la methode ultime ou de maitriser parfaitement cet outil, mais simplement je veux vous expliquer comment je m'en sers pour les fonctions de bases.

On ouvre le programme via le menu File | open executable.

CommandLine: C:\netix\compil.exe 
Symbol search path is: c:\
Executable search path is: c:\
ModLoad: 00400000 00405000 image00400000
ModLoad: 77f40000 77ff0000 ntdll.dll
ModLoad: 77e40000 77f35000 C:\WINDOWS\system32\kernel32.dll
ModLoad: 77d10000 77d9d000 C:\WINDOWS\system32\USER32.dll
ModLoad: 77c40000 77c80000 C:\WINDOWS\system32\GDI32.dll
ModLoad: 77da0000 77e3c000 C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77c90000 77d05000 C:\WINDOWS\system32\RPCRT4.dll
(59c.2ac): Break instruction exception - code 80000003 (first chance)
eax=77fb642f ebx=7ffdf000 ecx=00000004 edx=77f67010 esi=00241eb4 edi=00241eb4
eip=77f6f570 esp=0012fb38 ebp=0012fc2c iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
*** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll -
ntdll!DbgBreakPoint:
77f6f570 cc int 3

Windbg nous affiche les modules alors chargé, tels que User32, Kernel32 etc... Notre programme se nomme image00400000 Puis l'adresse ou le debugger à breaké : 77f6f570 cc int 3

Contrairement à SoftIce nous ne somme pas sous notre module à l'entry-point, et si nous voulons faire un un break sur l'entry point, il va falloir le specifier. Pour cela, on affiche le header de notre crackme et on recupere l'entry-point avec la commande:

!dh image00400000

ce qui nous interresse est ici :
OPTIONAL HEADER VALUES
10B magic #
5.12 linker version
200 size of code
600 size of initialized data
0 size of uninitialized data
1000 address of entry point
1000 base of code
----- new -----
00400000 image base


On pose donc un BP sur l'image base + l'entry point pour obtenir l'adresse virtuelle de celui-ci:
bp 00400000+1000 (ou directement 401000)

Ne vous inquietez pas si vous obtenez des erreurs, celles ci viennent du fait que notre module est correctement chargé mais qu'aucun symbol n'est present dans celui-ci. Les symbols etant des labels, noms de variables fonctions etc.. qui sont normalement inserés dans un prog pendant la compilation et déstinés à faciliter le debugging par la suite.

Etant donné que le programme n'a normalement pas ces informations , le debugger nous en rendra compte. On redonne la main au programme avec la touche F5 ou la commande G, aussitot celui-ci break et nous nous retrouvons sur notre bp dans la fenetre du code:

00400ffa 0000             add     [eax],al
00400ffc 0000 add [eax],al
00400ffe 0000 add [eax],al
00401000 6a00 push 0x0
00401002 e8c9010000 call image00400000+0x11d0 (004011d0)
00401007 a300304000 mov [image00400000+0x3000 (00403000)],eax
0040100c 6a00 push 0x0
0040100e 682b104000 push 0x40102b
00401013 6a00 push 0x0
00401015 6804304000 push 0x403004
0040101a ff3500304000 push dword ptr [image00400000+0x3000 (00403000)]

On pose un bp sur l'api MessageBoxA et lui redonne la main avec G ou F5

bp messageboxa

Si vous obtenez à nouveau un message d'erreur sur les symbols ne vous inquitez pas c'est le dernier, apres le debugger ne nous embetera plus avec ca, il aura surement compris que nous crackeur n'avons pas besoins de ces shits la pour debugger

On rempli les champs du crackme avec un nom et un serial et on presse le boutton check, ca break et on se retrouve ici:

USER32!MessageBoxA:
77d3add7 833dc4d3d67700 cmp dword ptr [USER32!VRipOutput+0x357d (77d6d3c4)],0x0 ds:0023:77d6d3c4=00000000
77d3adde 0f85377e0100 jne USER32!TrackPopupMenu+0x6ca1 (77d52c1b)
77d3ade4 6a00 push 0x0
77d3ade6 ff742414 push dword ptr [esp+0x14]
77d3adea ff742414 push dword ptr [esp+0x14]
77d3adee ff742414 push dword ptr [esp+0x14]
77d3adf2 ff742414 push dword ptr [esp+0x14]
77d3adf6 e803000000 call USER32!MessageBoxExA (77d3adfe)
77d3adfb c21000 ret 0x10

Ici on a breaké dans une dll du systeme, USER32 qui contient la fonction MessageBoxA, on voit que l'API est referencé par un label en tout debut avec USER32!MessageBoxA puis les arguments qui vont etre passés pour cette fonction.

On pourrait comme sous SI faire un F12 (sous Windbg un SHIFT+F11 ou le boutton Step out) ce qui aurait pour effet d'executer l'API MessageBox, et ensuite une fois que nous aurions quitté la message box, le debugger nous redonnerais la main dans notre programme en se placant juste apres le call de la messagebox. Cepandant on peux ici de voir les arguments qui seront passé pour la message box avant que celle-ci s'affiche. Pour cela nous restons nous restons dans la dll system et nous tracons avec F10. Les instructions qui suivent sont les push des argument pour MessageBoxA , exemple du 2eme argument pushé , lorsque l'on arrive dessus les infos suivantes sont ajoutées :

77d3adea ff742414 push dword ptr [esp+0x14] ss:0023:0012fbc8=00401147

Cet argument selon le prototype represente le titre de la message box, pour voir celui-ci il suffit de tapper la commande suivante dans le fenetre de commande:

d 00401147 et on obtient :

0:000> d 00401147
00401147 45 72 72 6f 72 20 21 21-20 42 41 44 20 53 65 72 Error !! BAD Ser
00401157 69 61 6c 20 2d 20 74 72-79 20 61 67 61 69 6e 00 ial - try again.
00401167 6a 00 68 47 11 40 00 68-47 11 40 00 6a 00 e8 38 j.hG.@.hG.@.j..8
00401177 00 00 00 5a 5f 5e c9 c2-04 00 68 8d 30 40 00 68 ...Z_^....h.0@.h
00401187 e9 03 00 00 ff 75 08 e8-2b 00 00 00 5a 5f 5e c9 .....u..+...Z_^.
00401197 c2 04 00 ff 25 28 20 40-00 ff 25 1c 20 40 00 ff ....%( @..%. @..
004011a7 25 10 20 40 00 ff 25 24-20 40 00 ff 25 0c 20 40 %. @..%$ @..%. @
004011b7 00 ff 25 20 20 40 00 ff-25 14 20 40 00 ff 25 18 ..% @..%. @..%.


Remarques : on peux aussi se servir de la fenetre Memory et en entrant l'adresse à visualiser sous la forme byte et ascii, pour obtenir la meme chose.

On continu à tracer, depassé le call, la MessageBox va s'afficher, on clik OK sur celle -ci et le debugger reprend la main, en pointant sur l'instruction qui suit, a savoir un ret qui va nous faire revenir dans notre programme juste apres le call de la messagebox, (comme si nous avions effectué le step out des le debut) :

0040116b 114000           adc     [eax],eax
0040116e 6847114000 push 0x401147
00401173 6a00 push 0x0
00401175 e838000000 call image00400000+0x11b2 (004011b2)
0040117a 5a pop edx
0040117b 5f pop edi
0040117c 5e pop esi
0040117d c9 leave
0040117e c20400 ret 0x4
00401181 688d304000 push 0x40308d
00401186 68e9030000 push 0x3e9


On efface les précédents BP et on en place un sur GetDlgItemTextA

bc * (efface tous les breakpoints)

bp GetDlgItemTextA

On redonne la main au programme avec F5, on entre un nom et un serial et on clik sur le boutton Check, ca break dans USER32! :

USER32!GetDlgItemTextA:
77d3274f 55 push ebp
77d32750 8bec mov ebp,esp
77d32752 ff750c push dword ptr [ebp+0xc]
77d32755 ff7508 push dword ptr [ebp+0x8]
77d32758 e84b63feff call USER32!GetDlgItem (77d18aa8)
77d3275d 85c0 test eax,eax
77d3275f 0f84148f0200 je USER32!TrackPopupMenu+0xf6ff (77d5b679)
77d32765 ff7514 push dword ptr [ebp+0x14]
77d32768 ff7510 push dword ptr [ebp+0x10]
77d3276b 50 push eax
77d3276c e8c999ffff call USER32!GetWindowTextA (77d2c13a)
77d32771 5d pop ebp
77d32772 c21000 ret 0x10


Vous pouvez explorer comment cette api fonctionne en tracant cette petite partie et en regardant les valeurs des push.
Pour etre plus direct, faisons un ret vers notre programme avec SHIFT+F11 ou step out
004010b1 6a10             push    0x10
004010b3 680d304000 push 0x40300d
004010b8 68e8030000 push 0x3e8
004010bd ff7508 push dword ptr [ebp+0x8]
004010c0 e8e7000000 call image00400000+0x11ac (004011ac)
004010c5 83f805 cmp eax,0x5
004010c8 0f8cb3000000 jl image00400000+0x1181 (00401181)
004010ce 8d350d304000 lea esi,[image00400000+0x300d (0040300d)]
004010d4 56 push esi
004010d5 8a16 mov dl,[esi]
004010d7 84d2 test dl,dl

On se retouve juste apres le call de GetDlgItemTextA, si on examines ses parametres pushé (les 4 derniers avant le call, puisque cet api utilise 4 arguments selon le prototype) on peux voir notre nom en examinant le 2eme argument pushé (rappel : inverse par rapport au prototype) :

d 40300d
       
0:000> d 40300d
0040300d 4e 65 74 69 78 00 00 00-00 00 00 00 00 00 00 00 Netix...........
0040301d 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040302d 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040303d 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040304d 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040305d 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040306d 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0040307d 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

On continue en tracant, des que l''on rencontre un call d'une api, en tracant avec F10 on entre dans la dll ou elle est declaré, on en ressort avec un Step out.

Voila en gros comment controler sa cible, ce qui parrait deroutant au debut est de ne pas voir le nom des fonctions directement dans le code desassemblé de notre module, mais apres on s'y habitue et cela ne gene pas vraiment, l'important etant d'examiner les parametres pushé avant celle-ci, apres l'avoir tracé. Peut etre aussi existe t-il une manip qui m'a echapé et qui permetrai d'y remedier, j'attend avec impatiente vos solutions.

De toute facon, un debugger sert à verifier ou modifier des valeurs et examiner des situations et la progression d'un code, le travail s'effectuant en alternance entre un debugger et un desassembleur. On etudie le prog par le desassembleur et on teste avec le debugger.

Un moyen que j'ai trouvé pour y remedier est par l'export de IDA vers WindDbg, voyons comment faire.

Export de IDA vers WinDbg

Pour cela il faut une petite manip, avec un petit prgramme creer par Borland qui s'appelle Map2Dbg que vous trouverez ICI
On produit un fichier MAP à partir d'IDA, portant le meme nom que l'exe ( avec l'extension MAP pas EXE :p )

On utilise ensuite Map2Dbg, pour s'en servir rien de plus simple : on place Map2Dbg dans le meme rep qui contient l'EXE analysé ainsi que son fichier .MAP, tout 2 porte le meme nom, On fait glisser l'EXE sur Map2Dbg et un nouveau fichier va etre creé portant le nom de l'EXE avec l'extension .DBG. C'est ce fichier qui va nous servir pour WinDbg, mais avant tout une chose tres importante, il faut le renommer en image00400000.dbg en effet image00400000 est le nom de notre module sous WinDbg et le debugger va donc chercher le fichier .dbg correspondant a ce nom de module.

Ensuite on va specifier le chemin du repertoire ou se trouve ce fichiers qui contient des Symbols, on peux via le menu File | Symbol File Path, specifier le repertoire ou se trouve le fichier image00400000.dbg et ensuite ouvrir l'EXE. La commande .sympath [chemin vers le repertoire ou se trouve le fichier] permet de modifier ce chemin.

Voyons voir le rendu :

00400ff6 0000             add     [eax],al
00400ff8 0000 add [eax],al
00400ffa 0000 add [eax],al
00400ffc 0000 add [eax],al
00400ffe 0000 add [eax],al
image00400000!start:
00401000 6a00 push 0x0
00401002 e8c9010000 call image00400000!GetModuleHandleA (004011d0)
00401007 a300304000 mov [image00400000!hInstance (00403000)],eax
0040100c 6a00 push 0x0
0040100e 682b104000 push 0x40102b
00401013 6a00 push 0x0
00401015 6804304000 push 0x403004
0040101a ff3500304000 push dword ptr [image00400000!hInstance (00403000)]
00401020 e875010000 call image00400000!DialogBoxParamA (0040119a)
00401025 50 push eax
00401026 e89f010000 call image00400000!ExitProcess (004011ca)
image00400000!DialogProc:
0040102b 55 push ebp
0040102c 8bec mov ebp,esp
0040102e 837d0c10 cmp dword ptr [ebp+0xc],0x10
00401032 750c jnz image00400000!DialogProc+0x15 (00401040)
00401034 6a00 push 0x0
00401036 ff7508 push dword ptr [ebp+0x8]
00401039 e862010000 call image00400000!EndDialog (004011a0)
0040103e eb62 jmp image00400000!loc_401099+0x9 (004010a2)

On peut voir à present les labels ( start, DialogProc ), les fonctions appelés, les variables ( mov [image00400000!hInstance (00403000)],eax ).

On peux poser des BP sur ces labels et Fonctions : BP start , BP DialogProc ainsi qu'examiner la valeur des variables en les designant par leur nom, bref debugger en utilisant les symbols contenu dans ce fichier .DBG.

Conclusion

J'espere que vous avez apprecié ce debugger, et que vous vous en servirez et ferez evoluer des methodes de cracking par l'intermediaire de tutoriaux voir pourquoi pas si vous en etes capables de programmer des plug-ins ou scripts qui permettraient d'ajouter des fonctions à ce petit debugger.
De plus c'est un tres bon outils pour debugger vos propres programmes avec les informations symboliques et en mode source ce dont je n'ai pas parlé, mais je trouve que j'en ai deja pas mal dit dans ce tut donc je m'arrete là en vous souhaitant bon courage dans le cracking.