NotePad

Défi FCF 2000

By Christal

Avant Propos :

Le
11 AVRIL 1999, le Site de La Main Rouge proposait son cinquième défi, sur l'initiative de Xose :

" Le boulot : Tout simplement modifier notepad. En effet, vous savez que les documents ouverts par défaut sont de type *.txt, ce qui est plus qu'ennuyant... En fait, ça serait *.asm, ça serait mieux pour nous, non ? Ou bien choisir *.asm, *.bat, *.* etc...Donc le défi c'est de modifier notepad pour le rendre plus convivial, pour finir le travail bâclé des programmeurs de M$.

L'idée de ce défi me vient après avoir lu l'excellent article de +Mammon à ce sujet. Il contient des éléments très intéressants, et un début de solution (ce n'est qu'un début...). Si les réponses pouvaient être claires pour les newbies (expliquer comment marche une API, etc...) ce serait cool !. Allez donc faire un tour chez notre maître +Mammon ".


A cette époque, je ne savais même pas ce que le mot Cracking aurait bien pu vouloir dire...
S'il y a des +crackers, j'étais un -Newbie.
Depuis j'ai pris du galon...
j'ai enlevé le - !

En
Avril 2000, soit 1 an plus tard, le site de FCF 2000 proposait de refaire le même défi que celui de la Main Rouge qui n'avait pas eu d'écho :

" - 2éme partie il s'agit ici d'apporter quelques améliorations au notepad :-) il s'agit de rajouter du code dans le notepad : ici la création est libre de s'exprimer : on peut ajouter des Anti-Si pour améliorer la protection on peut rajouter un nag au démarrage du notepad ou encore modifier l'apparence en rajoutant un menu ou en modifiant les menus existants .... (Bien évidemment tout les tools existant peuvent être utilisés)
je vous conseille cependant de garder un petit moment pour protéger votre petit bijoux et ses améliorations car si quelqu'un arrive a enlever vos modifications vous aurez perdu "


Au départ, mon idée était tout simplement de traduire le texte de +Mammon, mais 40 pages à traduire, même dans un anglais parfaitement compréhensible (le privilège des non anglo-saxons ?)...

Je me suis donc dis que je pourrais m'inspirer de ce texte, en limitant le plagiat au maximum, mais en gardant les grandes lignes du tutoriel de +Mammon.

Il y a une partie que je n'ai pas abordée, c'est la limitation du Bloc-Notes à des fichiers de 32ko, et pour plusieurs raisons :

- NotePad.exe n'est pas limité par une forme de protection du genre " SI > 32 Ko alors WORDPAD ", mais l'est tout simplement par la fonction EDIT qu'il utilise, contrairement à la fonction RICHEDIT utilisée par WordPad.exe
- Les explications de +Mammon sont amplement suffisantes et compréhensibles
- Le NotePad relooké de +Mammon a malgré tout de sérieux problèmes à fonctionner de façon systématique (testé sur trois PC, deux Win95 avec des versions différentes et Win98).
- Pour finir, je suis incapable d'arriver à un résultat similaire par un autre moyen, et ce n'est pas faute d'avoir essayé ! Le mieux de ce que j'ai pu obtenir et d'ouvrir un fichier quelle que soit sa taille, mais tronqué au-delà des 32 ko fatidiques.

 Au programme :

1- Modification des menus
2- Recherche de places disponibles
3- Gestion des événements
4- Modification des boites de messages
5- Détection de SoftIce
6- Rajout de fichiers à ouvrir
7- Création d'un fichier .CFG


Modifications des Menus:

A l'aide d'un éditeur de ressources, la modification de menus ne pose aucun problème. Il en existe plusieurs qui permettent ces modifications, mais ma préférences va à Borland Ressources WorkShop Version 4.5, éventuellement à ExeEscope version 5.11.

En ouvrant BRW, et en double cliquant sur MENU, vous obtenez la liste suivante:

