Manual Unpacking

Packer : FSG 1.31

Objectifs :

Cible :

Outils nécessaires :

Fichiers joints :

Index

  1. Introduction
  2. Collecte des infos sur la cible
  3. Dump du programme
  4. Recherche de l'original entry-point (OEP)
  5. Etude du dump sous un éditeur hexa
  6. Reconstruction de la table des imports
  7. Infos pratiques sur l'architecture d'un programme packé par FSG 1.31

1. Introduction

FSG 1.31 est l'un, voir le meilleur packer, pour les petits programmes, il est parfait pour faire des exe de - 4ko comme pour cette démo par exemple. A ce jour je crois qu'il n'existe pas d'unpackeur générique pour cette version de FSG et l'unpacker manuellement reste relativement simple. Voici donc la méthode que j'ai utilisée.

2. Collecte des infos sur la cible

On ouvre la cible avec Lord-PE et on récupère les infos suivantes :

Entry-point : 004CD8
Import-Table : RVA = 00004DC7, size = 00000034


Sections Table :

names		Voffset		Vsize		Roffset		Rsize		Flags
		00001000	00003000	00000000	00000000	C00000E0
		00004000	00001000	00000200	00000DFB	C00000E0

On voit ici qu'il n'y a que 2 sections et que celles-ci n'ont pas de nom, ce qui veux dire que les sections originales du programme (normalement .code .data .idata et .rscr) ont sûrement du être regroupées en ces 2 seules sections au moment de la compilation du programme ou plus précisement du link ou alors lors de la compression par FSG qui est l'une de ces caractéristique mais nous reviendrons la dessus en fin de ce tutorial.

Note : Dans le cas de section merged nous avons le code, les data et les imports sûrement mélangés dans la même section. Si nous voulons obtenir un listing désassemblé sous wdasm avec le code, les strings datas et les imports il nous faut donc ajuster le flag des sections et mettre les options, executable, readable, writeable et contain executable code, contain initialised data ce qui reviens à placer en flag la valeur E00000E0.

3. Dump du programme

Toujours avec Lord-PE on va dumper la cible, assurez-vous que ces options soit cochés avant de dumper :

Cela à pour effet de faire correspondre la Rsize et le Roffset des sections avec leur Voffset et Vsize, en gros d'avoir sur le disque la même image qu'occupe le programme en mémoire et de faire correspondre les adresses et tailles des sections dans le PE header.

Ensuite on ajuste les flags des 2 sections sur notre dump et on met la valeur E00000E0 comme expliqué plus haut. Avec ça on pourra déjà obtenir sous wdasm le code désassemblé et les strings datas référence. Il nous reste à trouver l'OEP et reconstruire les imports pour rendre ce dump fonctionnel.

4. Recherche de l'original entry-point (OEP)

On va se servir d'un debugger, dans mon cas WinDbg que je vous conseille pour ce genre de job, pour tracer le code du loader, et repérer le moment ou l'on quitte le segment du loader pour sauter vers le déroulement normal du programme.

On lance l'exe original avec notre debugger et on s'arrange pour breaker à l'entry-point. (Pour windbg, il suffit de lancer l'exe et de poser un bp sur 404CD8 (image base + offset entry-point)) (Pour softice lancer l'exe par le symbol loader qui devrait breaker tout seul sur l'entry-point)

Nous sommes dans le loader qui va servir à décompresser l'exe en mémoire. Il suffit de tracer instruction par instruction et déterminer l'adresse où l'on quitte ce loader. Je le reconnais c'est assez long et chiant à faire mais c'est le seul moyen quand on ne connaît pas suffisamment bien le packer pour élaborer des stratégies pour identifier l'OEP plus simplement.

On peut aussi commencer à partir d'un bpx sur l'api LoadLibraryA puisque notre loader va se servir de cette fonction, ce qui nous évitera de tracer depuis le tout début. Voici ma méthode avec WinDbg, je crois que y'a pas plus simple et plus rapide :) :

Voila ça met environ 20 secondes Il ne nous reste plus qu'à remonter le log pour trouver le moment où l'on saute du loader vers le programme :

(on lit du bas vers le haut)

