                                                               

 /-----------------------------------------------------------------------\

  INFECTION WIN32 :    I/ Premiers pas dans la programmation de Windows 
                       en assembleur.                                   
                                                                       
                       (Doxtor L. Janvier 2001)                        
 /-----------------------------------------------------------------------\





          Cet article est le premier article d'une serie qui se propose de 
     traiter les bases ncessaires  la comprhension et la ralisation de 
     programmes auto-reproducteurs fonctionnant dans un environnement Win-
     dows 32 bits comme windows98.  




Dans ce qui suit vous trouverez quelques informations qui peuvent vous aider
 dbuter dans la programmation de Windows en assembleur.



Matriel ncessaire:

les programmes et fichiers suivants sont indispensables:

     - Tasm32.exe version 5.0    De chez inprise/borland
     - Tlink32.exe            
     - Import32.lib
     

Ce qui suit n'est pas ncessaire, mais conseill:

     -Un dbuggeur peut s'avrer trs utile ,
      je vous conseille td32 pour dbuter, mme si celui-ci
      s'avre tre rapidement insuffisant  l'usage.

      si vous dcidez d'approfondir le sujet, optez pour
      softice.

     -Une liste documente des APIs (voir plus loin pour la signification
      de ce sigle) standard utilises par Windows.

      En gnral fournit avec tous les compilateurs (Vc++,c++ de Borland,..)
      qui produisent du code excutable sous Windows.
      
  
  Voila ce que vous trouverez dans cet article: 

 
  I) Comment batir un fichier excutable  partir d'un listing 
     contenant du code source en assembleur.

 II) Premier programme en assembleur.

III) Deuxime exemple : afficher une fentre.

 IV) Troisime exemple: afficher en hexadcimal (conversion dcimale-Hexa)

  V) Conclusion

 Annexe: exemple de fichier .bat pour automatiser le processus de compilation.



     I ) Comment batir un fichier excutable  partir d'un listing
     -------------------------------------------------------------