1 MENU
{
POPUP "&Fichier"
{
MENUITEM "&Nouveau", 9
MENUITEM "&Ouvrir...", 10
MENUITEM "&Enregistrer", 1
MENUITEM "En&registrer sous...", 2
MENUITEM SEPARATOR
MENUITEM "Mise en &page...", 32
MENUITEM "&Imprimer", 14
MENUITEM SEPARATOR
MENUITEM "&Quitter", 28
}

POPUP "&Edition"
{
MENUITEM "&Annuler\tCtrl+Z", 25
MENUITEM SEPARATOR
MENUITEM "&Couper\tCtrl+X", 768, GRAYED
MENUITEM "Co&pier\tCtrl+C", 769, GRAYED
MENUITEM "C&oller\tCtrl+V", 770, GRAYED
MENUITEM "&Supprimer\tDel", 771, GRAYED
MENUITEM SEPARATOR
MENUITEM "Sélectionner &tout", 7
MENUITEM "Heure/&Date\tF5", 12
MENUITEM SEPARATOR
MENUITEM "&Retour à la ligne automatique", 27
}

POPUP "&Recherche"
{
MENUITEM "&Rechercher...", 3
MENUITEM "Rechercher le &suivant\tF3", 8
}

POPUP "&?"
{
MENUITEM "&Rubriques d'aide", 5
MENUITEM SEPARATOR
MENUITEM "&A propos de Bloc-Notes", 11
}

Il est facile de rajouter un PopUp Menu, et son Item:

POPUP "&New option"
{
MENUITEM "&Show Me", 20
MENUITEM "Detection", 21, GRAYED
}

le "&" précise que le caractère suivant sera souligné et accessible par une combinaison clavier ALT+Caractère.
La valeur qui suit (20 par exemple) va être l'identificateur (ID) de l'Item.
Dans un éditeur hexadécimal, vous retrouvez ces informations:

6300 2D00 6E00 6F00 7400 6500 7300 0000  s. .d.u. .B.l.o.
9000 2600 4E00 6500 7700 2000 4F00 7000  ..&.N.e.w. .O.p.
7400 6900 6F00 6E00 0000 0000 1400 2600  t.i.o.n.......&.
5300 6800 6F00 7700 2000 5400 6800 6500  S.h.o.w. .T.h.e.
6D00 0000 8100 1500 2600 4400 E900 7400  m.......&.D...t.
6500 6300 7400 6900 6F00 6E00 0000 0000  e.c.t.i.o.n.....

Si on regarde au niveau de l'Item &Détection, on trouve ses caractéristiques (Grayed = 81) et son Identificateur (15h = 20d).
Ses nouveaux éléments de la ressource Menu viennent se glisser à la suite des autres dans la section .rsrc, ou plus exactement s'intégrer au bloc ressources, décalant d'autant les ressources suivantes (Dialog, String Tables, Icônes...). L'éditeur se charge de "recalculer" les adresses du PE header qui permettront au programme de retrouver ses petits sans se mélanger les pinceaux.
Si la section .rsrc est altérée, le programme plantera au démarrage, aussi il est préférable de commencer par ses modifications avant d'aller plus loin.

La Recherche de place disponible

Une fois les nouvelles ressources créées, il va être possible de définir les zones potentielles où il y aura moyen d'inclure les différents Patchs.
Wdasm ou ProcDump vont pouvoir vous donner une image des différentes sections:

.text    RVA: 00001000 Offset: 00001000 Size: 00004000 Flags: 60000020
.data    RVA: 00005000 Offset: 00005000 Size: 00001000 Flags: C0000040
.idata   RVA: 00006000 Offset: 00006000 Size: 00001000 Flags: 40000040
.reloc   RVA: 00007000 Offset: 00007000 Size: 00001000 Flags: 42000040
.rsrc    RVA: 00008000 Offset: 00008000 Size: 00006000 Flags: 40000040

Vous remarquerez une première chose, les RVA (Relative Virtuel Address) et les Offsets sont identiques pour chaque section. Voilà qui va simplifier le passage entre SoftIce et un éditeur hexadécimale, les sections sont alignées.
L'adresse 00401000 se décompose en ImageBase (00400000 dans 90% des cas) et RVA (00001000 pour la section .text). Un "Goto 1000" dans un éditeur hexa va vous caler sur l'offset qui correspondra à l'adresse 00401000 dans SoftIce, ce qui est loin d'être fréquent!

Code Offset = 00001000, Code Size = 00004000
Data Offset = 00005000, Data Size = 00001000

La taille du Code étant de 00001000, la taille de chaque section sera un multiple de 1000h.
Ce qui va nous intéresser, c'est de connaître la taille réelle du code occupant chaque section: la Virtual Size:

.text   3E9C
.data   084C
.idata  0DE8
.reloc  0A9C
.rscr   6000

Par exemple la section .idata à une taille réelle de 0x0DE8 pour une Raw Size de 0x1000 soit une différence de 0x1000 - 0x0DE8 = 0x0218 ou encore 536 octets.
Ces 536 octets vont être complétés par des 0000 jusqu'à ce que la section ait une taille multiple du Code. C'est le Padding, et autant de place susceptible d'être prise.
Le début de la section .idata commence en 00400000 + 00006000 = 00406000. Elle se termine en 00407000. L'adresse de la fin du code utile est en 00406000 + 0DE8 = 00406DE8
Donc à partir de l'offset 0x6DE9, il y a moyen d'insérer du code à la place des 0000.
Ca, c'est la théorie...

00006DC0   6743 7265 6174 654B 6579 4100 9400 5265  gCreateKeyA...Re
00006DD0   674F 7065 6E4B 6579 4100 4144 5641 5049  gOpenKeyA.ADVAPI 
00006DE0   3332 2E64 6C6C 0000 0000 0000 0000 0000  32.dll..........
00006DF0   0000 0000 0000 0000 0000 0000 0000 0000  ................

A la suite de ces petits calculs, on se rend vite compte qu'il y a largement de quoi faire, et que la place ne manque pas. Vous verrez un peu plus tard qu'il y aussi de la place "disponible" directement en réécrivant sur le code lui même...


Gestion des Evénements:

Après avoir modifié les Menus, et noté les Identificateurs de ceux ci, il va falloir mettre la main sur la partie du programme s'occupant de traiter les messages les concernant.

Les programmes gèrent habituellement les événements liés aux messages (de menus, boites de dialogues...) à partir d'un "if uMsg = WM_COMMAND", qui se traduit souvent par cmp eax, 00000111.
Une recherche dans le dead Listing en donne deux occurrences, mais qui ne semblent pas être liées à un WM_COMMAND!
Je suis donc repartie de l'approche de +Mammon, en faisant une recherche sur le traitement des:

  MENUITEM "&Couper\tCtrl+X", 768, GRAYED
  MENUITEM "Co&pier\tCtrl+C", 769, GRAYED
  MENUITEM "C&oller\tCtrl+V", 770, GRAYED
  MENUITEM "&Supprimer\tDel", 771, GRAYED

les valeurs semblant significatives, ou du moins plus évidentes à localiser que les 1, 2, 3 ... 21 des autres Items:

768 d = 300 h. Petite recherche:

:0040125E 83FE20                  cmp esi, 00000020
:00401261 8BC6                    mov eax, esi
:00401263 7F1A                    jg 0040127F
:00401265 0F84F9040000            je 00401764
:0040126B 48                      dec eax
:0040126C 83F81B                  cmp eax, 0000001B
:0040126F 773F                    ja 0040112B      
:00401271 0FB688FB184000          movzx ecx, byte ptr [eax+004018FB]
:00401278 FF248DBB184000          jmp dword ptr [4*ecx+004018BB]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401263(C)
|
:0040127F 83F825                  cmp eax, 00000025
:00401282 0F846B030000            je 004015F3

* Possible Ref to Menu: MenuID_0001, Item: "Couper   Ctrl+X"
                                  |
:00401288 3D00030000              cmp eax, 00000300
:0040128D 7C21                    jl 004012B0

Un Bpx sur 0040127F va donner un break si, et seulement si, une action Ctrl+X est commandée. Donc c'est plus haut que la gestion des autres événements commencent.
En l'occurrence, c'est en

:00401271 0FB688FB184000          movzx ecx, byte ptr [eax+004018FB]
:00401278 FF248DBB184000          jmp dword ptr [4*ecx+004018BB]

Que tout ce décide!
ECX contient l'ID du menu cliqué, et le JMP va plonger sur une table dans laquelle se trouve l'adresse de l'événement à traiter.
Il y a donc deux possibilités:

Þ soit créer une petite dérivation juste avant, pour gérer nos nouveaux Items
Þ soit calculer l'adresse de la table où il n'y aura qu'à placer l'adresse du patch.

Par exemple notre Item Show me a un ID = 14h.
[(0x14 x 4) +004018BB] = 0040190B

00001900  0F04 0506 0708 090F 0A0B 0F0F 0F0F 0F0F  ................
00001910  0F0F 0F0C 0F0D 0E56 5733 F656 E825 0100  .......VW3.V.%..

Petit contrôle à l'adresse dans la table susceptible de recevoir un Dword. Pas de problème, elle est squattable sans flanquer la pagaille. (cf +Mammon qui indique dans son tut qu'entre 14d et 21d, il est possible de trouver une place dans cette table).