00404da2 fe0f             dec     byte ptr [edi]          ds:0023:004021bc=03
image00400000+4da4:
00404da4 74ef jz image00400000+0x4d95 (00404d95) [br=0]
image00400000+4da6:
00404da6 fe0f dec byte ptr [edi] ds:0023:004021bc=02
image00400000+4da8:
00404da8 7506 jnz image00400000+0x4db0 (00404db0) [br=1]
image00400000+4db0:
00404db0 fe0f dec byte ptr [edi] ds:0023:004021bc=01
image00400000+4db2:
00404db2 0f8427d0ffff je image00400000+0x1ddf (00401ddf) [br=1]
image00400000+1ddf:
00401ddf 56 push esi
image00400000+1de0:
00401de0 33f6 xor esi,esi
image00400000+1de2:
00401de2 56 push esi
image00400000+1de3:
00401de3 ff1540104000 call dword ptr [image00400000+0x1040 (00401040)]{kernel32!GetModuleHandleA (77e5ad86)} ds:0023:00401040=77e5ad86
image00400000+1de9:
00401de9 56 push esi
image00400000+1dea:
00401dea a3781e4000 mov [image00400000+0x1e78 (00401e78)],eax ds:0023:00401e78=00000000
image00400000+1def:
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\GDI32.dll -
00401def ff1518104000 call dword ptr [image00400000+0x1018 (00401018)]{GDI32!CreateSolidBrush (77c4217c)} ds:0023:00401018=77c4217c
image00400000+1df5:
00401df5 56 push esi
image00400000+1df6:
00401df6 68811c4000 push 0x401c81
image00400000+1dfb:
00401dfb 56 push esi
image00400000+1dfc:
00401dfc 6a65 push 0x65

On se trouvait vers l'adresse 00401dfc en remontant on s'aperçoit que l'on à effectué un assez long jump en 00404db2 pour sauter en 00401ddf. C'est déjà un bon signe qui pourrait indiquer que l'on a sauté du loader vers le code du programme. Si on regarde par rapport aux section on s'aperçoit que l'on a donc sauté de la 2ème section vers la 1ere. C'est encore la un signe, car normalement le code du programme est dans la même section. Si on examine le code qui suit on s'aperçoit que l'on appelle la fonction GetModuleHandleA est caractéristique du début d'un programme.

On peux, sans craintes, certifier que notre OEP est bien à l'adresse 00401ddf et donc à l'offset 1DDF. On remplace dans le PE l'offset de l'entry-Point, par celui que nous venons de trouver et on sauvegarde.

5. Etude du dump sous un éditeur hexa

Comme nous n'avons aucun renseignement sur le contenu des sections, il va falloir explorer un peu le dump sous un éditeur hexa.

On se rend à l'offset de la 1ere section en 1000h :