Pour batir un programme, c'est  dire en ce qui nous concerne
un fichier avec l'extension ".exe", a partir d'un fichier contenant
des instructions crits en assembleur (celui-ci a l' extension ".asm")
Il faut procder en deux tapes:

On utilise tasm32.exe en premier, cela va nous batir un fichier
dont l'extension est ".obj"
Puis on utilise tlink32.exe pour obtenir notre fichier excutable.


Si vous voulez batir un programme appel monprog.exe  partir 
du fichier source monprog.asm, qui contient des instructions en
langage assembleur, vous pouvez procdez comme suit:

Vous mettez  tasm32.exe, tlink32.exe, import32.lib dans le mme
rpertoire que votre fichier monprog.asm  compiler.

Pour dbuter le plus simple est de tout faire dans une session Msdos
que vous avez ouvert apres le chargement de Windows.

Pour ceux qui savent ce qu'est le path, mettez les fichiers
necessaires  la cration du programme dans un rpertoire
qui est dans le path. 


Sur la ligne de commande dos, tapez:

tasm32.exe /m /ml monprog.asm

vous allez obtenir, si le listing ne contient pas d'erreurs
un fichier appel monprog.obj

/m et /ml sont des options de compilations.

/m signifie : une passe , parfois il sera ncessaire de remplacer par
/m2 ou /m3. Une passe signifie que tasm32 compile tout en une seule fois
En gnral l' option /m est suffisante.



/ml signifie que les majuscules et minuscules sont considres comme 
diffrentes par tasm32.

Cela veut dire par exemple que les mots:

Les chanes de caractres "MICROSOFT" et "mIcrOsofT" ne seront pas 
considrs comme identiques par tasm32.


Si tasm32 trouve une erreur il l'indique, en prcisant la ligne
o a t trouv l' erreur.

En cas d'erreur le fichier monprog.obj ne sera pas cr bien sr.
Il vous faut corriger l'erreur et recommencer cette tape.


Une fois le fichier monprog.obj  cr il faut taper la ligne de commande:

tlink32.exe /Tpe /aa /c monprog,monprog.exe,,import32.lib

Ce qui prcde doit tre tap tel quel c'est  dire, en respectant exactement 
les majuscules et minuscules pour les options.


les options utilises:

/Tpe indique que ce qui va tre construit est un fichier ".exe"

/aa  indique que l'on va utiliser les ressources mises 
      disposition du programmeur par Windows9x

/c  indique que l'on tient compte de la diffrence entre minuscules
    et majuscules 

monprog,monprog.exe indique qu' partir du fichier monprog.obj
                    on va batir le programme monprog.exe.

,,import32.lib est le fichier o tlink32 prend connaissance
               des ressources mises  disposition par Windows.
               Ce fichier est indispensable pour nos applications


 
     II) Premier programme en assembleur
     -----------------------------------

 Voici le listing d'un programme crit en assembleur, c'est un programme
 trs  simple puisqu'il ne fait rien!



 <-------------------Dbut-Couper ici-------------------------------->

  .386p               
  .model flat         


  .data              
  
   db 0              
                      
  .code

   extrn ExitProcess:Proc  

 
   DEBUT:


   push 0
   call ExitProcess
                       

   end DEBUT


  <---------------Fin-Couper ici------------------------------------->



  Si vous recopiez ce listing dans un fichier monprog.asm, la compilation 
  du  programme, en suivant la mthode indiquee, va crer un fichier 
  monprog.exe dont la taille est de 4096 octets.

  Commentaires sur le listing:

  .386p            indique que les instructions utilises appartiennent
 au jeu fournit par le processeur 80386 de intel
 Ces instructions sont bien sur excutables sur n'importe quel
 processeur de type pentium ou clone/compatible
 le p indique que le programme fonctionne en mode protg.
 Tous les programmes conus exclusivement pour windows
 fonctionnent de cette facon.

  .model flat      indique le modle mmoire utilis.
 Pour un programme Windows, la mmoire est un bloc qui peut faire jusqu'
 4 GiGa octets en thorie, chaque octet a une adresse. Une adresse mmoire
 est un groupe de 4 octets appel aussi double mot (DWORD).

 Chaque programme a son propre espace mmoire, deux programmes
 ne partagent pas le mme espace de travail.
  
 Pour avoir une idee approximative de la faon dont marche les choses,
 ouvrez deux sessions Msdos sous Windows simultanment, dmarrer un 
 programme Msdos dans l'une des fnetres, vous pourriez vrifier que 
 dans l'autre session le programme n'est pas dans la mmoire utilise
 par cette copie de Msdos!

 Les deux sessions Msdos s'ignorent superbement!
 
 
 

     
  .data            est la zone du listing ou vous devez declarer les variables
 qui seront initialiss pendant le droulement du programme.
 tasm32 ne permet pas de laisser cette partie vide
 Le "db 0" est l pour eviter ca.
 Cela signifie que la zone des donnes contient un octet initialis  0.  
   
     
     
  .code        est la zone du listing qui contient le code du programme 
 proprement dit.

 Si vous dclarez une variable dans cette partie et que celle ci
 est initialise au cours de l'excution du programme, vous allez obtenir
 une superbe erreur lorsque Windows va excuter votre code.

 Ce problme doit tre surmonter pour qu'un excutable puisse greffer
 son code dans un autre.

 Dans certaines conditions on peut rsoudre ce problme.
 On aurra l'occasion d'y revenir dans un prochain article.
 
     
 extrn ExitProcess:Proc       signifie que l'on va importer un sous-programme
 externe  notre listing qui est appel aussi API (Application Programming 
 Interface) dans notre programme.

La grande force de Windows est lie a la notion d'importer-exporter des
fonctions.

Pour viter qu'un fichier excutable contienne tout le code qui est rellement
ncessaire pour son bon fonctionnement, un fichier excutable IMPORTE
des fonctions d'autres modules de Windows qui sont en gnral des fichiers
.dll. Ce sont des librairies de fonctions qui sont EXPORTEES  l'attention
d'autres modules de Windows, un module tant un fichier qui contient du code.