Mais pour cette fois ci, j'ai préféré dériver le programme vers une autre section (.adata)en plaçant un JUMP à la place du CMP EAX,1B/JA:

:00401265 0F84F9040000            je 00401764
:0040126B 48                      dec eax
:0040126C E93C400000              jmp 004052AD

Où on commence par restaurer les octets écrasés par le jmp:

cmp eax, 0000001B
ja  004012B0

Puis on passe au traitement des événements liés à nos nouveaux menus:

:004052AD  3DB1000000          CMP     EAX,000000B1
:004052B2  0F87F8BFFFFF        JA      004012B0
:004052B8  3D13000000          CMP     EAX,00000014 -> Item "show me"
:004052BD  740C                JZ      004052CB     -> Ok ? -> saute
:004052BF  3D14000000          CMP     EAX,00000014 -> Item "détection"
:004052C4  740C                JZ      004052D2     -> Ok ? -> saute
:004052C6  E9A6BFFFFF          JMP     00401271     -> retour au programme "normal" 
:004052CB  B8F06D4000          MOV     EAX,00406DF0 -> vers patch 2
:004052D0  FFE0                JMP     EAX
:004052D2  B80D6E4000          MOV     EAX,00406E0D -> vers patch 3
:004052D7  FFE0                JMP     EAX

Le traitement des sauts vers les Patchs auraient pu être plus direct (jmp Patch) au lieu d'un premier saut conditionnel, puis d'un mov adresse_patch, jmp patch, mais dans la mesure où le cadre du défi suggérait un renforcement de la protection, j'ai préféré des jump eax qui ne permettront pas de retrouver facilement les lignes ci dessus à partir des indications de Wdasm.


Le patch 1 est une simple boite de message, codée ainsi:

