-------[  RtC Mag, At the end of the universe  ]

--------------[  Infection Win32 : Part 2  ]
--------------[  Manipulation de fichiers en asm  ]
---------[ fvrier 2001 ]
----[  by Doxtor L. <>  ]


-------[  Sommaire


    Voici le deuxime volet de notre srie d'articles consacre aux techniques de base utilises dans le phnomme de rplication d'un programme dans un autre.
    Pour se dupliquer, un programme auto-reproducteur doit pouvoir ouvrir un fichier (en l'occurence un autre fichier .exe) pour le modifier en ajoutant une partie ou la totalit de son propre code.     

Voila ce que vous trouverez dans cet article:
    1)  le Mapping.
    2)  Prsentation et utilisation d' APIs pour ouvrir un fichier et crire dedans.
    3)  Exemple d'un programme modifiant un autre fichier.
    4)  Conclusion.


-------[  1) Le Mapping


    Pour manipuler des fichiers, Windows offre des APIs dont la philosophie est assez proche des fonctions que Msdos,  travers le jeu d'interruptions, met  disposition du programmeur pour raliser ces tches dans cet environnement 16 bits. Je ne tiens pas  traiter de cela dans cet article. Je prfre aborder une autre manire de faire, spcifique  Windows, qui n'existe pas sous Msdos. La mthode repose sur le concept de MAPPING.

    Qu'est-ce que le Mapping? L'ide est assez naturelle. On voudrait pouvoir crire dans un fichier, qui se trouve sur un disque dur, avec la mme facilit que l'on crit en mmoire. Pour crire en mmoire, on peut procder de cette faon:

mov eax,01b75480h                    ;on met dans eax une adresse en mmoire
mov dword ptr [eax],0aabbccddh       ;on va crire sur l'espace mmoire
                                     ;qui commence  l'adresse 01b75480h
                                     ;(tous les nombres sont en criture
                                     ;hexadcimales)  
                                     ;Dword indique que l'on crit 4 octets
                                     ;d'un coup.

    Le rsultat est : A l'emplacement 01b75480h et aux trois suivants ont va trouver les octets aah,bbh,cch,ddh. Ouvrons une parenthse. En fait, plus exactement la mmoire ressemble  a :

adresse:          contenu:

01b75480h         ddh
01b75481h         cch
01b75482h         bbh
01b75483h         aah

    Le micropresseur a stock le nombre 0aabbccddh dans l'ordre inverse des octects (aah,bbh,cch,ddh) qui le composent. C'est une bizarrerie de tous les microprocesseurs pour PC. (Cela ne porte pas  concquence dans la pratique car la lecture
d'une zone mmoire de 4 octects en une fois, se fait aussi dans l'ordre inverse). Si vous voulez analyser le comportement de ce petit programme sous un dbogueur tel que td32 n'oubliez pas que l'criture dans une zone mmoire est svrement rglemente par Windows. Ecrire au hazard dans la mmoire va dboucher au mieux sur un cran bleu d'erreur, au pire au crash de Windows! On a vu que la partie d'un programme sous Windows qui correspond  la section appele ".data" dans le listing du code source est accessible en criture pour l'usage du programme lui-mme. Nous pouvons refermer cette parenthse.

    Voila en quoi consiste, pour rsumer le MAPPING : Par l'intermdiaire d'une srie d'APIs on demande  Windows d'ouvrir un fichier et d'en faire une image en mmoire. L'image sera la copie conforme de ce qu'est le fichier sur le disque. Windows va renvoyer de plus l'adresse de dbut de la copie en mmoire. Apres cela, en connaissant cette adresse et en utilisant les techniques pour crire en mmoire comme celle dja cite, on peut modifier cette copie.
    Une fois que l'on a fini notre travail sur cette copie, une autre srie d'appels  des APIs permet que ce qui a t fait sur la copie soit aussitt rpliqu sur le fichier qui a servi de modle ! La mmoire utilise par la copie sera libre.
    Le mot Mapping est issu du mot map qui veut dire carte. La copie est comme une carte qui reprsente le vrai fichier qui se trouve sur le disque. C'est comme ci nous avions une carte routire, et que si nous plantions une punaise sur la carte  l'emplacement o est indiqu Lyon et qu'au mme moment dans la ville relle  l'endroit prcis, qui correspond au trou fait par la punaise, se creusait un gouffre !