L'IMPORTATION de ces fonctions se fait DYNAMIQUEMENT.
Cela veut dire que les modules qui EXPORTENT des APIs ne sont pas tous
prsents en mmoire  un moment donn.

Une dll est charge en mmoire lorsqu'un module qui est dja en mmoire
a besoin d'une fonction qu'elle EXPORTE.

Certaines .dll, comme kernel32.dll, EXPORTE des APIs qui sont trs souvent
utilises, elles rsident en permanence en mmoire.

Chaque dll regroupe des fonctions ddies  une tche.

Windows met a notre disposition des centaines d'API pour nous aider
 dvelopper des programmes.
     
ExitProcess est le nom d'une de ces APIs.
Remarquez bien la faon dont son nom est crit, car ne l'oubliez pas
les minuscules sont diffrentes des majuscules.

Si vous crivez exitprocess,  la place, dans le listing 
tasm32 et tlink32 seront incapables de crer le programme attendu.

N'ommtez pas non plus ":Proc", sinon vous allez voir apparatre l'cran
bleu d'erreur de Windows  l'excution du programme fraichement compil.

Comme dja indiqu, le fichier import32.lib est ncessaire pour que
l'importation de l'API se fasse dans notre programme.
     
ExitProcess sert  revenir  Windows c'est  dire  quitter
le programme qui appelle cet API.
 
Notez bien la facon de faire l'appel:

           push  0
           call ExitProcess

Le "push 0" sert  passer un paramtre  l'API ExitProcess
0 est considr comme un double mot ici .
"push 0" met la valeur 00 00 00 00 sur la pile.

La pile est un endroit que Windows met a notre disposition
dans le mmoire pour sauvegarder des valeurs 

Cette pile est comme une pile d'assiettes entasses les unes
sur les autres. Pour pouvoir rcuprer l'assiette qui est 
tout en bas de la pile, on doit enlever une par une les
assiettes du dessus.

l'instruction "push" permet de mettre sur le sommet de la pile
un nouvel lment .  
      

Ne chercher pas de label "ExitProcess:" dans le listing
il n'y en a pas, pour appeler un API, on utilise la syntaxe:
 
           "call Nom De L'api" 
 