MessageBox(

    HWND hWnd,            // handle of owner window
    LPCTSTR lpText,      // address of text in message box
    LPCTSTR lpCaption,  // address of title of message box  
    UINT uType         // style of message box   ); 


ce qui donne à l'adresse 00406DF0:

6A00       Push 00          > bouton OK -> MB_OK (style of message box)
68B0D54000 Push 0040D5B0    > adresse du titre de la MessageBox
6810D64000 Push 0040D610    > adresse du message
6A00       Push 00          > Handle de la fenêtre (si 00, pas de fenêtre attribuée)
E82BD3B4BF Call messageBoxA > appel de l'API
B813000000 Mov  Eax, 13     > remise à 13h de EAX
E9644FFFF  Jmp 00401271     > retour à la normale.

Le paramètre à la sortie de l'API MessageBox influant sur EAX, il faut que la valeur de ce registre soit restaurée au risque, sinon, de vous retrouvez dans la nature à cause du jmp dword ptr [4*ecx+004018BB], l'adresse de la table en 004018BC ne correspondant à rien.

Les adresses du titre et du message de la box ont été écrit sous éditeur hexa à la place du texte que BRW donnaient comme étant celui de la boite About.

Le Patch 2

L'action provoquée par un clic sur l'Item "Détection" va entraîner un effet ON/OFF sur la détection éventuelle de SoftIce. La présence de SoftIce ayant déjà été détectée, un flag a été mis à 3 (histoire de ne pas mettre 0 ou 1) en cas d'absence active du débuggeur. Ce flag est pris sur le numéro de version du Bloc Note (offset D55E).

:00406E0D  6A00           PUSH    00                     > MB_OK
:00406E0F  68B0D54000     PUSH    0040D5B0               > titre MessageBox
:00406E14  803D5ED5400004 CMP     BYTE PTR [0040D55E],04 > Détection activée ?
:00406E1B  750E           JNZ     00406E2B               > non -> saute
:00406E1D  6890D64000     PUSH    0040D690               > oui -> "désactivation"
:00406E22  C6055ED5400003 MOV     BYTE PTR [0040D55E],03 > Flag " SI non détectable "
:00406E29  EB0C           JMP     00406E37               > suite MessageBox
:00406E2B  68B0D64000     PUSH    0040D6B0               > "Activation" anti SI
:00406E30  C6055ED5400004 MOV     BYTE PTR [0040D55E],04 > Flag " SI détectable "
:00406E37  6A00           PUSH    00                     > handle fenêtre
:00406E39  E8F0D2B4BF     CALL    USER32!MessageBoxA     > affichage
:00406E3E  B814000000     MOV     EAX,00000014           > restauration état EAX
:00406E43  E929A4FFFF     JMP     00401271               > retour à la normale

Le titre de la Boite de message et le Bouton OK étant commun aux deux cas de figure, le test 00406E14 va seulement déterminer quel est l'état en cours de la détection (active ou inactive) et l'inverser avant d'afficher le message "Détection activée" ou "détection désactivée". Ces deux messages ont été écrits par-dessus les informations de la boite About aux offsets D690 et D6B0 à l'aide d'un éditeur hexadécimal.


La Boite About

Le texte de la boite ABOUT est lisible sous BRW. Lors d'un clic sur l'Item About dans le menu "?", le programme va utiliser l'API ShellAboutA:

ShellAbout (

    HWND hWnd,               // handle of parent window
    LPCTSTR szApp,          // title bar and first line text
    LPCTSTR szOtherStuff,  // other dialog text
    HICON hIcon           // icon to display
   );

Vous remarquerez qu'une Icône est attendue. Cela aura son intérêt tout à l'heure.
Le masque de cette boite et son texte s'étalent dans la section .rsrc de D5B0 à D960, soit 688 octets de bonne place à prendre si l'About Box est détournée...

Pour mettre la main sur la gestion des événements liés à la sélection de l'Item About, il est possible de retourner en 00401271 pour chopper le moment ou l'ID (11d -> 0Bh) de cet Item sera utilisé pour le jmp indexé. Il est également possible de calculer d'emblée l'adresse dans la table où se trouve placé l'adresse du début de la routine de traitement:
[4*0B+004018BB]= 004018E7

000018E0   1540 001C 1540 00AD 1840 008A 1540 00A4  .@...@...@...@..

Soit à l'adresse 004018AD.

Une autre solution est de poser un bpx ShellAboutA, de sélectionner l'Item "A propos du Bloc-Notes" et d'attendre de tomber au milieu de le routine en question.

:004014EC  50             PUSH    EAX                  > handle de l'application
:004014ED  FF15C8644000   CALL    [USER32!LoadIconA]
:004014F3  50             PUSH    EAX                  > icône à afficher
:004014F4  6800104000     PUSH    00401000             > texte
:004014F9  FF3564504000   PUSH    DWORD PTR [00405064] > title bar
:004014FF  FF3500504000   PUSH    DWORD PTR [00405000] > handle de la fenêtre
:00401505  FF15F8634000   CALL    [SHELL32!ShellAboutA]

La Boite "A propos du Bloc-Notes" faisant apparaître une icône, le début de l'affichage de la boite en question commence en 004014EC.

HICON LoadIcon(

    HINSTANCE hInstance,     // handle of application instance
    LPCTSTR lpIconName      // icon-name string or icon resource identifier
   );

Il est important, en cas de bidouilles au niveau des APIs de savoir ce qui a été poussé sur la pile au risque sinon de voir votre patch planter le système. Suivant les cas, soit vous aurez à placer une dérivation avant les Push susceptibles de pouvoir être problématiques, soit de Poper la pile.

Après le chargement de l'icône, vous trouvez l'appel à la boite About par l'API ShellAboutA:

ShellAbout (

    HWND hWnd,                  // handle de la fenêtre
    LPCTSTR szApp,             // title bar et première ligne de texte
    LPCTSTR szOtherStuff,     // autre  dialog text
    HICON hIcon              // icon à afficher
   );

Il est maintenant facile d'opter pour deux solutions:

Þ soit intervenir directement dans le code des adresses ci dessus
Þ soit de placer dans la table, à l'offset 18E7, l'adresse du patch 2

J'ai choisi la seconde solution, beaucoup plus "propre" à mon avis, en plaçant 00406E48 dans la table à l'offset 18E7.
La boite About est équipée d'un détecteur de la présence de SoftIce, sur le schéma du MetlIce (push \\.\SICE-Call CreateFileA), et en fonction du résultat:

· de l'état du flag "détection activée/désactivée"
· de la présence active de SoftIce

La boite en question affichera "SoftIce détecté", ou seulement le message "FCF 2000/Reverse Enginnering".

:00406E48  6A00            PUSH    00                     > MB_OK
:00406E4A  68B0D54000      PUSH    0040D5B0               > titre "ChrisPad"
:00406E4F  803D5ED5400004  CMP     BYTE PTR [0040D55E],04 > détection activée
:00406E56  7407            JZ      00406E5F               > non -> saute
:00406E58  6A00            PUSH    00                     > hTemplateFile
:00406E5A  EB14            JMP     00406E70               > détection désactivée
:00406E5C  90              NOP                            > bah!
:00406E5D  EB05            JMP     00406E64               > Bof!
:00406E5F  68D5D54000      PUSH    0040D5D5               > FCF 2000 etc...
:00406E64  6A00            PUSH    00                     > handle fenêtre
:00406E66  E8C3D2B4BF      CALL    USER32!MessageBoxA     
:00406E6B  E93DAAFFFF      JMP     004018AD               > End proc
:00406E70  6880000000      PUSH    00000080               > dwFlagsAndAttributes
:00406E75  6A03            PUSH    03                     > dwCreationDistribution
:00406E77  6A00            PUSH    00                     > lpSecurityAttributes
:00406E79  6A03            PUSH    03                     > dwShareMode
:00406E7B  68000000C0      PUSH    C0000000               > dwDesiredAccess
:00406E80  6814104000      PUSH    00401014               > lpFileName -> \\.\SICE 
:00406E85  E8510CB7BF      CALL    KERNEL32!CreateFileA
:00406E8A  3DFFFFFFFF      CMP     EAX,FFFFFFFF           > Sice Détecté?
:00406E8F  74CE            JZ      00406F5F               > non -> saute
:00406E91  68C0D54000      PUSH    0040D5C0               > "SoftIce Detected"
:00406E96  EBCC            JMP     00406F64               > retour

le \\.\SICE ayant été écrit au préalable sous éditeur hexa à l'offset 1014

HANDLE CreateFile(

    LPCTSTR lpFileName,                             // pointer to name of the file 
    DWORD dwDesiredAccess,                         // access (read-write) mode 
    DWORD dwShareMode,                            // share mode 
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,  // pointer to security attributes 
    DWORD dwCreationDistribution,               // how to create 
    DWORD dwFlagsAndAttributes,                // file attributes 
    HANDLE hTemplateFile                      // handle to file with attributes to copy  
   );

Mais en procédant ainsi pour la détection de Sice, vous avez de fortes probabilités de trouver des références disgracieuses dans le Dead listing, sans parler d'une bête recherche sur "CreateFileA".
Une autre solution pourrait consister à coder dynamiquement en mémoire une partie des lignes ci dessus. Prenons les plus révélatrice d'un MeltIce

:00406E80  6814104000          PUSH    00401014             > lpFileName -> \\.\SICE 
:00406E85  E8510CB7BF          CALL    KERNEL32!CreateFileA
:00406E8A  3DFFFFFFFF          CMP     EAX,FFFFFFFF

Vous avez 15 octets à coder, soit 3 DWORD, 1 WORD et 1 BYTE.

:00406E80  Mov Dword Ptr [00406EX1], 00401014
           Mov Dword Ptr [00406EX5], 68BFB70C 
           Mov Dword Ptr [00406EX9], 51E8FFFF
           Mov Word  Ptr [00406EXD], FFFF
           Mov Byte  Ptr [00406EXF], 3D
:00406EX1  ADD [EAX], AL  -> 0000   > espace réservé pour la décompression dynamique
           ADD [EAX], AL  -> 0000
           ADD [EAX], AL  -> 0000
                          -> 00
:00406EY0  Suite du programme

Les Mov écrivent dans leur espace réservé les 3 lignes à " cacher ", puis le programme les exécute, avant de continuer comme si de rien n'était.
Un peu lourd, non?

On peut faire pire pour tromper un Dead Listing :

Ecrire les codes en Wide Char Format 68 00 14 00 10 00 40 00 E8 00 51 etc...

Puis créer une routine qui s'occupe de les récupérer à une adresse de départ (par exemple 0040D850), pour les placer à une adresse de destination (par exemple 00406EXX) avec un pas de 2 pour la lecture, et un pas de 1 pour l'écriture. De là a y inclure un petit Xor EAX, 53 (Ou EAX = octet lu et 53 une valeur bidon de votre choix, voir même indexée sur le double pas), vous avez un joli petit cryptage de la routine anti Sice , mais qui ne tiendra pas la route en face d'un BPX CreateFileA sous SoftIce...

Un transfert de bloc pourrait être tout aussi intéressant, et du coup porter sur l'ensemble de la routine ci dessus:

Adresse de départ du bloc: 0040D850 (par-dessus les informations de version)
Adresse d'arrivée du Bloc: 00406E48
Taille du bloc : 0x50 octets

Un Repz Movsb placé juste au-dessus de notre routine va permettre de transférer les 50 octets de l'adresse DEPART à l'adresse ARRIVEE:

Pushad             > sauvegarde des registres
mov ESI, 0040D850  > adresse de départ
mov EDI, 00406E48  > adresse d'arrivée
Mov ECX, 50        > taille du bloc à déplacer
Repz Movsb         > déplacement

Une fois le repz Movsb exécuté, la ligne suivante commence par la routine déplacée, et finissent par POPAD (restitution de l'état des registres).

Même en mettant la main sur CreateFileA dans le bloc à l'adresse DEPART, je doute fort que le Dead Listing puisse être d'une grande utilité...

Seconde détection SoftIce

Un seul Anti Sice ne me suffisait pas.
Dans l'idée que la première détection rencontrée pourrait faire oublier à un cracker débutant de penser à d'autres Anti Sice (ou Wdasm, Ou TRW, ou FrogsIce...) comme celui ci dessus (uniquement sollicité lors de la sélection de l'Item About), j'ai voulu en placer un bien détectable dès le démarrage de l'application.

J'ai bien essayé de glisser une Int68, mais si sur mon PC je n'avais pas de problème, sur d'autres le Notepad plantait. J'en suis donc resté au MelTice.
L'Entry point de NotePad étant en 004010CC, j'ai trouvé qu'une petite dérivation en 0040110C serait très bien:

:004010FE  803E00         CMP     BYTE PTR [ESI],00
:00401101  740B           JZ      0040110E
:00401103  803E20         CMP     BYTE PTR [ESI],20
:00401106  7F06           JG      0040110E
:00401108  46             INC     ESI
:00401109  803E00         CMP     BYTE PTR [ESI],00
:0040110C  75F5           JNZ     00401203
:0040110E  B9CED64000     MOV     ECX,0040D6CE  > pousse l'adresse d'arrivée
:00401113  51             PUSH    ECX           > sur la pile, et simule
:00401114  C3             RET                   > une fin de call

Avec un Push ECX pour ne pas rendre trop facile une recherche sur un JMP EAX déjà utilisé.

La dérivation est facile à trouver en traçant pas à pas sous Sice, mais en utilisant Wdasm comme débuggeur, je me suis dis qu'elle serait peut être moins évidente à voir, et puis en procédant ainsi, je n'avais pas à me soucier de laisser des * Referenced by a (U)nconditional Jump at Address 0040110E.

Cette fois ci, mon MeltIce va ressembler à ceci:

: 0040D6CE
Push  00        > iReadWrite
Push  00401014  > \\.\SICE
call  _lopen    > pour éviter un CreateFileA
Inc   eax       > évite le FFFFFFFF trop facile à repérer
cmp   eax, NULL > Sice detected?
Jne   0040D6E1  > non -> retour à la normale
Jmp   0040D6DA  > oui -> met le Flag "SICE Detected" à 3

L'avantage de _lopen est son petit nombre de paramètres à pousser sur la pile:

HFILE _lopen(

    LPCSTR lpPathName,   // pointer to name of file to open  
    int iReadWrite      // file access mode 
   );

Fin pour le moment des Anti XXX, il est temps de passer à autre chose.

Rajout de fichiers à ouvrir

C'est toujours en partant de l'idée de +Mammon, mais en l'adaptant à mes maigres connaissances en ASM que j'ai rajouté la possibilité de pouvoir ouvrir également des fichiers .asm et .bat, en plus du .txt d'origine.

Comme j'ai eu l'occasion de vous le dire dans l'introduction de ce texte, La Main Rouge avait déjà proposé ce défi, et Xose avait suggérée de permettre l'ouverture de ces fichiers. Sous forme d'hommage à ce groupe, voici comment je m'y suis pris:

+Mammon, dans son tut, partait d'une redéfinition des filtres et de l'API GetOpenFileNameA. Ayant eu du mal à correctement saisir sa technique, j'ai commencé par poser un BPX sur l'API qu'il indiquait:

BOOL GetOpenFileName(

    LPOPENFILENAME lpofn   // address of structure with initialization data
   );

1 seul paramètre est nécessaire à cette API.

:00401423 A38C564000              mov dword ptr [0040568C], eax
:00401428 E8633A0000              Call comdlg32.GetOpenFileNameA

Pour autant, rien à faire pour trouver dans les parages quoi que ce soit en lien avec ce que je cherchai. Et puis j'ai fait un petit tour dans mon éditeur hexa :

00001050 2A2E 2A00 4564 6974 0000 0000 2200 0000 *.*.Edit...."...
00001060 2E74 7874 0000 0000 2000 0000 E903 0000 .txt.... .......

Hey !
On trouve cote à cote le EDIT qui limite NotePad à 32Ko (cf texte de +Mammon), et les deux filtres correspondants au fichier texte, et à tous les autres types de fichiers.
Continuons à chercher, mais en Wide Char Format :

0000B800 5C00 2A00 2E00 7400 7800 7400 0B00 6E00 \.*...t.x.t...n.

Et quelques recherches de plus :

0000BA50 4400 6F00 6300 7500 6D00 6500 6E00 7400 D.o.c.u.m.e.n.t.
0000BA60 7300 2000 7400 6500 7800 7400 6500 0A00 s. .t.e.x.t.e...
0000BA70 5400 6F00 7500 7300 2000 2800 2A00 2E00 T.o.u.s. .(.*...
0000BA80 2A00 2900 0000 0000 CE00 5600 6F00 7500 *.).......V.o.u.

Voici les éléments du filtre qui vont pouvoir nous aider...

De fil en aiguille, vous arrivez rapidement ici :

:00402FD8  FFD3                CALL    EBX
:00402FDA  8D7C3801            LEA     EDI,[EDI+EAX+01]
:00402FDE  A1A4504000          MOV     EAX,[004050A4]
:00402FE3  50                  PUSH    EAX
:00402FE4  57                  PUSH    EDI

Ou un " d EDI " va vous montrer :

0187:00405550 75636F44  746E656D  65742073  00657478      Documents texte.
0187:00405560 78742E2A  00000074  00000000  00000000      *.txt...........
0187:00405570 00000000  00000000  00000000  00000000      ................
0187:00405580 00000000  00000000  00000000  00000000      ................

Changez txt en asm, et vous ouvrirez les fichiers ayant cette extension.
Rajouter une ligne supplémentaire (.Documents Bat.*.bat par exemple), et vous obtiendrez les deux filtres ouvrant les extensions .txt et .bat.
Un peu empirique, je vous l'accorde, mais opérationnel !

Vous avez maintenant tous les ingrédients pour pouvoir réussir un truc amusant :

Remplacer les éléments du filtre en 00405550 par ceux qui vous passeront par la tête. Commençons par définir les éléments de notre nouveau filtre, en continuant à écraser les informations de version :

0000D6F0 446F 6375 6D65 6E74 7320 7465 7874 6500 Documents texte.
0000D700 2A2E 7478 7400 446F 6375 6D65 6E74 7320 *.txt.Documents.
0000D710 6173 6D00 2A2E 6173 6D00 446F 6375 6D65 asm.*.asm.Docume
0000D720 6E74 7320 6261 7400 2A2E 6261 7400 546F nts bat.*.bat.To
0000D730 7573 2028 2A2E 2A29 002A 2E2A 0000 0000 us (*.*).*.*....

Maintenant, une petite dérivation vers de la place disponible :

:00402FDA  8D7C3801       LEA     EDI,[EDI+EAX+01]
:00402FDE  E95DA70000     JMP     0040D740
:00402FE3  50             PUSH    EAX

Et il n'y a plus qu'à charger notre nouveau filtre à la place de l'ancien :

:0040D740  60             PUSHAD               < sauvegarde des registres
:0040D741  BEF0D64000     MOV     ESI,0040D6F0 < adresse de départ
:0040D746  BF50554000     MOV     EDI,00405550 < adresse d'arrivée
:0040D74B  B94D000000     MOV     ECX,0000004D < taille du bloc à déplacer
:0040D750  F3A4           REPZ MOVSB           < déplacement
:0040D752  61             POPAD                < restauration des registres

Mais dans la foulée, on va ajouter une gâterie !

Création d'un fichier .CFG

A la suite de l'ouverture d'un fichier, j'ai souhaité glisser un espion. +Mammon propose dans son tutoriel la création d'un fichier .ini lui servant à mémoriser le nom du dernier fichier ouvert, pour le réafficher à l'ouverture suivante du Bloc-Notes.

Pour ne pas plagier trop facilement +Mammon, j'ai créé un fichier CFG mémorisant le dernier fichier ouvert, et le résultat de la détection de SoftIce :

[Last Open File]
Path=C:\Antipdd.txt

[SoftIce]
Detected=Yes

Pour réaliser cette action, j'ai fait appel à l'API WritePrivateProfileStringA :

BOOL WritePrivateProfileString(

    LPCTSTR lpAppName,       // pointer to section name 
    LPCTSTR lpKeyName,      // pointer to key name      
    LPCTSTR lpString,      // pointer to string to add 
    LPCTSTR lpFileName    // pointer to initialization filename    );	

Les paramètres à pousser sur la pile sont les adresses de l'lpAppName ([Last Open File] et (SoftIce]), lpKeyName (Path et Detected), et le texte à " mémoriser " (C:\Antipdd.txt et Yes).

Rien de bien compliqué pour lpAppName et lpKeyName. Il suffit de prendre la suite des autres strings créées, en utilisant un HexEditeur :

0000D760 633A 5C63 6872 6973 7061 642E 6366 6700 c:\chrispad.cfg.
0000D790 FF4C 6173 7420 4F70 656E 2046 696C 6500 .Last Open File.
0000D7A0 5061 7468 0000 3900 3800 0000 4000 0C00 Path..9.8...@...

reste trois choses :

- trouver de la place pour ce nouveau patch
- catcher le nom du dernier fichier ouvert
- détecter SoftIce une fois de plus

Vous avez pu voir que ce n'est pas la place qui manque, mais pour éviter d'être trop facilement localisé, j'ai continué à chercher des adresses différentes pour loger mes bébés et éviter de vous servir toutes les modifications les unes derrières les autres. Cette fois ci, je m'installe en 0040D770, dans les ex-infos de version.

Pour catcher le nom du programme ouvert, je me suis ré-intéressé à l'API GetOpenFileNameA.
La valeur retournée lors de l'appel de cette API, si un fichier à été choisi, est placé dans un buffet. Cherchons-le :

:00401423  A38C564000     MOV     [0040568C],EAX            > paramètre de l'API
:00401428  E8633A0000     CALL    comdlg32!GetOpenFileNameA
:0040142D  85C0           TEST    EAX,EAX                   > bouton OK sélectionné
:0040142F  0F8483000000   JZ      004014B8                  > non -> saute
:00401435  56             PUSH    ESI
:00401436  8D85C0FEFFFF   LEA     EAX,[EBP-0140]            > Buffet
:0040143C  6800000080     PUSH    80000000

Glop ! Glop !
Et il y a même un superbe Push 80000000 à remplacer par un JUMP :

:0040143C  E92FC30000          JMP     0040D770

Voyons le Patch :

:0040D770  60              PUSHAD               > sauvegarde les registres
:0040D771  6860D74000      PUSH    0040D760     > c:\chrispad.cfg
:0040D776  50              PUSH    EAX          > adresse du Buffet
:0040D777  68A0D74000      PUSH    0040D7A0     > " Path "
:0040D77C  6891D74000      PUSH    0040D791     > " Last Open File "
:0040D781  E83DA1B6BF      CALL    KERNEL32!WritePrivateProfileStringA
:0040D786  B88DAD4000      MOV     EAX,0040AD8D > vers l'Anti Sice 3
:0040D78B  50              PUSH    EAX
:0040D78C  C3              RET

Et toujours histoire de noyer le Dead Listing, un Push Eax/Ret pour aller à la routine suivante :

Le MeltIice bête et classique (manque d'inspiration...)

:0040AD8D  6A00            PUSH    00
:0040AD8F  6880000000      PUSH    00000080
:0040AD94  6A03            PUSH    03
:0040AD96  6A00            PUSH    00
:0040AD98  6A03            PUSH    03
:0040AD9A  68000000C0      PUSH    C0000000
:0040AD9F  6814104000      PUSH    00401014      > \\.\SICE
:0040ADA4  E832CDB6BF      CALL    KERNEL32!CreateFileA
:0040ADA9  6860D74000      PUSH    0040D760      > c:\chrispad.cfg
:0040ADAE  3DFFFFFFFF      CMP     EAX,FFFFFFFF  > détecté ?
:0040ADB3  7507            JNZ     0040ADBC      > non -> saute
:0040ADB5  680CD84000      PUSH    0040D80C      > " YES "
:0040ADBA  EB05            JMP     0040ADC1      > saute le " NON "
:0040ADBC  6808D84000      PUSH    0040D808      > " NON "  
:0040ADC1  6810D84000      PUSH    0040D810      > " detected " -> Key
:0040ADC6  6800D84000      PUSH    0040D800      > "  SoftIce " -> Section
:0040ADCB  E8F3CAB6BF      CALL    KERNEL32!WritePrivateProfileStringA
:0040ADD0  61              POPAD                 > restitue les registres
:0040ADD1  6880000000      PUSH    00000080      > restaure le push écrasé
:0040ADD6  E96666FFFF      JMP     00401441      > et retour à la normale


Il y a bien d'autres possibilités encore qui s'offre à un apprenti reverser. La place ne manque pas...

J'espère que d'autres répondront également à ce défi, et que nous aurons un panel de textes complétant le pauvre essai que je vous ai proposé.


Encore une chose...

La dernière version du ChrisPad était protégée par VG Crypt.
Regardons un peu comment il était possible de s'en débarrasser :

VG CRYPT 0.75: Comment écrire un script automatisé pour ProcDump


Rapide présentation:

This is a fairly simple PE encryptor I wrote up. I commented everything
; that is relavent to PE appendation or insertion, more so than I needed to
; even. The most interesting feature of this encryptor is that it attempts to
; find a location to insert itself between object virtual size and the next
; file alignment boundary, thus not changing the physical file size.

VG Crypt comme son nom l'indique, est un crypteur de donnés de 9 ko! Son objectif ne semble pas la protection en tant que tel, dans la mesure ou SoftIce rend la main sur l'Entry Point au lancement de l'application-cible si vous passez par le Symbol Loader, et Wdasm peut réaliser un désassemblage du programme en fournissant des ressources (String Data References…).
A ceci prêt que les StringDatas ne seront pas aussi complètes dans la version cryptée, que dans l'application d'origine, et limitées à un certain nombre.
En fait on pourrait croire que l'auteur de ce crypteur à volontairement cherché à noyer le poisson, lisez la suite:

Pour trouver comment réaliser ce script pour ProcDump, j'ai crypté mon NotePad.exe modifié, et j'ai contrôlé le bon fonctionnement du script avec Calc.exe.

Première approche:

Une fois crypté, Notepad n'a pas bougé d'un octet en taille virtuelle

Avant Cryptage :

.text    00003E9C    00001000     00004000     00001000     60000020
.data    0000084C    00005000     00001000     00005000     C0000040
.idata   00000DE8    00006000     00001000     00006000     40000040
.reloc   00000A9C    00007000     00001000     00007000     42000040
.rsrc    00006000    00008000     00006000     00008000     40000040

Après Cryptage :

.text    00003FF4    00001000     00004000     00001000     E0000060
.data    0000084C    00005000     00001000     00005000     C0000040
.idata   00000DE8    00006000     00001000     00006000     40000040
.reloc   00000A9C    00007000     00001000     00007000     42000040
.rsrc    00006000    00008000     00006000     00008000     40000040

Vous remarquerez que la doc de VG Crypt ne ment pas, il n'y a pas de création de section supplémentaire, le Loader de VG Crypt s'est simplement glissé dans la section .text en augmentant sa taille de 158 octets pour pouvoir s'y loger, et cette section a été modifiée pour la rendre Readable, et eXécutable, suivant le principe suivant:

   0x00000020 IMAGE_SCN_CNT_CODE 
   0x20000000 IMAGE_SCN_MEM_EXECUTE 
   0x40000000 IMAGE_SCN_MEM_READ 
-----------------------------------
   0x60000020 

Eventuellement si vous souhaitez la rendre Writeable, il faudrait faire:

       0x60000020
OR     0x80000000 IMAGE_SCN_MEM_WRITE 
-----------------------------------
       0xE0000020 

Bon, du coup, VG Crypt sera difficile à identifier, d'autant plus qu'il n'y a aucune "signature" de ce cryptage si vous en recherchez une avec un hexéditeur (pas de CopyRight, rien de rien…)
La seule manière de repérer un programme qui aura été crypté, sera lors du traçage avec F10 dans SoftIce, les portions de sections se codant et se décodant sous vos yeux (CCA ou Overlapping).
Pour autant vous ne saurez pas à qui vous avez affaire, dans ce cas précis.
Pas souvent que l'auteur d'un bidule de ce genre soit aussi discret…


Prenons les problèmes dans l'ordre

Le Loader:

Crypté ou compressé, il doit toujours y avoir un moyen pour obtenir une version au plus proche du programme d'origine…

Commençons par trouver le passage du relais vers l'Original Entry Point.

Via le Symbol Loader de SoftIce, vous allez charger l'application cryptée, et tracer doucement avec F10 depuis le point d'entrée: 00404E9D. En soit même cet Entry Point a de quoi mettre la puce à l'oreille, les points d'entrée des programmes honnêtes étant plutôt du genre 00401000 (bien que celle du NotePad d'origine soit 4010CC)…

Vous allez très rapidement arriver a trouver la routine de cryptage:

:00404FDD  8AA511274000  MOV       AH,[EBP+00402711] > Chaîne à traiter
:00404FE1  AC            LODSB               > charge EAX avec le contenu de DS:SI
:00404FE2  32C4          XOR       AL,AH     > ou logique entre AL(E8h) et AH
:00404FE4  FEC4          INC       AH        > ajoute 1 à AH
:00404FE6  C0C402        ROL       AH,02     > rotation à gauche de 2
:00404FE9  80C490        ADD       AH,90     > ajoute 90h à AH
:00404FEC  AA            STOSB               > transfère double mot par double mot 
                                             > le contenu de EAX dans ES:DI
:00404FED  E2F2          LOOP      004050E1  > et ce tant que CX est <> de 0 (boucle)
:00404FEF  E9CBFEFFFF    JMP       00404EBF    (JUMP)  ici
:00404FF4  0000          ADD       [EAX],AL
:00404FF6  0000          ADD       [EAX],AL

Juste au-dessus du Jmp 00404EBF, vous avez la routine de décryptage.
J'espère que les commentaires vous ont permis d'en appréhender le principe.

Donc en 00404FEF, le Loader a fini de décrypter la seconde partie de celui ci, mais le programme d'origine est encore crypté. Pour le moment seul le loader est devenu clean (et vous verrez, pas pour longtemps…)
F10 pour continuer la ballade, et vous voici ici:

:00404EBF  E800000000     CALL    00404EC4
:00404EC4  8B9D05274000   MOV     EBX,[EBP+00402705]
:00404ECA  83C328         ADD     EBX,28
:00404ECD  58             POP     EAX
:00404ECE  2BC3           SUB     EAX,EBX
:00404ED0  89850D274000   MOV     [EBP+0040270D],EAX
:00404ED6  CC             INT     3
:00404ED7  8DBD24264000   LEA     EDI,[EBP+00402624]
:00404EDD  B93B000000     MOV     ECX,0000003B
:00404EE2  F3AA           REPZ STOSB
:00404EE4  64678F060000   POP     DWORD PTR FS:[0000]
:00404EEA  5A             POP     EDX
:00404EEB  8B850D274000   MOV     EAX,[EBP+0040270D]
:00404EF1  018509274000   ADD     [EBP+00402709],EAX
:00404EF7  61             POPAD               > POPAD !
:00404EF8  9D             POPFD
:00404EF9  8B9A09274000   MOV     EBX,[EDX+00402709]
:00404EFF  898A09274000   MOV     [EDX+00402709],ECX
:00404F05  FFE3           JMP     EBX         > passage de relais caractéristique !

Si vous avez un tant soit peu l'habitude des programmes cryptés/compressés, le jmp EBX devrait vous sauter aux Yeux!
Dans la très grande majorité des cas, vous retrouverez un tel saut, ou l'une de ses variantes (Call EAX, Push Eax/Ret, Jmp Eax…) quand vous avez affaire à ce type de programme.

Donc, entre 00404EF9 et 00404F05, vous êtes sensé trouver:

- Le "dépôt" de l'entry point de l'application d'origine dans EBX (004010CC)
- Le décryptage de l'application d'origine
- La restauration des registres qui semble être une constante des programmes compressés (POPAD)

Faites un d 004010CC en arrivant en 00404EBF. Vous verrez des ????? dans la fenêtre des Datas (codes invalides). Tracez avec F10, et en passant sur l'INT 3 en 00404ED6, vous pourrez voir que ce mnémonique va permettre la décompression de NotePad, dans sa version pré-cryptée (par contre je ne sais pas quelle est le rôle exacte que joue l'interruption 3 dans l'opération de décryptage…). En continuant à tracer pas à pas, le REPZ STOSB va refermer les portes derrière vous en EFFACANT toutes les adresses précédant la 0040ED7 (vous y verrez à la place des jolies codes que vous aviez, de vilains ADD [EAX],AL), y compris le premier jmp que nous avions repéré en 00404FEF.

Continuez jusqu'au jmp EBX, et au F10 suivant, vous aurez changé de section, pour passer de .reloc à .text: vous êtes dans NotePad.exe, Bye Bye le Loader.

Obtenir une version Clean du programme compressé/crypté:

Ce qui va nous intéresser, maintenant, c'est de pouvoir obtenir l'ensemble des String Data References que Wdasm est supposé nous donner, et de réussir ensuite à modifier le programme en enlevant les erreurs de type Shareware qui pourraient y avoir été glissées…

Pour réaliser un Dump exécutable, vous allez remplacer le jmp ebx par un jmp eip. Ainsi le programme effectuera une boucle sans fin sur lui même, alors que l'application d'origine sera décompressée en mémoire.
Ceci fait, quittez SoftIce (F5), et ouvrez ProcDump. Dans "options", sélectionnez "Rebuit import table", puis Notepad (en version crypté) dans la liste des applications actives de la fenêtre de ProcDump. Clic_droit sur Notepad, et choisissez Dump (Full), puis sauvegardez le nouvel exécutable décompressé.
Cliquez ensuite "PE Editor", et remplacez le précédent point d'entrée par celui donné par EBX, soit 4010CC - 400000 (image base) = 10CC, en lieu est place du 4E9C.
Le résultat est exécutable et désassemblable avec toutes les ressources habituelles.

Désormais, vous pouvez traiter votre nouvel exécutable comme n'importe lequel des programmes dont vous avez l'habitude: il est clean, patchable à souhait, et fonctionne sans problème.

Mais si à chaque fois que vous tombez sur un programme encrypté par VG Crypt, vous devez refaire toutes ces manipulations, j'ai peur que vous finissiez par vous lasser…

Rédaction d'un script automatisé pour ProcDump.

Comme nous avons déjà repéré les deux goulets d'étranglement par lesquels VG Crypt nous a fait passer, il ne devrait plus être difficile d'automatiser tout le processus…

Voici ma proposition:

[VGCrypt]
L1=LOOK E9,CB         > recherche du JMP 0040D95F (1)
L2=BP                 > pose d'un break point
L3=LOOK 00,FF,E3      > recherche du JMP EBX (2)- 1 byte
L4=ADD 1              > avance de 1 byte
L5=BP                 > pose d'un break point sur le jmp EBX
L6=STEP               > commence à tracer le programme pas à pas
OPTL1=00000000
OPTL2=01010001
OPTL3=01010001 
OPTL4=00010000
OPTL5=00000000

Bien sur, vous n'oublierez pas de rajouter une entête dans l'index de ProcDump:

P1C=Shrinker 3.4
P1D=SalesAgent
P1E=Photo 1.0
P1F=VGCrypt

2 ou 3 détails pour finir:

En (1), la recherche ne porte que sur
E9 CB pour E9 CB FE FF FF. Inutile de chercher plus de 2 octets, c'est suffisant, il n'y en a pas d'autres identiques. Nous dirons que c'est la signature de VG Crypt, et ce pourra être utile pour identifier désormais que ce crypteur a été appliqué à un exécutable.

En (2), la recherche porte sur
00 FF E3, soit sur la fin du MOV[EDX+00402709],ECX (-> 89 8A 09 27 40 00), et sur le JMP EBX (FF E3), et ceci parce que le Loader, au moment ou il recrypte derrière lui sa première partie, va aussi traiter, sans modifications, les codes allant jusqu'au JMP EBX. Si vous ne mettez pas le 00 dans la chaîne à chercher, le Breakpoint va être posé trop vite, et faire planter l'opération. (Bien que je reste un peu dans l'expectative par rapport à cette solution, et à l'explication que je cherche à en donner…). Le ADD 1 servira simplement à avancer d'un octet, et à se recaller sur le JMP EBX.

ProcDump, au moment de la copie du Dump vous redonnera les 2 breakpoints (0040FEF et 0040F05), et vous indiquera l'adresse à laquelle l'EIP a été sauvé.

J'ai testé ce script sur plusieurs autres programmes, et apparemment sur mon PC, ça marche…

Bonne Journée

Christal