00001000 31 57 c4 77 d1 36 c4 77 07 36 c4 77 98 1b c4 77  1W.w.6.w.6.w...w
00001010 6e 3c c4 77 6f 1d c4 77 7c 21 c4 77 eb 1e c4 77 n<.wo..w|!.w...w
00001020 e0 20 c4 77 5f 3a c4 77 1a 1e c4 77 71 4b c4 77 . .w_:.w...wqK.w
00001030 c4 5d c4 77 b4 3b c5 77 00 00 00 00 9b a2 e5 77 .].w.;.w.......w
00001040 86 ad e5 77 fd 98 e5 77 ea 1b e4 77 e1 60 e5 77 ...w...w...w.`.w
00001050 00 00 00 00 87 7e c0 77 50 b2 c1 77 80 52 c0 77 .....~.wP..w.R.w
00001060 74 8e c1 77 8d 52 c0 77 10 2f c1 77 a9 7d c0 77 t..w.R.w./.w.}.w
00001070 00 00 00 00 1b 2a d2 77 a2 e7 d1 77 f0 0e d2 77 .....*.w...w...w
00001080 16 48 d1 77 bc a1 d5 77 b1 7a d1 77 a3 ba d2 77 .H.w...w.z.w...w
00001090 1a 16 d3 77 2d 5a d1 77 34 e9 d3 77 78 4d d1 77 ...w-Z.w4..wxM.w
000010a0 a4 5f d1 77
00 00 00 00 00 00 00 00 00 00 00 00 ._.w............
000010b0 38 13 40 00 2c 11 40 00 68 1e 40 00 0c 11 40 00 8.@.,.@.h.@...@.
000010c0 e8 10 40 00 d0 10 40 00 cc 10 40 00 2e 2e 2e 00 ..@...@...@.....
000010d0 46 69 6e 61 6c 20 53 69 7a 65 20 3a 20 34 30 39 Final Size : 409
000010e0 36 20 62 79 74 65 73 00 43 6f 64 65 64 20 66 6f 6 bytes.Coded fo
000010f0 72 20 34 4b 42 20 6b 67 20 74 65 6d 70 6c 61 74 r 4KB kg templat
00001100 65 20 63 6f 6e 74 65 73 74 00 00 00 54 69 6e 79 e contest...Tiny
00001110 20 6b 65 79 67 65 6e 20 74 65 6d 70 6c 61 74 65 keygen template
00001120 20 62 79 20 54 68 69 67 6f 00 00 00 48 65 72 65 by Thigo...Here
00001130 20 69 73 20 74 68 65 20 66 69 6e 61 6c 20 22 65 is the final "e
00001140 66 66 65 63 74 22 2e 2e 2e 0a 53 6f 2c 20 74 68 ffect"....So, th
00001150 69 73 20 74 65 6d 70 6c 61 74 65 20 77 61 73 20 is template was
00001160 66 75 6c 6c 79 20 63 6f 64 65 64 0a 69 6e 20 43 fully coded.in C [.......]

On voit distinctement 2 parties, la 1ère partie ressemble à des pointeurs vers des adresses de fonctions en mémoire : comme 77C45731 en 1000h. Ça pourrait bien être nos tableaux pointés par les FirstThunk de la table des imports.

La 2ème partie on voit des strings datas, on se dit que c'est sûrement l'endroit où sont stocké les variables du programme (la section .data)

Apres ce qu'on considère comme les datas on trouve du code hexa, qui ressemble à la partie du code proprement dite :

00001300 6f 74 68 65 72 20 65 66 66 65 63 74 20 69 6e 20  other effect in 
00001310 74 68 65 20 73 70 61 63 65 20 6c 65 66 74 20 73 the space left s
00001320 6f 20 49 20 77 72 69 74 65 20 73 68 69 74 20 3a o I write shit :
00001330 29 0a 42 79 65 20 21 00 45 6e 74 72 79 20 66 6f ).Bye !.Entry fo
00001340 72 20 63 6f 6e 74 65 73 74 73 2e 61 6e 74 69 63 r contests.antic
00001350 72 61 63 6b 2e 64 65 0a 62 79 20 54 68 69 67 6f rack.de.by Thigo
00001360 00 00 00 00 54 61 68 6f 6d 61 00 00 25 58 00 00 ....Tahoma..%X..
00001370 45 6e 74 65 72 20 79 6f 75 72 20 6e 61 6d 65 20 Enter your name
00001380 21
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 !...............
00001390 00 00 00 00 00 00 59 40 6e 86 1b f0 f9 21 99 3f ......Y@n....!.?
000013a0 55 8b ec 80 7d 10 ff 75 11 0f b6 4d 0c b8 80 00 U...}..u...M....
000013b0 00 00 2b c1 0f b6 4d 08 eb 0e 80 7d 10 01 75 10 ..+...M....}..u.
000013c0 0f b6 45 08 0f b6 4d 0c 0f af c1 c1 f8 07 eb 03 ..E...M.........
000013d0 8a 45 08 5d c2 0c 00 55 8b ec b8 f4 43 01 00 e8 .E.]...U....C...
000013e0 4c 0a 00 00 53 56 57 ff 15 3c 10 40 00 50 ff 15 L...SVW..<.@.P..
000013f0 5c 10 40 00 33 db 59 89 5d f0 db 45 f0 51 51 dc \.@.3.Y.]..E.QQ.
00001400 0d 98 13 40 00 dd 1c 24 e8 11 0a 00 00 dc 0d 90 ...@...$........
00001410 13 40 00 59 59 e8 46 0a 00 00 8b 4d f0 ff 45 f0 .@.YY.F....M..E.
00001420 81 7d f0 00 01 00 00 88 84 0d 1c fe ff ff 7c ca .}............|.
00001430 ff 35 74 1e 40 00 ff 15 84 10 40 00 8b 35 20 10 .5t.@.....@..5 .
00001440 40 00 8b f8 57 89 7d d0 ff d6 57 89 45 cc ff d6 @...W.}...W.E...
00001450 57 89 45 f4 ff d6 6a 68 89 45 c0 ff 35 78 1e 40 W.E...jh.E..5x.@
00001460 00 ff 15 74 10 40 00 be 28 01 00 00 6a 4e 56 57 ...t.@..(...jNVW [.......]

On trouve ensuite les noms des fonctions importés et des dll :

00001fce 01 3c 10 40 00 4b 45 52 4e 45 4c 33 32 2e 64 6c  .<.@.KERNEL32.dl
00001fde 6c 00 47 65 74 54 69 63 6b 43 6f 75 6e 74 00 47 l.GetTickCount.G
00001fee 65 74 4d 6f 64 75 6c 65 48 61 6e 64 6c 65 41 00 etModuleHandleA.
00001ffe 45 78 69 74 50 72 6f 63 65 73 73 00 53 6c 65 65 ExitProcess.Slee
0000200e 70 00 6c 73 74 72 6c 65 6e 41 00 00 74 10 40 00 p.lstrlenA..t.@.
0000201e 55 53 45 52 33 32 2e 64 6c 6c 00 4c 6f 61 64 42 USER32.dll.LoadB
0000202e 69 74 6d 61 70 41 00 77 73 70 72 69 6e 74 66 41 itmapA.wsprintfA
0000203e 00 44 72 61 77 54 65 78 74 41 00 52 65 6c 65 61 .DrawTextA.Relea
0000204e 73 65 44 43 00 47 65 74 44 43 00 53 65 74 57 69 seDC.GetDC.SetWi
0000205e 6e 64 6f 77 54 65 78 74 41 00 53 65 6e 64 44 6c ndowTextA.SendDl
0000206e 67 49 74 65 6d 4d 65 73 73 61 67 65 41 00 45 6e gItemMessageA.En
0000207e 64 44 69 61 6c 6f 67 00 53 65 6e 64 4d 65 73 73 dDialog.SendMess
0000208e 61 67 65 41 00 44 69 61 6c 6f 67 42 6f 78 50 61 ageA.DialogBoxPa
0000209e 72 61 6d 41 00 53 65 74 52 65 63 74 00 46 69 6c ramA.SetRect.Fil
000020ae 6c 52 65 63 74 00 00 00 10 40 00 47 44 49 33 32 lRect....@.GDI32
000021ae 70 79 00 5f 65 6e 64 74 68 72 65 61 64 00 00 00 py._endthread... [.......]

On voit dans cette partie que l'on a importé 4 DLL.

Voila nous avons tout ce qui nous intéresse pour passer à l'étape suivante.

6. Reconstruction de la table des imports

Comme on n'a pas retrouvé la table des imports on va en reconstruire une. On sait qu'il y'a 4 DLL importés donc nous aurons 5 éléments IMAGE_IMPORT_DESCRIPTOR dans cette table (4 pour les 4 DLL + 1 vide).

Pour reconstruire cette table nous avons besoins de quelques renseignements que nous relevons dans la partie ou il y a le nom des dll et des fonctions, il nous faut simplement l'offset du début du nom des DLL, j'ai aussi compté le nombre de fonctions pour chaque DLL, ce qui n'est pas vraiment nécessaire mais on pourra ce servir de cette info plus tard.

Nom de la DLL Offset du début du Nom Nbr de fonctions Offset FirstThunk
KERNEL32.dll 1FD3 5 ?
USER32.dll 201E 12 ?
GDI32.dll 20B9 14 ?
MSVCRT.dll 217D 7 ?

Il nous manque plus que les offset des tableaux des FirstThunk pour construire une Import-Table complète.
Revenons sur le début de la 1ère section en 1000h et ce qui parait être les tableaux des FirstThunk

00001000 31 57 c4 77 d1 36 c4 77 07 36 c4 77 98 1b c4 77  1W.w.6.w.6.w...w
00001010 6e 3c c4 77 6f 1d c4 77 7c 21 c4 77 eb 1e c4 77 n<.wo..w|!.w...w
00001020 e0 20 c4 77 5f 3a c4 77 1a 1e c4 77 71 4b c4 77 . .w_:.w...wqK.w
00001030 c4 5d c4 77 b4 3b c5 77 00 00 00 00 9b a2 e5 77 .].w.;.w.......w
00001040 86 ad e5 77 fd 98 e5 77 ea 1b e4 77 e1 60 e5 77 ...w...w...w.`.w
00001050 00 00 00 00 87 7e c0 77 50 b2 c1 77 80 52 c0 77 .....~.wP..w.R.w
00001060 74 8e c1 77 8d 52 c0 77 10 2f c1 77 a9 7d c0 77 t..w.R.w./.w.}.w
00001070 00 00 00 00 1b 2a d2 77 a2 e7 d1 77 f0 0e d2 77 .....*.w...w...w
00001080 16 48 d1 77 bc a1 d5 77 b1 7a d1 77 a3 ba d2 77 .H.w...w.z.w...w
00001090 1a 16 d3 77 2d 5a d1 77 34 e9 d3 77 78 4d d1 77 ...w-Z.w4..wxM.w
000010a0 a4 5f d1 77
00 00 00 00 00 00 00 00 00 00 00 00 ._.w............

