Une Grande Enquête,

Aprés "le chien des Baskerville":

Comment Patcher une DLL

By christal

Ce que fait, ou ne fait pas, le programme/cible n'a aucune espèce d'importance. Par contre, le fait qu'il soit compressé par ASPack, et que la DLL qui gère l'enregistrement de l'utilisateur le soit aussi, présente un certain intérêt.
Le problème est donc de réussir à patcher une dll compressée, à partir d'un exécutable qui l'est également. L'octet à modifier dans Fguard32.dll est en 10015663, le remplacement d'un 75 par un EB.

Les méchants:
Les malfrats: Folder Guard 04.11
Le complice: ASPack

Les gentils:
Softlock Holmes: SoftIce 4.0
Dr Wadsom: Wdasm 6
Le Super Intendant: ProcDump 1.5

C'était un soir. SoftLock Holmes et son fidèle compagnon, le Dr Wadsom était au coin du feu quand le carillon de la porte d'entrée résonna. C'était le super Intendant ProcDump qui venait les solliciter pour une bien étrange affaire: un détournement de saut dans une dll, appartenant à la bande de Folder Guard.
L'affaire n'était pas simple, il fallait réussir à dévier ce branchement en obligeant l'exécutable (des hautes oeuvres) de la bande de malfrats à l'effectuer sans qu'il s'en rende compte. Une affaire à la mesure de nos détectives...

Au son de son célèbre violon, Softlock Holmes commence à réfléchir à ce que le Super Intendant lui avait dit. Visiblement, l'exécutable à convaincre (sans qu'il s'en doute) avait codé ses données pour les rendre inaccessibles. Oui, mais comment?

Les premières informations rapidement obtenues par nos deux détectives, chacun de leur coté, furent les suivantes

Sherlock Holmes:
Le programme ne break pas sur l'Entry point, en passant à la moulinette de son fameux Symbol Loader. C'est louche!

Dr Wadsom:
Quelques questions posées aux indics des bas quartiers ne donnent rien. C'est l'Omerta!, la loi du silence. La seule information que notre brave docteur récupère, et le nom d'un bar louche ou se retrouverait la bande à Folder guard pour commencer leur réunion:

+++++++++++++++++++ ASSEMBLY CODE LISTING ++++++++++++++++++
//********************** Start of Code in Object .text **************
Program Entry Point = 0047E000 (Fguard.exe File Offset:0007E000)


Mais ni listing, ni ressources.
Pour le moment cette adresse, même si elle n'est pas courante, ne constitue pas une preuve flagrante d'une quelconque compression.

Grâce au Super Intendant ProcDump, les sections du PE Header qui régissent cette loi du silence vont lever une partie du voile, et voici la liste que le Super a établi:

.text     00041000    00001000   00022400      00001000      C0000040
.rdata    00013000    00042000   00005600      00023400      C0000040
.data     0000A000    00055000   00000C00      00028A00      C0000040
.rsrc     0001F000    0005F000   0000BA00      00029600      C0000040
.adata    00003000    0007E000   00002800      00035000      C0000040
.udata    00001000    00081000   00000000      00037800      C0000040

Une étonnante section .udata attire tout de suite l'œil exercé de SoftLock Holmes. L'un de ses collègues, le détective Belge Hercule TeeJi Poirot, avait déjà mis en évidence que cette section était significative d'une compression ASPack.
Ainsi, ce serait ce compresseur qui assurerait la protection de notre bande de malfrats?

Pour briser cette loi du silence qui règne autour de Folder Guard, SoftLock Holmes et le Dr Wadsom décident de faire modifier par le Super Intendant ProcDump, les caractéristiques de la section .text, et de remplacer le C0000040 (propre aux sections compressées) par un E0000020 pour que .text devienne Readeable, Writeable et eXecutable.
Les résultats sont immédiats, Le Dr Wadsom peut enfin obtenir des éléments tangibles sous la forme d'un listing. Mais le poids de l'Omerta est difficile à briser, et les String Data Références continuent à être muettes:

