Avant Propos :
Bon je me suis décidé à regardé le défi de la main rouge, qui consiste à faire passer en shareware le prog xnview qui est freeware. Tout d’abord il ne faut pas vous attendre ici à des merveilles de reverse engineering et autres truc... je ne suis qu’un newbie . Pour cela faudra aller voir les autres contributions.
Enfin, pour ma part j’ai décidé de rendre se programme en version de démonstration et de brider quelques fonctions.
Le premier objectif que je me suis fixé c’est de mettre un nagscreen au démarage du prog. Je me suis contenté d’une simple messagebox, car les dialogbox ou les fenêtres sont plus longues à faire (on utilise Masm ou autre, et je suis pas au top sur la création de fenêtre).
Pour ce faire il faut de la place dans le prog. A la fin il y en a, mais j’ai préféré rajouter une section au prog. Pour cela on prend procdump, on va sur Pe-editor, on ouvre xnview, on clique sur sections, on se place sur la dernière, et on fait add section (ajouter une section). La mienne à les caractéristiques suivantes :
Name .LuTiN
VirtualSize 00001000
VirtualOffset 00110000
RawSize 00001000
RawOffset 00109800
Characteristics E0000020 code exécutable, readable, writable
Maintenant que la section est crée il faut changer la taille de l’image base toujours sous procdump de 110000 par 111000 (j’ai rajouté 1000 bytes ce qui est amplement suffisant, même de trop).
Maintenant que notre section est crée il faut lui donné
c’est 1000 bytes. Pour cela on prend Hex Workshop, on va à la fin
du fichier, on fait insérer, on met 1000 bytes en hexa et ok. Maintenant
que l’on a notre espace de travail on peut s’attaquer à la MessageBox.
Pour cela j’ai decidé quelle apparaitra avant la création
du prog. Il faut donc rechercher où le prog est créer. On
va sous softice et on met un point d’arrêt sur la création
d’une fenêtre :
BPX CreateWindowExA. On lance le soft, et là softice se déclenche.
On appuie sur F12 pour remonter dans le prog et chercher quelle fonction
affiche le prog (et le créé). En remontant les fonctions
et en regardant dans W32dasm j’arrive là :
:00478954 6A0A
push 0000000A
:00478956 8B1574924D00
mov edx, dword ptr [004D9274]
:0047895C 52
push edx
:0047895D 6A00
push 00000000
:0047895F 6A00
push 00000000
* Reference To: KERNEL32.GetModuleHandleA,
Ord:002Fh
|
:00478961 2EFF15D0F84B00
Call dword ptr cs:[004BF8D0]
:00478968 50 push eax
:00478969 E82AA8FAFF
call 00423198 <-- affiche le prog
:0047896E E850F8FBFF
call 004381C3
:00478973 89EC
mov esp, ebp
:00478975 5D
pop ebp
:00478976 5A
pop edx
:00478977 59
pop ecx
:00478978 5B
pop ebx
:00478979 C3
ret
Donc en 478969 on trouve la fonction qui affiche le prog : c’est donc
là que l’on va détourner notre prog vers le début
de notre section qui se trouve à l’adresse 00510780 (c’est Hiew
qui l’dit J ).
Mais avant de faire cela il faut savoir ce que l’on va ecrire dans
cette section. Donc en gros voilà comment se présente l’appel
d’une MessageBox (voir tut de Morgate pour de plus ample informations)
:
PUSH 00
ß forme de la MessageBox
PUSH XXXXXXX ß
adresse du titre
PUSH XXXXXXX ß
adresse du texte
PUSH 00
ß n° de la fenêtre
CALL USER32 !MessageBoxA
ß appel de la message box (c’est pas
exactement comme cela, mais c’est comme ça qu’on va le mettre sous
softice)
Donc il y a besoin d’une place pour le titre, et d’une pour le texte. J’ai décidé de mettre le texte, et le titre au début de la section, ce qui donne :
On trouve que le début du titre est à l’adresse 510780
et le début du texte à l’adresse 51078B.
On va mettre l’appel du nag un peu après en 5107FB (par exemple).
Donc on modifie d’abor le call. On lance le prog avec symbol loader,
on met un point d’arrêt en 478969, on appuie sur F5 et la on tape
a 478969 pour remplacer le call par notre saut :
:00478961 2EFF15D0F84B00
Call dword ptr cs:[004BF8D0]
:00478968 50
push eax
:00478969 E98D7E0900
jmp 005107FB ßsaut
vers nag
:0047896E E850F8FBFF
call 004381C3
:00478973 89EC
mov esp, ebp
:00478975 5D
pop ebp
:00478976 5A
pop edx
:00478977 59
pop ecx
:00478978 5B
pop ebx
:00478979 C3
ret
On appuie sur f10 pour aller à l’endroit où l’on va mettre le nag. On rappuit sur F10 car la zone est invalide sous softice, il break et l’adresse redevient valide. On peut mettre notre nag avec a 5107FB :
5107FB 60
pushad
ß sauvegarde les registres
5107FC 6A00
push 00
ß
forme nag
5107FE 6880075100 push
00510780
ß titre nag
5107F3 688B075100 push
0051078B
ß texte nag
5107F8 6A00
push 00
ß n° MessageBox
5107FA E81F39A4BF call USER32!MessageBoxA
ß appel nag
51080F 61
popad
ß restaure les registres
510810 E88329F1FF call
00423198
ß création du prog
510815 E95481F6FF jmp
0047896E
ß on retourne dans le prog
51081A 0000
add [eax], al
ß suite de notre section
Maintenant on va désactiver les fonctions de sauvegarde. Pour cela on désassemble le prog avec W32dasm, on va dans import fonction et on trouve GetSaveFileName qui sert à sauver les fichiers. On on trouve plusieurs dans le prog. Pour savoir si elle corresponde ou pas au fonction save ou save as j’ai mis un point d’arrêt vers l’endroit où elle sont appelées et j’ai testé save et save as. Voici la fonction save as :
:00418EC9 B906080000
mov ecx, 00000806
:00418ECE 89842430170000
mov dword ptr [esp+00001730], eax
:00418ED5 B8DC8C4100
mov eax, 00418CDC
:00418EDA 8B1D7C934E00
mov ebx, dword ptr [004E937C]
:00418EE0 89842444170000
mov dword ptr [esp+00001744], eax
:00418EE7 A178934E00
mov eax, dword ptr [004E9378]
:00418EEC 89942448170000
mov dword ptr [esp+00001748], edx
:00418EF3 89842408170000
mov dword ptr [esp+00001708], eax
:00418EFA 8D842400100000
lea eax, dword ptr [esp+00001000]
:00418F01 898C2434170000
mov dword ptr [esp+00001734], ecx
:00418F08 89842440170000
mov dword ptr [esp+00001740], eax
:00418F0F 85DB
test ebx, ebx
:00418F11 740B
je 00418F1E ßon
va dériver le prog ici
:00418F13 C784243417000066080800
mov dword ptr [esp+00001734], 00080866
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:00418F11(C)
|
:00418F1E 8D842400170000
lea eax, dword ptr [esp+00001700]
:00418F25 50
push eax
* Reference To: comdlg32.GetSaveFileNameA,
Ord:0002h
|
:00418F26 E8295D0A00
Call 004BEC54 ßboite
de dialog save
:00418F2B 85C0
test eax, eax
:00418F2D 745E
je 00418F8D ßsaut
important
:00418F2F 8B842418170000
mov eax, dword ptr [esp+00001718]
:00418F36 A3ACE74C00
mov dword ptr [004CE7AC], eax
:00418F3B 668B8484FC0F0000
mov ax, word ptr [esp+4*eax+00000FFC]
:00418F43 8D942400140000
lea edx, dword ptr [esp+00001400]
:00418F4A 668906
mov word ptr [esi], ax
:00418F4D 89F8
mov eax, edi
:00418F4F E8C5F80000
call 00428819
:00418F54 31C0
xor eax, eax
:00418F56 668B842438170000
mov ax, word ptr [esp+00001738]
:00418F5E 31D2
xor edx, edx
:00418F60 C6040700
mov byte ptr [edi+eax], 00
:00418F64 668B942438170000
mov dx, word ptr [esp+00001738]
:00418F6C 8D842400140000
lea eax, dword ptr [esp+00001400]
:00418F73 01C2
add edx, eax
:00418F75 89E8
mov eax, ebp
:00418F77 E89DF80000
call 00428819
:00418F7C B883944E00
mov eax, 004E9483
:00418F81 89FA
mov edx, edi
:00418F83 E891F80000
call 00428819
* Possible Ref to Menu: BROWSERMENU,
Item: "Ouvrir..."
|
:00418F88 B801000000
mov eax, 00000001
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:00418F2D(C)
|
:00418F8D 81C454170000
add esp, 00001754 ßsaut
arrive là
:00418F93 5D
pop ebp
:00418F94 5F
pop edi
:00418F95 5E
pop esi
:00418F96 C3
ret ßretour
de la fonction
En 418F26 la boite de sauvegarde est appelé. Pour voir comment éviter cela j’ai d’abord mis ret à la place du suat avant la fonction en 418F11 mais le programme plantait. Ensuite j’ai remarqué le saut en 418F2D qui nous ammenait vers la fin de la fonction. Je l’ai donc forcé, après que la boite de dialogue soit apparu et la le prog plantait plus.
Donc j’ai d’abord détourné le saut en 418F11 vers une
partie de la section .LuTiN où j’ai mis un autre nag, puis il revenait
en 418F8D où le programme continuait sa route.
Voilà comment forcer le saut :
:00418F0F 85DB
test ebx, ebx
:00418F11 E904790F00
jmp 0051081A
:00418F13 90
nop ßon
rééquilibre le code
:00418F13 90
nop
:00418F13 90
nop
:00418F13 90
nop
:00418F13 90
nop
:00418F13 90
nop
:00418F13 90
nop
:00418F13 90
nop
:00418F1E 8D842400170000 lea
eax, dword ptr [esp+00001700]
:00418F25 50
push eax
L’adresse 51081A de la section .LuTiN est juste après le nag précédent . Donc maintenant , on peut aller à cette adresse et y faire notre nag. Ici comme mon but n’est pas de détruire la fonction de sauvegarde, mais de la bloquer (en gros quelques changement la réactive) j’ai volontairement réécrit la partie que l’on a détruit par le saut :
51081A 60
pushad
ß sauvegarde les registres
51081B 6A00
push 00
ß forme de la MessageBox
51081D 6880075100
push 00510780
ß Titre
510822 688B075100
push 0051078B
ß Texte
510827 6A00
push 00
ß N°
510829 E80039A4BF
call USER32!MessageBoxA
ß MessageBox
51082E 61
popad
ß on restaure les registres
51082F E95987F0FF
jmp 00418F8D
ß on retourne à la fin de la
fonction
510834 0F84E486F0FF
jz 00418F1E
ß ce que l’on a détruit par
le saut
51083A C784243417000066080800 mov dword ptr
[esp+00001734], 00080866
510845 E9D486F0FF
jmp 00418F1E
ß retourne dans la fonction
Donc cette partie du code affiche la MessageBox de tout à l’heure et retourne à la fin de la fonction pour éviter l’enregistrement. Il peut être réactiver en noppant le call en 51082F car j’ai remis ce qui suivait normalement dans le prog. (le je devient jz c’est un saut long)
Si on s’arrête là, on a plus la boite de sauvegarde mais pourtant une sauvegarde s’effectue. C’est parce qu’en retour de la fonction il y a un test sur eax :
:004127D9 E8DE650000
call 00418DBC
:004127DE 85C0
test eax, eax ß
test eax
:004127E0 7445
je 00412827 ßsaute
si = 0 et pas sauvegarde
:004127E2 8D942400030000
lea edx, dword ptr [esp+00000300]
:004127E9 89E0
mov eax, esp
:004127EB E829600100
call 00428819
:004127F0 8D942400020000
lea edx, dword ptr [esp+00000200]
:004127F7 89E0
mov eax, esp
:004127F9 E89D630100
call 00428B9B
Donc pour que l’enregistrement ne s’effectue pas, il faut que eax soit égale à 0. Donc on modifie légérement notre appel de nag :
51081A 60
pushad
ß sauvegarde les registres
51081B 6A00
push 00
ß forme de la MessageBox
51081D 6880075100
push 00510780 ß
Titre
510822 688B075100
push 0051078B ß
Texte
510827 6A00
push 00
ß N°
510829 E80039A4BF
call USER32!MessageBoxA
ß MessageBox
51082E 61
popad
ß on restaure les registres
51082F B800000000
mov eax, 00000000
510834 E95487F0FF
jmp 00418F8D
ß on retourne à la fin de la
fonction
510839 0F84DF86F0FF
jz 00418F1E
ß ce que l’on a détruit par
le saut
51083F C784243417000066080800 mov dword ptr
[esp+00001734], 00080866
510849 E9CF86F0FF
jmp 00418F1E
ß retourne dans la fonction
Et là le nag s’affiche et l’enregistrement ne s’effectue pas J . Attention aux valeurs hexa qui ont changées. On peut maintenant effectuer les modif avec un éditeur hexa.
Bon maintenant on peut s’attaquer à la fonction sauver. Pour
cela j’ai ouvert un fichier, j’ai fait sauver, et là une boite de
dialogue nous dit que le fichier existe déjà et nous demande
si on veut l’écraser. Là j’ai fait surgir softice, j’ai taper
task pour obtenir les noms des progs en mémoire. Le notre c’est
xnviewfr. On fait hwnd xnviewfr pour voir tous les évènements
du prog. J’obtiens ça (attention surement différent chez
vous) :
|
|
|
|
|
|
|
| 0494 (1) | 31FF | 32 | XNVIEWER | #32770 (Dialog) | 17AF :000050B1 |
| 049C (2) | 31FF | 32 | XNVIEWER | Button | 17AF :00001040 |
| 04A0 (2) | 31FF | 32 | XNVIEWER | Button | 17AF :00001040 |
| 04A4 (2) | 31FF | 32 | XNVIEWER | Static | 17AF :00005C20 |
Il y en a encore d’autre mais celle là suffise.
Bon je veux mettre un Breakpoint sur l’activité de la souris donc il Faut prendre une ClassName avec bouton, or la première c’est la boite de dialog et après il y a deux bouton (ceux de la boite). Bon on met le point d’arrêt sur un des deux et si ça marche pas on prend l’autre. Donc on met le point d’arrêt : BMSG 49C 0202 . 49C c’est le window handle du bouton et 0202 c’est l’api WM_LbuttonUp.
On appuie sur F5 et softice se déclenche, on remonte avec F12,
on regarde où on est (on peut s’aider du désassembleur) et
on arrive là :
* Reference To: USER32.GetWindowLongA,
Ord:0037h
|
:004126C1 2EFF152CF74B00
Call dword ptr cs:[004BF72C]
:004126C8 89C6
mov esi, eax
:004126CA 8B8002020000
mov eax, dword ptr [eax+00000202]
:004126D0 C1F810
sar eax, 10
:004126D3 83F8FF
cmp eax, FFFFFFFF
:004126D6 7521
jne 004126F9 ßsaute
vers nag fichier existe
:004126D8 89D9
mov ecx, ebx
:004126DA 31C0
xor eax, eax
:004126DC 31D2
xor edx, edx
:004126DE 668B842404040000
mov ax, word ptr [esp+00000404]
:004126E6 668B942400040000
mov dx, word ptr [esp+00000400]
:004126EE 89C3
mov ebx, eax
:004126F0 89F8
mov eax, edi
:004126F2 E885000000
call 0041277C
:004126F7 EB75
jmp 0041276E
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:004126D6(C)
|
:004126F9 6800010000
push 00000100 ßnag
fichier existe
:004126FE 8D442404
lea eax, dword ptr [esp+04]
:00412702 50
push eax
* Possible Reference to String
Resource ID=04017: "Ce fichier existe !Voulez-vous l'écrasez ?"
|
:00412703 68B10F0000
push 00000FB1
:00412708 8B1578934E00
mov edx, dword ptr [004E9378]
:0041270E 52
push edx
* Reference To: USER32.LoadStringA,
Ord:004Bh
|
:0041270F 2EFF157CF74B00
Call dword ptr cs:[004BF77C]
:00412716 6A21
push 00000021
* Possible StringData Ref from
Data Obj ->"Save As"
|
:00412718 68181A4C00
push 004C1A18
:0041271D 8D442408
lea eax, dword ptr [esp+08]
:00412721 50
push eax
:00412722 57
push edi
Donc en 4126D6 il saute vers le nag le fichier existe voulez vous l’écraser. J’ai dans un premier temps penser à détourner ce saut comme tout à l’heure vers une partie de la section .LuTiN et faire afficher le nag. Mais en y regardant de plus près, c’est inutile. Et oui si le saut ne s’effectue pas on arrive en 4126F2 à un appel de fonction, or cet fonction c’est le save as. Donc si le saut ne s’effectue pas en 4126D6 le prog va vers enregistrez sous or on a désactivé cette fonction et notre nag apparait J . Il suffit donc de virer ce saut avec un éditeur hexa.
Bon maintenant on va rajouter dans le menu about, un item register. Pour cela on prend Borland Resource Workshop et on édite les menus et on rajoute l’item register dans about . Je lui ai donné l’id 194. Bon en fait on aurait du faire cela au début parce que quand on fait cela il détruit ce que l’on a mis dans notre section .LuTiN. Il y a plus qu’à tout recommencer.
Une fois qu’on à tout refait, on lance le prog et on vérifie
que l’item est dans le menu about. Maintenant on va afficher une MessageBox
quand on cliquera sur register. Pour ce faire il faut trouver l’endroit
où le prog traite le fait qu’on est appuyé sur register.
Pour ce faire j’ai recherché 00000111 dans W32dasm (Pour comprendre
à quoi correspond ce 00000111 il faut lire le tut de christal et
de +Spath sur les menus). J’ai d’abord mis des points d’arrêts sur
chaque comparaison avec 00000111 et j’ai cliqué sur register mais
aucun n’a marché. J’en est mis ensuite sur les autres références
à 00000111 (11 en tout) et un seul à marché en cliquant
sur register, celui en 40DE71. On obtient cela :
:0040DE6E 40
inc eax
:0040DE6F EBCB
jmp 0040DE3C
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:0040DE3E(C)
|
:0040DE71 8B0C24
mov ecx, dword ptr [esp]
:0040DE74 BB11010000
mov ebx, 00000111 ßon
arrive là
:0040DE79 55
push ebp
:0040DE7A 8B4605
mov eax, dword ptr [esi+05]
:0040DE7D 89FA
mov edx, edi
:0040DE7F C1F818
sar eax, 18
:0040DE82 E8DDFEFFFF
call 0040DD64
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:0040DE6C(U)
|
:0040DE87 83C408
add esp, 00000008
:0040DE8A 5D
pop ebp
:0040DE8B 5F
pop edi
:0040DE8C 5E
pop esi
:0040DE8D C20400
ret 0004
Donc on va détourner le prog en 40DE74 vers la section .LuTiN, à la suite de ce que l’on a écrit. Mais là il faut encore vérifier si c’est bien avec register, et oui A propos fait aussi breaker softice. Donc pour cela il faut vérifier que l’id de register est bien dans ecx. L’id est 194 ce qui correspond à C2h. Voilà on peut détourner le prog :
:0040DE71 8B0C24
mov ecx, dword ptr [esp]
:0040DE74 E9D6291000
jmp 0051084F ßon
détourne le prog
:0040DE79 55
push ebp
:0040DE7A 8B4605
mov eax, dword ptr [esi+05]
:0040DE7D 89FA
mov edx, edi
Et en 51084F (suite des autres nag que l’on a fait dans .LuTiN) on met l’appel du nag :
51084F BB11010000 mov
ebx, 00000111 ß on restaure ce qu’on
a détruit
510854 81F9C2000000 cmp ecx, 000000C2 ß
register ?
51085A 7515
jnz 00510871 ß Non, on saute
51085C 60
pushad
51085D 6A00
push 00 ß oui on appel le nag
51085F 6880075100
push 00510780
510864 688B075100
push 0051078B
510869 6A00
push 00
51086B E8BE38A4BF call USER32 !MessageBoxA
510870 61
popad
510871 E903D6EFFF jmp 0040DE79
ß
et on retourne dans prog
Voilà . J’ai fait le saut à la fin en 0040DE79 pour éviter d’avoir des erreurs dans le prog. Bon là on a le nag, mais c’est pas les bon messages. On peut les mettre juste après :
Donc le titre de la MessageBox est en 510876 et le texte en 510882.
On fait les modif :
51084F BB11010000 mov
ebx, 00000111 ß on restaure ce qu’on
a détruit
510854 81F9C2000000 cmp ecx, 000000C2 ß
register ?
51085A 7515
jnz 00510871 ß Non, on saute
51085C 60
pushad
51085D 6A00
push 00 ß oui on appel le nag
51085F 6876085100 push
00510876
510864 6882085100 push
00510882
510869 6A00
push 00
51086B E8BE38A4BF call USER32 !MessageBoxA
510870 61
popad
510871 E903D6EFFF jmp 0040DE79
ß
et on retourne dans prog
On fait les modifs avec un éditeur hexa. On lance le prog, on teste notre item register : ça marche impec. J .
Voilà. Maintenant je m’attaque à la dernière protection que je veux mettre : un anti-softice. Bon là je met juste un meltice, même pas un pour NT. Pour ce faire on met \\.\SICE à la suite de notre section :
Bon là pour appeler la routine on va redétourner le prog en 00478969 où l’on arrivait vers le nag de départ, mais ici on va tomber sur l’anti-si en 51089A :
:00478961 2EFF15D0F84B00
Call dword ptr cs:[004BF8D0]
:00478968 50
push eax
:00478969 E92C7F0900
jmp 0051089A ßsaut
vers anti SI
:0047896E E850F8FBFF
call 004381C3
:00478973 89EC
mov esp, ebp
:00478975 5D
pop ebp
:00478976 5A
pop edx
:00478977 59
pop ecx
:00478978 5B
pop ebx
:00478979 C3
ret
Bon maintenant on peut écrire la routine de détection :
51089A 90
nop
ß
sinon le prog aime pas
51089B 50
push eax
ß on sauve les registres
51089C 52
push edx
51089D 51
push ecx
51089E 53
push ebx
51089F B891085100
mov eax, 00510891
ß \\.\SICE
5108A4 50
push eax
5108A5 E83572A6BF
call KERNEL !32CreateFileA
ß debuger ?
5108AA 3DFFFFFFFF cmp
eax, FFFFFFFF
ß eax et –1 égal ?
5108AF 7418
jz 005108C9
ß saute si pas softice
5108B1 6A00
push 00
ß sinon message softice trouvé
5108B3 68EB085100
push 005108EB
5108B8 68D8085100
push 005108D8
5108BD 6A00
push 00
5108BF E86A38A4BF
call USER32 !MessageBoxA
ß
message
5108C4 E801CCA7BF
call KERNEL32 !ExitProcess
ß et on quite le prog
5108C9 BC10FD6500
mov esp, 0065FD10 ß
sinon on ce replace
5108CE 5B
pop ebx
ß au bon endroit sur
5108CF 5C
pop ecx ß
la pile et on restaure
5108D0 5A
pop edx ß
les registres
5108D1 58
pop eax
5108D2 E924FFFFFF
jmp 005107FB
ß et on va vers nag début
Pour mieux comprendre le pourquoi du comment de cette routine il faut lire la doc fournit avec frogice (merci au meilleur cracker français J ). Voilà en gros on test la présence de softice, s’il y est on le dit et on quitte le prog, sinon on continue le prog.
On fait les modifs avec un éditeur hexa, on lance le prog et pof softice est détecté et on quitte le prog. On relance mais avec FPloader en mémoire , on contourne la protection et le prog marche impec. J .
Voilà j’ai fini avec la protection du prog. A si j’ai aussi rajouté
une petite compression (Aspack), histoire de dire.
Voilà c’est fini pour mon travail sur le défi proposé par la main rouge. Ce défi m’aura permis de découvrir pas mal de truc. J’espère que j’ai été assez clair dans la rédaction, sinon un petit mail J (city_of_bitch@caramail.com).
Amicalement,
LuTiN NoIR
PS : Merci tout particulièrement à Christal (tut sur menu), Morgate (tut sur messagebox) et TeeJi (cours sur reverse engineering).