Passons en mode DWORD pour une vision plus claire. Et on peut encore diviser en plusieurs parties délimitées par les dword 0000000.

00000FF8 00000000 00000000 3157C477 D136C477 0736C477 981BC477 6E3CC477 ........1W.w.6.w.6.w...wn<.w
00001014 6F1DC477 7C21C477 EB1EC477 E020C477 5F3AC477 1A1EC477 714BC477 o..w|!.w...w. .w_:.w...wqK.w
00001030 C45DC477 B43BC577
00000000 9BA2E577 86ADE577 FD98E577 EA1BE477 .].w.;.w.......w...w...w...w
0000104C E160E577
00000000 877EC077 50B2C177 8052C077 748EC177 8D52C077 .`.w.....~.wP..w.R.wt..w.R.w
00001068 102FC177 A97DC077
00000000 1B2AD277 A2E7D177 F00ED277 1648D177 ./.w.}.w.....*.w...w...w.H.w
00001084 BCA1D577 B17AD177 A3BAD277 1A16D377 2D5AD177 34E9D377 784DD177 ...w.z.w...w...w-Z.w4..wxM.w
000010A0 A45FD177
00000000 00000000 00000000 ._.w............

On peut voir 4 tableaux pour nos 4 DLL importés. Et les adresses que nous voyons sont bien des adresses vers des fonctions API en mémoire. Attention de bien inverser les bytes pour lire correctement la valeur de l'adresse en mémoire, exemple sur le premier :

3157C477 se lit => 77C45731

Le problème est de savoir à quelle DLL correspond chaque tableau. Pour ça on peut soit compter le nombre d'élément et comparer avec le nombres de fonctions pour faire la correspondance ou alors se servir de l'API GetProcAdress pour retrouver l'adresse d'une fonction part son nom, et retrouver cette adresse dans les tableaux, le tableau dans lequel elle se trouve correspondra à la DLL de notre fonction.

La avec le nombre des fonctions de chaque dll et le nombre d'élément des tableaux ça suffit pour s'y retrouver.

Il suffit alors de relever l'offset du début de chaque tableau, et nous pouvons donc compléter nos infos manquantes :

Nom de la DLL Offset du début du Nom Nbr de fonctions Offset FirstThunk
KERNEL32.dll 1FD3 5 103C
USER32.dll 201E 12 1074
GDI32.dll 20B9 14 1000
MSVCRT.dll 217D 7 1054

Voila maintenant nous avons tous ce qu'il faut pour construire notre nouvelle Import-Table et on cherche un endroit libre dans notre dump pour insérer cette table. (On pourrait aussi créer une nouvelle section)

Pour l'exemple je me place à l'offset 1F10 dans le dump, juste avant les noms des fonctions.

Notre table devra ressembler à ça :

OriginalFirstThunk TimeDateStamp ForwarderChain DllName FirstThunk  
00000000 00000000 00000000 D31F0000 3C100000 (Kernel32)
00000000 00000000 00000000 1E200000 74100000 (User32)
00000000 00000000 00000000 B9200000 00100000 (Gdi32)
00000000 00000000 00000000 7D210000 54100000 (Msvcrt)
00000000 00000000 00000000 00000000 00000000 (vide)

ATTENTION DE BIEN INVERSER L'ORDRE DES BYTES

Je me place à l'offset 1F10 et je recopie cette table.

00001F10 00000000 00000000 00000000 D31F0000 3C100000 00000000 00000000 ................<...........
00001F2C 00000000 1E200000 74100000 00000000 00000000 00000000 B9200000 ..... ..t................ ..
00001F48 00100000 00000000 00000000 00000000 7D210000 54100000 00000000 ................}!..T.......
00001F64 00000000 00000000 00000000 00000000 ................

Voila c'est presque fini, on oublie pas de sauvegarder notre dump. Il nous reste maintenant à mettre à jour dans le PE l'offset de L'import-table pour que nous puissions rectifier les adresses des tableaux FirstThunk.

Maintenant on va se servir de Lord-PE qui va nous éviter bien du travail :

Voila nous avons à présent un dump fonctionnel, et quand nous le désassemblons nous obtenons bien le code, les datas et les imports.

On peut regarder ce que Lord-PE à rebuild :

avant :

00000FF8 00000000 00000000 3157C477 D136C477 0736C477 981BC477 6E3CC477 ........1W.w.6.w.6.w...wn<.w
00001014 6F1DC477 7C21C477 EB1EC477 E020C477 5F3AC477 1A1EC477 714BC477 o..w|!.w...w. .w_:.w...wqK.w
00001030 C45DC477 B43BC577
00000000 9BA2E577 86ADE577 FD98E577 EA1BE477 .].w.;.w.......w...w...w...w
0000104C E160E577
00000000 877EC077 50B2C177 8052C077 748EC177 8D52C077 .`.w.....~.wP..w.R.wt..w.R.w
00001068 102FC177 A97DC077
00000000 1B2AD277 A2E7D177 F00ED277 1648D177 ./.w.}.w.....*.w...w...w.H.w
00001084 BCA1D577 B17AD177 A3BAD277 1A16D377 2D5AD177 34E9D377 784DD177 ...w.z.w...w...w-Z.w4..wxM.w
000010A0 A45FD177
00000000 00000000 00000000 ._.w............
après : 00000FF8 00000000 00000000 C1200000 CB200000 E2200000 EB200000 F8200000 ......... ... ... ... ... ..
00001014 FF200000 0C210000 1D210000 27210000 3A210000 47210000 52210000 . ...!...!..'!..:!..G!..R!..
00001030 60210000 6A210000
00000000 DE1F0000 EB1F0000 FC1F0000 08200000 `!..j!................... ..
0000104C 0E200000
00000000 86210000 93210000 99210000 9F210000 9A210000 . .......!...!...!...!...!..
00001068 A8210000 AF210000
00000000 27200000 33200000 3D200000 47200000 .!...!......' ..3 ..= ..G ..
00001084 51200000 57200000 66200000 7A200000 84200000 91200000 A1200000 Q ..W ..f ..z ... ... ... ..
000010A0 A9200000
00000000 00000000 00000000 . ..............

Ce ne sont plus les adresses des fonctions en mémoire mais des pointeurs vers l'index suivi du nom des fonctions dans le dump.

7. Infos pratiques sur l'architecture d'un programme packé par FSG 1.31

:00404D95 47                      inc edi
:00404D96 8B37 mov esi, dword ptr [edi]
:00404D98 AF scasd
:00404D99 57 push edi
:00404D9A FF13 call dword ptr [ebx]
:00404D9C 95 xchg eax,ebp :00404D9D 33C0 xor eax, eax :00404D9F AE scasb
:00404DA0 75FD jne 00404D9F
:00404DA2 FE0F dec byte ptr [edi]
:00404DA4 74EF je 00404D95
:00404DA6 FE0F dec byte ptr [edi]
:00404DA8 7506 jne 00404DB0

On peux donc en relevant la valeur hexa de ce code en faire une belle signature qui nous permettra de reconnaître avec un éditeur hexa si le programme contient bien ce bout de code caractérisé par FSG 1.31.

478B37AF57FF139533C0AE75FDFE0F74EFFE0F7506 => Signature FSG 1.31 

:00404DAB FF37                    push dword ptr [edi]
:00404DAD AF scasd
:00404DAE EB09 jmp 00404DB9 :00404DB0 FE0F dec byte ptr [edi]
:00404DB2 0F8427D0FFFF je 00401DDF ==> saute vers l'OEP