String Resource ID=00129: ' "
String Resource ID=00130: ' "
String Resource ID=00132: ' "
String Resource ID=00136: ' "

Et peut on réellement faire confiance dans le listing soutiré à Folder Gard?
Il y a encore trop de zones d'ombres...

De son coté, SoftLock Holmes a plus de chance, et réussi à s'introduire subrepticement dans la place:

0177:0047E000  60            PUSHAD                > Entry Point
0177:0047E001  E800000000    CALL      0047E006
0177:0047E006  5D            POP       EBP
0177:0047E007  81ED0A4A4400  SUB       EBP,00444A0A
0177:0047E00D  BB044A4400    MOV       EBX,00444A04

Le PUSHAD sur l'Entry point (sauvegarde des coupables registres sur la pile), va finir de persuader notre détective qu'il a bien affaire à une compression.
Les conclusions définitives seront faites après l'enquête diligentée par PE SNIFFER, un précieux collaborateur, et qui identifiera formellement ASPack, sans pour autant préciser sa version exacte.

Lors d'une réunion de nos détectives, voici les informations qu'ils rassemblèrent sur ASPack:

· ProcDump peut obtenir un exécutable décompressé, mais ne traite pas les Dll
· ASPack utilise la même signature à chacun de ses mauvais coups: 50 CC
· Il signe toujours trois fois ses méfaits, et de la même façon
· Le décompresseur du loader ASPack est lui même compressé

A l'aide de ses informations, le Super Intendant ProcDump va se mettre au travail (UNPACK /ASPACK), et après un interrogatoire rapide, va obtenir le numéro de version d'ASPack, la 108, plus connue sous le nom de 10.83.
A l'aide de l'un des scripts dont il a le secret:

[Aspack108.3]
L1=OBJR
L2=LOOK 6A,00,50
L3=BP
L4=OBJR
L5=LOOK 50,C3
L6=ADD 1
L7=BP
L8=WALK
L9=OBJR
LA=LOOK 50,C3
LB=ADD 1
LC=BP
LD=STEP

ProcDump aura vite fait de transformer l'exécutable d'origine de 222 ko en un nouvel exécutable pleinement fonctionnel de 499 ko.
Entre les mains expertes du Dr Wadsom, cet exécutable donnera une liste de ressources, et un listing, mais dont la fiabilité ne sera pas à toutes épreuves. Pour autant, tout n'est pas encore clair dans les aveux de ce rascal, il y a encore de nombreuses zones d'ombres...

A l'aide des informations rassemblées, SoftLock Holmes va partir à la recherche des 3 signatures d'ASPack. De la porte d'entrée, et en traçant avec F10, SoftLock va trouver rapidement la première de ces signatures:

0177:0047E0CB  8D85374C4400        LEA       EAX,[EBP+00444C37]
0177:0047E0D1  50                  PUSH      EAX
0177:0047E0D2  C3                  RET
0177:0047E0D3  0000                ADD       [EAX],AL
0177:0047E0D5  0000                ADD       [EAX],AL

Le Push EAX / RET suivi d'octets nuls est la traduction mnémonique des opcodes 50 CC. Comprenne qui voudra...
En continuant sa filature, notre vaillant détective va mettre la main sur la deuxième signature des malfrats: ASPack a encore frappé, et toujours dans le quartier .adata:

0177:0047EF88  FF95BD504400        CALL      [EBP+004450BD]
0177:0047EF8E  8D85374C4400        LEA       EAX,[EBP+00444C37]
0177:0047EF94  C60563560110EB      MOV       BYTE PTR [10015663],EB
0177:0047EF9B  50                  PUSH      EAX
0177:0047EF9C  C3                  RET

Un petit interrogatoire de EAX va donner une nouvelle adresse: 0047E233