Les paramtres utiliss par l'API sont passs  Windows dans un ordre
convenu par l'intermdiaire de la pile.


  
 Pour connaitre la liste des API , leur noms, les paramtres
 ncessaires  leur bonne excution et l'ordre dans lequel
 ceux ci doivent tre mis sur la pile, il vous faut une liste 
 de rfrence.

 le label "DEBUT:" et "end DEBUT" indiquent que votre code se
 trouve entre ces deux balises.

 Pour commencer  programmer, ce listing est un bon modle
 qui s'avre tres utile pour crire un programme.
 Vous pouvez le rutiliser pour crire vos propres applications.






     III ) Deuxime exemple: afficher une fentre
     --------------------------------------------
 
        
   
     <-----------------Dbut-Couper ici------------------------------>



     .386p
     
     .model flat


     .data

     Titre      db "mon programme",0                 ;titre de la fentre
     Message    db "Chouette une fentre!",0         ;message  afficher
     


     .code

     extrn MessageBoxA: Proc
     extrn ExitProcess: Proc
   

     DEBUT:
 
     push 0                                    ;style de la fentre
     push offset Titre 
     push offset Message
     push 0

     call MessageBoxA                          ;crer la fentre

     push 0                                    ;sortie du programme
     call ExitProcess

    
     end DEBUT

     <--------Fin---Couper ici--------------------------------------->


     Commentaires sur le listing:

     Si vous voulez ajouter des commentaires dans un listing
     utiliser le symbole ";" ce qui suit est ignor par tasm32
   
     Dans ce programme nous utilisons une API de plus, MessageBoxA.

     Cette API a besoin de quatre paramtres qui sont tous des doubles
     mots c'est  dire compos de 4 octets chacun.

     Le premier paramtre  passer est le "style", il indique de 
     quel type sera la fentre  afficher et quelle icne sera utilise
     parmi la liste des icones fournies par Windows.
     Ici, on a choisit une fentre simple, pas d'icne affiche.

     Le deuxieme paramtre est un pointeur vers le dbut de la chane
     de caractres qui compose le titre de la fentre.

     Remarquez que les chanes de caractres se terminent par l'octet
     0, pour pouvoir tre affiches. Le 0 indique la fin de la chane
     de caractres.
     Les " " sont indispensables, elles indiquent  tasm32 que ce qui est
     plac entre, est du texte.

     Noter bien que c'est l'instruction "push offset Titre" qui
     est utilis et pas "push [Titre]"
     C'est un pointeur vers le dbut d'une chaine de caractres 
     que requiert l'API, MessageBoxA et pas le contenu des 4 premiers 
     octets de cette chaine!

     Troisieme paramtre, c'est un pointeur vers la chaine de
     caractres qui contient le message  afficher.
      
     Le quatrieme paramtre est un handle qui indique quelle application
     est propritaire de cette fentre, 0 = aucun propritaire
     Un handle est en gnral un double mot, utilis par Windows
     pour son bon fonctionnement.
     Windows attribue des handles pour tout.
 

     IV) Troisime exemple: affichage hexadcimal.

     On veut crire un programme capable de visualiser dans une 
     fentre  le contenu du registre eax, en hexadcimal.

     Que signifie hexadcimal?  
     Il existe plusieurs systmes de numration possible pour compter.
      
       
     Le plus utilis est le systme dcimal.
     Il est dit dcimal car nous utilisons dix symboles pour crire un 
     nombre dans ce systme :

     0,1,2,3,4,5,6,7,8,9


     lorsque nous lisons 156 en fait nous avons  l'esprit 
     que:        
                 1 x  100
               + 5 x   10
               + 6 x    1
               ----------
               =      156

      Les chiffres 1,5,6 ont t utiliss pour crire ce nombre

      Tout ceci semble un peu stupide de faire cela mais lisez ce qui suit.


      En base 16, nous avons 16 symboles pour crire un nombre:
      0,1,2,3,4,5,6,7,8,9,A,B,C,E,F

      le nombre qui s'crit AB en base 16 a bien sur une criture en base 10.
      On veut faire cette conversion.

      Le tableau de conversion suivant est utile:



      hexadcimal       0  1  2  3  4  5  6  7  8  9  A   B   C   D   E   F 
      dcimal           0  1  2  3  4  5  6  7  8  9 10  11  12  13  14  15 

   
      A correspond  10 , multipli par 16 = 160
      B correspond  11 , multipli par  1 =  11
                                         -----                               
                                    total  = 171
     
      171 est l'criture dcimale de AB

      Pour convertir le nombre hexadecimal 17DE on fait de mme:

 
      1 correspond  1  , multipli par 16*16*16  =  4096
      7 correspond  7  , multipli par 16*16     =  1792
      D correspond  12 , multipli par 16        =   192
      E correspond  14 , multipli par 1         =    14
                                                 -------
                                        total     =  6094



      Pour distinguer l'criture d' un nombre crit en hexadcimal, de
      celle d'un nombre crit en dcimal on ajoute un h  ce nombre:ABh,17DEh
      C'est la faon retenue ,par dfaut par tasm pour distinguer l'criture
      des nombres.

      Par dfaut si "156" non suivi d'un "h" apparait dans un listing
      contenant des instructions en assembleur, tasm va supposer que 156 est
      l'criture dcimale d'un nombre. 

      Notez bien que 156h ,nombre crit en hexadcimal, ne s'crit pas
      156 en notation dcimale.

      En effet,  1   x  256 = 256
                 5   x   16 =  80
                 6   x    1 =   6
                            -----
                     total  = 342

      342 est l'criture dcimale de 156h

               
      
      Pour pouvoir crire notre programme nous avons besoin
      de lire un nombre crit en hexadcimal
      c'est a dire d'tre capable de savoir quels chiffres 
      hexadcimaux (0,1,..9,a,...,f) le composent.
 
      En dcimal pour lire le nombre 123 on fait comme suit:

      On divise 123 par 10 le quotient fait 12 le reste 3
      3 est le chiffre le plus  droite
      
      On divise 12  par 10 le quotient fait 1 le reste  2
      2 est le chiffre suivant prcdant

      On divise 1   par 10  le quotient fait 0 le reste  1
      1 est le chiffre le plus a gauche

      Tout ceci semble stupide, une fois de plus, mais lisez la suite.

      En base 16 il faut juste remplacer la division par 10
      par une division par 16 les restes successifs sont les
      chiffres en base 16 qui composent le nombre.



      Voici une manire de programmer ceci :
   

      mov eax,342  ;342 est le nombre qu'on veut voir afficher en hexadcimal

      mov ecx,10h  ;on met 16 dans le registre ecx               

      Chiffre:

      xor edx,edx  ;on met  zro  le registre edx
      
      div ecx      ;on divise edx:eax par ecx
                   ;le reste est dans edx, le quotient dans eax
                   ;le reste contient le chiffre Hexadcimal 

      or eax,eax   ;est ce que le quotient est nul? 
      jnz Chiffre  ;il n'est pas nul ,il y'a encore des chiffres
                   
 
      les valeurs successives de edx : 6,5,1
      sont les chiffres utiliss pour crire 342 en hexadcimal.
      342 a 156h pour criture hexadcimale.  
       

      Nous avons crit dans le paragraphe III) un programme qui crait une
      fentre. Le titre de la fentre tait: "mon programme".
      Je vous ai indiqu alors de ne pas oublier les guillemets.
      
      Les symboles:  m,o,n,p,r,a,m,e que nous utilisons ,nous autres 
      francais, pour orthographier les mots:"mon,programme" ne veulent 
      rien dire pour le microprocesseur de votre machine.
      Celui-ci ne sait lire que des valeurs hexadcimales.

      En fait, tasm32 traduit la chaine de caractre: "mon programme"
      en :
      
          6dh,6fh,6eh,20h,70hh,72h,6fh,67h,72h,61h,6dh,6dh,65h
 
      20h est utilis pour traduire l'espace entre les deux mots.


      En fait, toutes les lettres et les chiffres ont un code qui
      permet  Windows de les afficher  l' cran.

      Cette codification utilise les nombres 00h,01h,02h,..,ffh.C'est
      le code ASCII. Tous les ordinateurs quips de Windows
      comprennent cette codification.

      Nous, pour notre programme, nous avons besoin d'afficher les 
      caractres suivants:

      0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f

      les  valeurs ASCII correspondantes sont:
    
      Caractre      "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" 
      Code ASCII     30h,31h,32h,33h,34h,35h,36h,37h,38h,39h
      
     
      Caractre      "a" "b" "c" "d" "e" "f"
     Code ASCII     61h 62h 63h 64h 65h 66h


 Pour pouvoir afficher les caractres "0","1",....,"9","a",..."f" qui
 servent  crire un nombre en hexadcimal on peut penser 
 faire 16 tests:

 si le chiffre est  0  alors   30h est son code ASCII
 si le chiffre est  1  alors   31h est son code ASCII
         [...]
 si le chiffre est  f  alors   66h est son code ASCII 


 Mais si vous observez bien on peut faire autrement.
 Plus simplement on a:


 Pour obtenir le code ASCII d'un chiffre X Hexadcimal compris entre 0 et 9
 il suffit de faire l addition:
                                  X+30h

 Pour obtenir le code ASCII d'un chiffre Y Hexadcimal compris entre a et f
 il suffit de faire:
                                 Y+61h-0ah

 Pour Y=0ah on obtient bien: 0ah+61h-0ah=61h           