-------[  2) Prsentation et utilisation d'APIs pour ouvrir un fichier et crire dedans.


    Il y'a deux sries d'APIs qui sont utilises :
    * Une premire srie qui doit tre appele avant d'effectuer des modifications sur la copie du fichier en mmoire.
    * Une deuxime srie le sera aprs que l'on ait fini d'crire sur la copie.

    Ces successions d'appels  des APIs sont trs utilises pour manipuler des fichiers, pas de scrupules donc  les utiliser, pas la peine de connaitre dans le dtail le fonctionnement respectifs de tous ces APIs. Seul le rsultat produit est important.

    La premire srie : (l'ordre d'appel est respect)


API :                Fonction dans notre code :
CreateFileA          (cr ou) ouvre un fichier, un handle de fichier est retourn.
CreateFileMappingA   prpare la copie du fichier en mmoire. un handle pour le mapping est renvoy
MapViewOfFile        cr la copie. l'adresse o se trouve la copie en mmoire est renvoye. 


    La deuxime srie :  (l'ordre d'appel est respect) 

UnMapViewOfFile      l'image est rendue inacessible
CloseHandle          1) fermeture du handle du mapping
                     2) fermeture du handle de fichier
(cette API est utilise deux fois de suite comme indiqu)
 

    Examinons les paramtre requis pour toutes ces APIs:

    ** CreateFileA **

 1) doit tre 0
 2) doit tre 0
 3) doit tre 3, cela indique que l'on veut ouvrir un fichier dja existant.
 4) doit tre 0
 5) doit tre 1, indique comment sera partag l'objet.
 6) indique le type d'accs requis: lecture,criture...
 7) un pointeur qui spcifie o se trouve  la chane de caractres qui compose le nom du fichier  ouvrir. Le "A" de CreateFileA indique que le nom du fichier est crit en ASCII. (Par exemple "cible.exe"). Le nom du fichier doit tre suivi par 00h pour tre lu.

  Cette API renvoit un double mot (quatre octet), un Handle de fichier.


    ** CreateFileMappingA **

 1) doit tre 0, (sinon on doit specifier un pointeur qui pointe sur le nom que l'on veut donner  la copie en mmoire, inutile ici)
 2) Taille du fichier aprs infection, Il faut tenir compte de l'accroissement de taille que va occasionner le virus. Prvoir donc suffisemment de place.
 3) Doit tre 0. La taille sur disque d'un fichier est, pour le moment, jamais plus grande que 4 Giga octets.
 4) Doit tre 4. Ceci authorise la lecture et l'criture dans la zone mmoire ou sera cre l'image du fichier.
 5) Doit tre 0. Attribut concernant la scurit.
 6) Handle retourn par CreateFileA

  Aprs excution de cet API si aucune erreur ne survient un handle, c'est  dire un double mot non nul, est renvoy dans le registre EAX.


    ** MapViewOfFile **