Le troisième, et dernier méfait d'ASPack va se dérouler dans le quartier .text:

0177:0047E560  C20C00              RET       000C
0177:0047E563  50                  PUSH      EAX
0177:0047E564  C3                  RET

Et cette fois ci EAX va être égale à 00416B22. C'est l'Entry Point de la version non protégée de Folder Guard

Comme parmi nos différents enquêteurs aucun ne se sent le goût pour des heures supplémentaires, il n'y aura pas de Dump manuel cette fois ci. Pourtant rien n'aurait été plus facile, en posant un jmp EIP en 0047E564, et en demandant à ProcDump d'exécuter un DUMP FULL de Folder Guard en mémoire, puis de restituer le bon Entry Point de l'exécutable obtenu.
Mais dans la mesure ou ce dump n'apportera rien de plus à l'enquête...

Maintenant que notre équipe connaît le mode de fonctionnement d'ASPack, il va falloir obtenir deux nouvelles informations:

· Le moment ou ASPack aura décompressé la Dll visée
· Le moment ou le décompresseur lui même aura été décompressé. Une histoire de fou...

Un point d'arrêt en 0047E0D2 , le premier des push EAX / RET, et un "d 10015663", l'adresse du branchement à modifier, va permettre de savoir que Fguard32.dll est clean en mémoire, et un BPM sur 0047E0D5, que le loader est partiellement décompressé après ceci:

:0047E0AE  F3A5           REPZ MOVSD
:0047E0B0  8BC8           MOV       ECX,EAX
:0047E0B2  83E103         AND       ECX,03
:0047E0B5  F3A4           REPZ MOVSB

En faisant appel à deux de ses collègues, HexWorkShop, et Hiew, SoftLock Holmes va essayer d'isoler dans Folder Guard, une chaîne qui va nous intéresser:

0177:0047E0CB  8D85374C4400        LEA       EAX,[EBP+00444C37]
0177:0047E0D1  50                  PUSH      EAX
0177:0047E0D2  C3                  RET

Si le Loader n'était pas compressé, il y aurait moyen de mettre la main sur 8D85374C440050C3.
Or, il faut attendre la fin de l'action REPZ MOVSB pour que ces octets soit écrit en mémoire sous la forme qui conviendrait à nos enquêteurs pour réussir à glisser un petit Patch.

Le plan de bataille que Sherlock Holmes et son équipe vont mettre en œuvre pour contrer la protection de Folder Guard, va être de détourner le chemin des malfrats pour les obliger à passer par un Patch. Celui ci va modifier le branchement de Fguard32.dll, avant de permettre à Folder guard de continuer sa route comme si de rien n'était. Cette déviation est virtuellement possible entre la fin de la décompression du Loader, et le push EAX / RET.

Reste que nos limiers doivent trouver un espace suffisant pour accueillir le Patch en question.