l'algorithme pour calculer le code ASCII d'un chiffre Hexadcimal est simple:

        soit Hexa ce chiffre
        si Hexa>=0Ah  faire CodeASCII=Hexa+61h-0ah
        sinon         faire CodeASCII=Hexa+30h

Le programme qui suit n'est pas indispensable pour la comprhension
des mthodes d'infection sous Win32.

Nammoins, la comprhension du systme d'criture binaire et surtout
hexadcimal est ncessaire pour programmer en assembleur.

Ce qui suit est un exemple de programme un peu plus labor que ceux dja
rencontrs. On peut crire un programme, plus court, accomplissant la mme 
tche, en utilisant une API supplmentaire, mais le code source ncessaire
est sans grande utilit pour notre sujet.



Voici le programme promis:




<----------------------Dbut--Couper ici---------------------------->


.386p
.model flat

.data


db 0        ;cet octet a une fonction qui se justifie dans ce qui suit
HEX_Message db 0,0,0,0,0,0,0
FIN_Message db 0
            db 0

.code

extrn ExitProcess:Proc
extrn MessageBoxA:Proc

DEBUT:


;Ce programme affiche le contenu de eax en notation Hexadcimale




lea esi,FIN_Message  ;esi contient un pointeur vers le dernier caractre
                     ;de la chaine qui va contenir la reprsentation
                     ;en code ASCII du nombre  afficher en Hexadcimal

