Préface
Aujourd'hui, je vais étudier
avec vous le système WWPack32 de Piotr Warezak et Rafal Wierzbicki.
Qu'est ce que WWPack32 ? La
réponsese trouve dans la DOC officielle :
![]()
Registered version advantages
- DLL compression,
- full version EXEINFO-like tool which is capable of predicting compression ratios,
- file signature option (only 'Shareware Author'/'Software Developer' version),
- printed user's license available on request (only 'Shareware Author'/'Software Developer' version),
- free 1.xx e-mail upgrades, WWPack32 distribution list subscription,
- WWPack32 web support pages" access (http://xyz.xyz.xyz/xyz),
- no shareware nag screen J
OverviewWWPack32 is an advanced Win32 executable file compressor. WWPack32 makes Windows 95/98/NT EXE and DLL files smaller and protects programs from cracking. Compressed files run exactly as before!
WWPack32 will save you disk space and it will also protect your programs from cracking.
Main features
- The tightest compression ratio available: algorithms are based on the well known WWPACK for DOS, the winner of many executable compressors' comparisions.
- Easy to use menu and quick menu.
- Automatic file structure analyzer which searches for Windows executable files.
- Full long filenames support.
- 32bit decompression routine written in pure assembler which results in decompression speeds of over 1MB/sec (!).
- Built in program code and relocation table compressor.
- Full Windows 95, Windows 95 OSR2, Windows 98 and Windows NT compatibility.
- Easy installation and configuration.
- Optional compression levels.
- Compatibility with any File Allocation Table.
Maintenant ce que la doc ne dis pas, c'est que ce programme ne peut pas TOUT compressé, ( j'aimerais savoir pourquoi !? si quelqu'un a une réponse. teejee@hotmail.com ). De plus, il ne peut faire qu'une couche de compression, et ne peut compressé que les fichiers qui n'ont jamais été compressé par un autres Compresseur / Crypteur.
|
Pour mon étude, j'ai utilisé
Ma première approche fut de comparer les PE Header ( et donc les différentes sections ) avant et après avoir compressé avec WWPack32. Je compresse donc une copie ( comme cela je garde toujours une version PROPRE de Notepad.exe ) de Notepad.exe et voilà les différentes information que WDasm nous fourni :
De manière à éclaircir les
chose et à bien voir ce qui à changé, je vais remetre ces information dans un tableau comparatif
et rajouter quelques détails sur les sections ( comme la Virtual Size ) qui ne sont pas affichée
dans WDasm. Pour récupérer les détails supplémentaires, j'ai utilisé ProcDump
disponible sur procdump32.cjb.net
* La première valeur est la valeur avant
compression, la 2ème est donc après compression.
Voilà donc un premier aperçu des changement aparus dans le PE Header. et donc dans les section. On peut déjà voir plusieurs point important :
Après cela, je crois qu'il serait intéressant de jeter un oeil aux dead-listing ( code désassemblé ) du fichier compressé. Mais il y a un problème car quand on veut se rendre à l'adresse de l'Entry Point du programme Compressé ( EPC ), on se rend compte qu'il n'est pas désassemblé. En effet, nous voyons le code des section .texte et .data. En fait, cela ce passe a cause des Flags des section. Si vous les regardez, vous verrez que il y a uniquement .text et .data qui ont les Flags E0000020. Ca veut dire, pour le programme, que ces sections contiennent du code exécutable. Les autres sections n'ayant pas ces caractéristiques, elles ne seront donc pas désassemblées. La réponse à ce problème va être rapide, nous allons simplement changer les flags de la section .WWP32 en E0000020. Pour ce faire, il faut retourner dans ProcDump, clicker sur PE-Editor, sélectionner le fichier compressé, clicker sur Section puis clicker avec le bouton droit sur la section .WWP32 et mettre dans la partie caractéristique E0000020 et pour que tout fonctionne bien, il faut aussi mettre la section .data à C0000040. Voici mes sections après modifications : Object01: .text RVA: 00001000 Offset:
00000400 Size: 00002200 Flags: E0000020 Maintenant si vous désassemblez à
nouveau le fichier compressé, vous aurez le dead-listing de la section WWP32 et donc du Loader. On jette
un oeil et on repère des endroit ou insérer plus tard notre patch :
Ben voilà un bon paquet de place où nous allons pouvoir insérer notre code. Mais, il y a un problème. Si vous avez regardé tout à l'heure la place allouée en mémoire ( Virtual Size ) pour la section .WWP32, vu avez pu remarquez qu'elle n'est que de 000006B7. Donc en mémoire, la section ira de (00400000+0000D000) à (00400000+0000D000+000006B7) soit de 0040D000 à 0040D6B7 !! Donc, il va falloire modifier cela pour qu'elle aille jusqu'à, par exemple, 0040D800 ( 800 bytes est le maximum que nous pourrons utiliser car c'est le nombre de bytes qui se trouve sur le disque. !! le calcul à faire pour le connaître ce maximum est ImageBase + Virtual Offset + Raw Size ). Nous aurons donc 0040D800-0040D6B3=14D hexa soit 333 bytes à notre disposition :). Je jette vite fait un coup d'oeil sur le dead-listing du Loader, et je tombe ici ( est-ce que les dieux étaient avec moi ? :) :
Ben voilà une bonne nouvelle, je crois que j'ai trouvé l'adresse de l'instruction qui va sauter sur l'EPO quand celui-ci sera décompressé. Le plus marrant serait que l'adresse de l'instruction se trouve toujours à 0x294 bytes de l'EPC ( Entry Point du programme Compressé ). Mais on verra cela plus tard. Maintenant, reguardons un peu le début du code du loader à partir de l'EPC. Nous voyons ceci :
Si vous regardez le jump en 0040D006, vous voyez qui ne saute pas sur une instruction affichée, mais il se décalle de 2 bytes sur la droite. Ceci à 2 buts( voir même plus ). Le premier étant de mettre la confusion dans le petit cerveau que hmm.. la vie à bien voulu nous donner, et deuxièmement, à bloquer certain debugger ( celui de WDasm notamment ). Je me suis donc amusé à réécrire
le code 2 byte décalé et ca donne ceci. On voit qu'ici "l'équilibre" est vite revenu
à la normal, mais imaginez que le programme fasse cela tout le temps. Je vous jure qu'alors cela devient
impossible !
Bon, je ne vais pas m'attarder plus longtemp sur le Loader car nous savons tout ce qu'il faut pour patcher un programme compressé avec WWPack32. Mais, si vous vous souvenez, j'avais dis qu'il fallait vérifier si l'instruction qui jump vers l'EPO est toujours à la même distance de l'EPC. Je vais donc compresser un autre programme ( Calc.exe fournit aussi avec Windows 95 OSR 2 ). Et voici ce que le PE Header m'apprend : Avant Compression :
Après compression :
On a donc bien une section supplémentaire nommée .WWP32 ajoutée dans le programme compressé et dont la première instruction est l'EPC. Maintenant, allons voir en 00413000+294 = 00413294 où on devriait trouver le jmp vers l'EPO :
Afin de vérifier tout ce que j'ai dit,
j'ai fait un patch pour notepad qui enlève l'acces à l'aide. Ceci n'a rien d'extraordinaire, j'ai
juste nopper le call WinHelpA. J'ai inséré mon patch en 0040D6B3 et modifié le jmp 401000
en 40D294 pour qu'il jump sur mon patch en 40D6B3 et j'ai rajouter un jmp 401000 à la fin de mon patch.
Voici la preuve en image :
J'ai ensuite modifié le Virtual Size de la section .WWP32 en lui mettant la valeur de son RAW Size. Ainsi je peut utiliser tout le code ( les 000000 ) situé à la fin de la section et mon patch est chargé en mémoire. Je lance mon notepad modifié et là, erreur. Je reguarde ce que Windows me dis :
Une défaillance en 0040D271, cela ressemble plus à une protection qu'autre chose car cette addresse fait partie du code du Loader ( car elle appartient à la section .WWP32 ). Je me rend donc en 0040D271 et je trouve ceci :
A ce que j'ai compris, cette boucle sert en fait à vérifier à quelle addresse la section se termine ( et que le reste de la section est donc remplie avec des 00 ). Quand il trouve cette adresse, il lui soustrait l'adresse à laquelle elle devrait se terminer ( que lui connait ) et il vérifie si le résultat de cette soustraction vaut 00. Sinon, c'est que quelqu'un à rajouté du code à la fin d'une section pour, par exemple, rajouter un patch :) ( Infos à vérifier ) La solution du problème est donc évidente.
Il suffit de forcer les jumps conditionnels en 0040D27B et en 0040D26D. Nous aurons donc maintenant :
Voici donc comment résoudre la seule et unique protection, en utilisant non pas Softice, mais en utilisant les infos données par Windows lors d'une erreur :) Rem
: Je force les 2 jumps conditionnels par mesure de sécurité.
Résumons-nous maintenant :
|
Amicalement,
TeeJi
teejee@hotmail.com