1) Taille du fichier, mme remarque que prcedemment.
2) Doit tre 0.  Ce champ et le suivant sont utiliss si on veut ne pas compltement crer une image complte du fichier.
3) Doit tre 0.
4) Doit tre 2. Authorise la lecture et l'criture de l'image  crer.
5) Handle retourn par CreateFileMappingA.

    Cette API renvoie l'adresse mmoire, de l'image cre, dans EAX. Si EAX contient 0, une erreur est survenue.



    Voici la deuxime squence d'APIs :

    ** unMapViewOfFile **
  1) Adresse en mmoire de l'image fichier.(Cette adresse a t renvoye par MapViewOfFile)


    ** CloseHandle **
  1) le handle renvoy par CreateFileMappingA


    ** CloseHandle  *
  1) Le handle du fichier.


    Il y'a un petit inconvenient  utiliser le Mapping. L'espace mmoire, qui va tre allou pour crer l'image d'un fichier,  est dtermin au moment des appels des APIs dja cites. Maintenant, imaginez la situation suivante : Pour savoir qu'un fichier est dja infect, un virus doit le mapper pour le lire, et l apparait le problme. Si le virus cre une image du fichier tenant compte de sa taille aprs infection et si ce fichier est dja infect, sa taille va s accroitre inutilement et dangereusement. Cela peut tre un ennui srieux.
    Il y'a une manire simple d'viter cela. Le virus peut commencer  crer une image qui ait la mme taille que le fichier dont elle est la copie. Si le fichier est dja infect, il ne sera pas modifi par cette opration. S'il ne l'est pas, il faudra utiliser un deuxime Mapping qui cette fois tiendra compte de la taille aprs infection du fichier.
    Cette mthode marche mais oblige  utiliser deux fois le mapping la plupart du temps (au dbut de l'infection l'ordinateur hte contient presque que des fichiers non infects).

    Il y'a une alternative a ceci : Avant de fermer le handle d'un fichier, on peut retailler ce fichier. C'est  dire changer sa taille. Deux APIs existent et peuvent faire ce travail.


    ** SetFilePointer **

    Un pointeur, c'est  dire un index, indique la position courante dans le fichier. Cette API permet de l'avancer, de le reculer.
  1) Doit tre 0. On spcifie que le pointeur de fichier est dplac par rapport a la fin.
  2) Doit tre 0. La taille d'un fichier actuellement dpasse pas 4 Giga octets
  3) La distance de dplacement. En ce qui nous concerne ce sera la taille du virus.
  4) le handle du fichier.


    ** SetEndOfFile **

    Tout ce qui tait situ aprs la position courante du pointeur de fichier est supprim.
  1) Handle du fichier


    Voila qui achve la description des APIs ncessaires pour l'ouverture et la modification de fichiers.


-------[  3) Exemple d'un programme modifiant un autre fichier


    Dans ce qui suit, je vous propose le source d'un petit programme qui ouvre un fichier, dont le nom et la taille sont fixs, si ce fichier commence par les deux lettres "VI" le fichier n'est pas modifi sinon, la chane de caractres "VIRUS" est ajoute.

--- FIRST.ASM -----------------------------------------------------------------

; Ce code source est issu de l'article: Infection, partie 2
; par DoxtorL/[T.I]. Cr en Fvrier 2001.
;
;
; Ce programme est une illustration lmentaire de l'utilisation
; d'APIs Win32 pour la manipulation de fichiers.
; Ce programme ouvre un fichier dont le nom et la taille sont dtermins dans
; le code source qui suit.
;
; Si les deux premiers octets de ce fichiers sont "VI" le fichier est referm 
; et laiss tel quel. S'il ne contient pas "VI"  son tout dbut, 
; elles sont ajouts et le mot "VIRUS" est ajout  la fin du fichier.
; Pour ne pas alourdir le listing j'ai omis volontairement les tests
; habituels qui suivent chaque appel  une API; par exemple, aucun test
; n'est effectu sur la russite de l'opration d'ouverture du fichier.
;
;
; pour tester ce qui suit vous avez besoin d'un fichier de
; 100 octets que vous appellerez: cible.txt (ces paramtres peuvent tre
; modifis)


.386p                 

.model flat


.data

HandleFichier        dd 0
HandleMap            dd 0
AdresseMap           dd 0
TailleMap            dd 0

TailleFichier        dd 100                 ; vous pouvez changer ces deux valeurs
NomFichier           db "cible.txt",0       ; pour tester

.code


DEBUT:                        

    extrn CreateFileA          :Proc        ;
    extrn CreateFileMappingA   :Proc        ;
    extrn MapViewOfFile        :Proc        ;
    extrn UnmapViewOfFile      :Proc        ;
    extrn CloseHandle          :Proc        ;
    extrn SetFilePointer       :Proc        ;
    extrn SetEndOfFile         :Proc        ;
    extrn ExitProcess          :Proc        ;




    mov eax,dword ptr [TailleFichier]       ; on met dans eax la taille du fichier

; on s'occupe maintenant de la taille qu'aurra l'image:

    mov dword ptr [TailleMap],eax           ;
    add dword ptr [TailleMap],5             ; pour tenir compte de l'ajout des
                                            ; 5 lettres du mot "VIRUS"
    call Ouvrir                             ; on ouvre et mappe le fichier
    mov edx,dword ptr [AdresseMap]          ; on met dans edx l'adresse de dbut de l'image