mov eax,14789        ;valeur dont on veut connaitre l'criture hexadcimale

inc esi              ;ajouter 1  la valeur dans esi
mov ecx,10h          ;mettre 16 dans ecx


HEX_chiffre:         

dec esi              ;soustraire 1  la valeur dans esi
xor edx,edx          ;mettre  zero edx 
div ecx              ;division de edx:eax par ecx
                     ;le quotient est dans eax
                     ;le reste dans edx, edx contient la valeur du 
                     ;nombre hexa: 0  F
 
cmp eax,0ah          ;la valeur dans eax est gale ou plus grande que
jge Lettre           ;10? si oui aller au label Lettre 


add edx,30h           ;le chiffre est compris entre 0 et 9 
mov byte ptr [esi],dl ;la chaine de caractre est compltee avec le code
                      ;ASCII du chiffre Hexa lu
or eax,eax            ;eax est nul?
jnz HEX_chiffre       ;non? il reste des chiffres  lire
                      

Lettre:

add edx,61h-0ah       ;le chiffre lu est compris entre a et f  
mov byte ptr [esi],dl 
or eax,eax
jnz HEX_chiffre
       
 
;Afficher le rsultat


        push 0
        push offset Titre
        push offset Hex_Message
        push 0
        call MessageBoxA

;exit

        push 0
        call ExitProcess
      
end DEBUT
    

<-----------Fin--Couper ici----------------------------------------->
         
       

     V) Conclusion:
     --------------

J'espre que tout ceci vous aidera dans vos premiers pas dans la 
programmation de Windows en assembleur.

L'article qui devrait suivre celui-ci traitera de la faon de manipuler
des fichiers sous Windows (lecture, criture) en assembleur videmment!

     A bientot.
   


     Annexe:
     -------

Pour commencer  programmer en assembleur sous Windows9x vous avez besoin 
des programmes cits et de deux fichiers supplmentaires qui vont vous
faciliter la tche.

Un modle de listing, dans lequel vous allez ajouter
vos propres instructions pour crire vos programme; Un fichier bat
qui va vous viter de resaisir  chaque fois les options de compilation
pour compiler votre code source.



Voici un fichier bat possible:


copier ce qui suit dans un fichier que vous appellerez compile.bat

<----------------------Dbut--couper ici---------------------------->

   tasm32  /m /ml %1.asm
   tlink32 /Tpe /aa /c %1,%.exe,,import32.lib
   del %.obj
   del %.map 

<----------------------Fin--couper ici------------------------------>


Commentaires:


Vous devez avoir tasm32.exe, tlink32.exe, import32.lib et votre listing
dans le mme rpertoire (ou dans le mme sous-rpertoire).

Il faut taper :

                  compile.bat monprog

si vous voulez compiler un listing qui s'appelle monprog.asm


et non pas: 
                  compile.bat monprog.asm