C'est encore SoftLock Holmes qui va trouver la solution en s'aidant de la liste donnée par le Super intendant ProcDump.
Sachant qu'il peut y avoir de la place disponible à la fin d'une section (... une histoire d'équilibrage de taille), Il va faire le calcul suivant:
Image base de Folder Guard (00400000) + Entry point (7E000) qui correspond à la section .adata + taille virtuelle de la section (3000) = 481000, début de la section .udata.

Or la taille réelle de la section .adata est de 2800 octets, soit 3000 (virtual size) - 2800 (raw size) = 200 octets qu'il serait possible de récupérer en modifiant la raw size du nombre d'octets qu'il nous est nécessaire pour y écrire un patch. La modification de la raw size peut facilement être réalisée par la commande PE EDITOR de ProcDump. En procédant ainsi, notre patch pourrait démarrer à l'adresse 400000 + 7E000 + 2801 = 480801.

Une autre solution, serait de jouer les grosses feignasses, et d'utiliser l'ascenseur de la fenêtre des Datas pour chercher vers la fin de cette section des octets nuls (0000).
La méthode a un coté empirique et aléatoire, mais fonctionne souvent, et c'est l'adresse 0047EF7B qui va être choisie pour le Patch.
Par contre, pour s'assurer qu'il n'y aura pas d'écriture à cette adresse, un petit BPM 0047EF7B RW va être indispensable, avant de continuer.

Mise en place de la déviation:

:0047E0AE  F3A5           REPZ MOVSD
:0047E0B0  8BC8           MOV       ECX,EAX
:0047E0B2  83E103         AND       ECX,03
:0047E0B5  F3A4           REPZ MOVSB         > fin de la décompression du loader
:0047E0B7  E9BF0E0000     JMP       0047EF7B > saut vers le Patch
:0047E0BC  006800         ADD       [EAX+00],CH
:0047E0BF  800000         ADD       BYTE PTR [EAX],00
:0047E0C2  6A00           PUSH      00
:0047E0C4  50             PUSH      EAX
:0047E0C5  FF95BD504400   CALL      [EBP+004450BD]
:0047E0CB  8D85374C4400   LEA       EAX,[EBP+00444C37]
:0047E0D1  50             PUSH      EAX      > pousse l'EP sur la pile
:0047E0D2  C3             RET                > simule un ret sur call

Juste après la décompression du Loader, et avant le Push EAX / RET, le JMP 0047EF7B va envoyer vers l'adresse secrète, qui va être organisée de la façon suivante, pour recevoir nos malfrats, ni vu, ni connu.

01:0047EF7B  8B85B5504400        MOV       EAX,[EBP+004450B5]
02:0047EF81  66680080            PUSH      8000
03:0047EF85  6A00                PUSH      00
04:0047EF87  50                  PUSH      EAX
05:0047EF88  FF95BD504400        CALL      [EBP+004450BD]
06:0047EF8E  8D85374C4400        LEA       EAX,[EBP+00444C37]
07:0047EF94  C60563560110EB      MOV       BYTE PTR [10015663],EB
08:0047EF9B  50                  PUSH      EAX
09:0047EF9C  C3                  RET

De la ligne 01 à 06, vous retrouverez le même décor que celui qui suivait à l'origine le REPZ MOVSB en 0047E0B5. En fait Softock Holmes se contente de réécrire les octets qu'il a écrasé avec le jmp 0047EF7B. En ligne 07, l'octet à modifier dans Fguard32.dll est remplacé par EB (jmp), puis l'Entry Point est replacé sur la pile, et le programme continu en ligne 08 vers la suite de la décompression ASPack.

Tout est en place.
Les malfrats arrivent, détournés sans rien avoir vu de louche. Ils traversent le patch sans problème, modifient la dll, et poursuivent leur chemin le plus naturellement du monde.
Arrivé en 10015663:

Bingo!
Folder Guard est piégé, et bien malgré lui, obligé de se considérer comme un programme enregistré. Tous les indicateurs le confirme, la protection ASPack, sous des apparences trompeuses, a volé en éclat...

Tout cela est bien joli, mais notre équipe de détectives doit maintenant s'assurer que ce qui marche en mémoire, donc en théorie, va fonctionner également après une modification physique des octets de l'exécutable.
C'est Hiew qui va se charger du travail: recherche de l'adresse à patcher, F3, modifications des codes, F9, et on relance.
Pour le moment Folder Guard n'a qu'une surcharge pondérale, mais ne passe pas (encore) par le patch.
1er essai: pas de plantage
2eme essai: le patch ne bouge pas en mémoire, donc pas de réécriture à cette adresse par ASPack.

Holmes et son équipe décident de finir le travail, et implantent le branchement en 0047E0B7 vers le patch.

RE Bingo!

La modification physique de Folder Guard fonctionne à l'identique du test en mémoire.
C'est fini, et même si ce Patch n'est pas très élégant, et qu'il y a certainement moyen de faire mieux,
CA MARCHE!

Bonne journée
Christal