; on teste les deux premiers octets:

    cmp word ptr [edx],"IV"                 ; remarquez que "VI" est inverse.
                                            ; La lecture en mmoire par le micropro-
                                            ; cesseur est faite  l'envers.
    jnz PasInfect                          ;
    sub dword ptr [TailleMap],5             ; le fichier est dja modifi. Pour ne
                                            ; pas accroitre inutilement sa taille 
                                            ; on soustrait ce que l'on avait prcedemment
                                            ; ajout.
    call Fermer                             ; le fichier a dja t modifi. 
    call ExitProcess                        ; On demande la fin du programme.


PasInfect:                                 ; Le fichier n'a pas encore t modifi.

    mov word ptr [edx],"IV"                 ; VI est ajout au tout dbut de l'image
                                            ; du fichier en mmoire.
    add edx,dword ptr [TailleFichier]       ; on veut pointer sur la fin relle du fichier
                                            ; en mmoire. On pointe maintenant sur la
                                            ; zone de 5 octets que l'on s'est octroy.
    mov dword ptr [edx],"URIV"              ; Le mot "VIRUS" est  cris a la fin
    mov byte ptr [edx+4],"S"                ; de l'image du fichier
    call Fermer                             ; le fichier est maintenant modifi et
                                            ; referm.                               
    call ExitProcess                        ;

Ouvrir:


; ouverture du fichier:

    pushad                                  ; sauvegarde des registres 

    push 0                                  ;
    push 0                                  ;
    push 3                                  ;
    push 0                                  ;
    push 1                                  ;
    push 80000000h or 40000000h             ;
    lea eax,NomFichier                      ;
    push eax                                ;
    call CreateFileA                        ;

    mov dword ptr [HandleFichier],eax       ; on sauvegarde le handle du fichier

; prpare le mapping:

    push 0                                  ;
    push dword ptr [TailleMap]              ;
    push 0                                  ;
    push 4                                  ;
    push 0                                  ;
    push dword ptr [HandleFichier]          ;
    call CreateFileMappingA                 ;

    mov dword ptr [HandleMap],eax           ; on sauvegarde ce handle

; le fichier est mapp:

    push dword ptr [TailleMap]              ;
    push 0                                  ;
    push 0                                  ;
    push 2                                  ;
    push dword ptr [HandleMap]              ;
    call MapViewOfFile                      ;

    mov dword ptr [AdresseMap],eax          ; on sauvegarde l'adresse de dbut de l'image
                                            ; cre en mmoire  
    popad                                   ; restauration des registres
    ret                                     ; retour au programme principal


Fermer:

    pushad                                  ;

; l'image cre en mmoire est supprime et le fichier va prendre en compte
; les modifications apportes.

    push dword ptr [AdresseMap]             ;
    call UnmapViewOfFile                    ;

    push dword ptr [HandleMap]              ;
    call CloseHandle                        ;

; on retaille le fichier si ncessaire:

    push 0                                  ;
    push 0                                  ;
    push dword ptr [TailleMap]              ;
    push dword ptr [HandleFichier]          ;
    call SetFilePointer                     ;

    push dword ptr [HandleFichier]          ;
    call SetEndOfFile                       ;

; on referme le fichier:

    push dword ptr [HandleFichier]          ;
    call CloseHandle                        ;

    popad                                   ;
    ret                                     ; retour au programme principal

end DEBUT


--- FIRST.ASM -----------------------------------------------------------------


-------[  4) Conclusion


    Vous connaissez maintenant les rudiments pour ouvrir et modifier des fichiers  partir d'un programme. J'ai laiss de ct le problme de la modification de l'heure d'un fichier. En effet  chaque fois qu'un fichier est modifi l'heure du fichier est change. Nous aurrons peut-tre l'occasion d'y revenir.

    L'article suivant sera consacr au format d'un fichier excutable de Windows. En effet pour que les modifications faites  un excutable le laissent valide il faut tenir compte de sa structure initiale. Cet article sera un peu thorique je m'en excuse d'avance.

    A bientot.


-------[  EOF