/-----------------------------------------------------------------------\ 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 n‚cessaires … la compr‚hension et la r‚alisation 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 … d‚buter dans la programmation de Windows en assembleur. Mat‚riel n‚cessaire: 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 n‚cessaire, mais conseill‚: -Un d‚buggeur peut s'av‚rer trŠs utile , je vous conseille td32 pour d‚buter, mˆme si celui-ci s'avŠre ˆtre rapidement insuffisant … l'usage. si vous d‚cidez d'approfondir le sujet, optez pour softice. -Une liste document‚e des APIs (voir plus loin pour la signification de ce sigle) standard utilis‚es par Windows. En g‚n‚ral fournit avec tous les compilateurs (Vc++,c++ de Borland,..) qui produisent du code ex‚cutable sous Windows. Voila ce que vous trouverez dans cet article: I) Comment batir un fichier ex‚cutable … partir d'un listing contenant du code source en assembleur. II) Premier programme en assembleur. III) DeuxiŠme exemple : afficher une fenˆtre. IV) TroisiŠme exemple: afficher en hexad‚cimal (conversion d‚cimale-Hexa) V) Conclusion Annexe: exemple de fichier .bat pour automatiser le processus de compilation. I ) Comment batir un fichier ex‚cutable … 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 proc‚der 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 ex‚cutable. Si vous voulez batir un programme appel‚ monprog.exe … partir du fichier source monprog.asm, qui contient des instructions en langage assembleur, vous pouvez proc‚dez comme suit: Vous mettez tasm32.exe, tlink32.exe, import32.lib dans le mˆme r‚pertoire que votre fichier monprog.asm … compiler. Pour d‚buter 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 cr‚ation du programme dans un r‚pertoire 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 n‚cessaire de remplacer par /m2 ou /m3. Une passe signifie que tasm32 compile tout en une seule fois En g‚n‚ral l' option /m est suffisante. /ml signifie que les majuscules et minuscules sont consid‚r‚es comme diff‚rentes par tasm32. Cela veut dire par exemple que les mots: Les chaŒnes de caractŠres "MICROSOFT" et "mIcrOsofT" ne seront pas consid‚r‚s comme identiques par tasm32. Si tasm32 trouve une erreur il l'indique, en pr‚cisant la ligne o— a ‚t‚ trouv‚ l' erreur. En cas d'erreur le fichier monprog.obj ne sera pas cr‚‚ bien s–r. 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 pr‚cŠde doit ˆtre tap‚ tel quel c'est … dire, en respectant exactement les majuscules et minuscules pour les options. les options utilis‚es: /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 diff‚rence 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 trŠs simple puisqu'il ne fait rien! <-------------------D‚but-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 m‚thode indiqu‚ee, va cr‚er un fichier monprog.exe dont la taille est de 4096 octets. Commentaires sur le listing: .386p indique que les instructions utilis‚es appartiennent au jeu fournit par le processeur 80386 de intel Ces instructions sont bien sur ex‚cutables sur n'importe quel processeur de type pentium ou clone/compatible le p indique que le programme fonctionne en mode prot‚g‚. Tous les programmes con‡us exclusivement pour windows fonctionnent de cette facon. .model flat indique le modŠle m‚moire utilis‚. Pour un programme Windows, la m‚moire est un bloc qui peut faire jusqu'… 4 GiGa octets en th‚orie, chaque octet a une adresse. Une adresse m‚moire est un groupe de 4 octets appel‚ aussi double mot (DWORD). Chaque programme a son propre espace m‚moire, deux programmes ne partagent pas le mˆme espace de travail. Pour avoir une idee approximative de la fa‡on dont marche les choses, ouvrez deux sessions Msdos sous Windows simultan‚ment, d‚marrer un programme Msdos dans l'une des fˆnetres, vous pourriez v‚rifier que dans l'autre session le programme n'est pas dans la m‚moire utilis‚e 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 initialis‚s pendant le d‚roulement 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 donn‚es contient un octet initialis‚ … 0. .code est la zone du listing qui contient le code du programme proprement dit. Si vous d‚clarez une variable dans cette partie et que celle ci est initialis‚e au cours de l'ex‚cution du programme, vous allez obtenir une superbe erreur lorsque Windows va ex‚cuter votre code. Ce problŠme doit ˆtre surmonter pour qu'un ex‚cutable puisse greffer son code dans un autre. Dans certaines conditions on peut r‚soudre ce problŠme. 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 li‚e a la notion d'importer-exporter des fonctions. Pour ‚viter qu'un fichier ex‚cutable contienne tout le code qui est r‚ellement n‚cessaire pour son bon fonctionnement, un fichier ex‚cutable IMPORTE des fonctions d'autres modules de Windows qui sont en g‚n‚ral 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 pr‚sents en m‚moire … un moment donn‚. Une dll est charg‚e en m‚moire lorsqu'un module qui est d‚ja en m‚moire a besoin d'une fonction qu'elle EXPORTE. Certaines .dll, comme kernel32.dll, EXPORTE des APIs qui sont trŠs souvent utilis‚es, elles r‚sident en permanence en m‚moire. Chaque dll regroupe des fonctions d‚di‚es … une tƒche. Windows met a notre disposition des centaines d'API pour nous aider … d‚velopper des programmes. ExitProcess est le nom d'une de ces APIs. Remarquez bien la fa‡on dont son nom est ‚crit, car ne l'oubliez pas les minuscules sont diff‚rentes des majuscules. Si vous ‚crivez exitprocess, … la place, dans le listing tasm32 et tlink32 seront incapables de cr‚er le programme attendu. N'omm‚tez pas non plus ":Proc", sinon vous allez voir apparaŒtre l'‚cran bleu d'erreur de Windows … l'ex‚cution du programme fraichement compil‚. Comme d‚ja indiqu‚, le fichier import32.lib est n‚cessaire 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 paramŠtre … l'API ExitProcess 0 est consid‚r‚ 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 m‚moire pour sauvegarder des valeurs Cette pile est comme une pile d'assiettes entass‚es les unes sur les autres. Pour pouvoir r‚cup‚rer 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 ‚l‚ment . 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 paramŠtres utilis‚s par l'API sont pass‚s … Windows dans un ordre convenu par l'interm‚diaire de la pile. Pour connaitre la liste des API , leur noms, les paramŠtres n‚cessaires … leur bonne ex‚cution et l'ordre dans lequel ceux ci doivent ˆtre mis sur la pile, il vous faut une liste de r‚f‚rence. le label "DEBUT:" et "end DEBUT" indiquent que votre code se trouve entre ces deux balises. Pour commencer … programmer, ce listing est un bon modŠle qui s'avŠre tres utile pour ‚crire un programme. Vous pouvez le r‚utiliser pour ‚crire vos propres applications. III ) DeuxiŠme exemple: afficher une fenˆtre -------------------------------------------- <-----------------D‚but-Couper ici------------------------------> .386p .model flat .data Titre db "mon programme",0 ;titre de la fenˆtre Message db "Chouette une fenˆtre!",0 ;message … afficher .code extrn MessageBoxA: Proc extrn ExitProcess: Proc DEBUT: push 0 ;style de la fenˆtre push offset Titre push offset Message push 0 call MessageBoxA ;cr‚er la fenˆtre 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 paramŠtres qui sont tous des doubles mots c'est … dire compos‚ de 4 octets chacun. Le premier paramŠtre … passer est le "style", il indique de quel type sera la fenˆtre … afficher et quelle ic“ne sera utilis‚e parmi la liste des icones fournies par Windows. Ici, on a choisit une fenˆtre simple, pas d'ic“ne affich‚e. Le deuxieme paramŠtre est un pointeur vers le d‚but de la chaŒne de caractŠres qui compose le titre de la fenˆtre. Remarquez que les chaŒnes de caractŠres se terminent par l'octet 0, pour pouvoir ˆtre affich‚es. Le 0 indique la fin de la chaŒne de caractŠres. 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 d‚but d'une chaine de caractŠres que requiert l'API, MessageBoxA et pas le contenu des 4 premiers octets de cette chaine! Troisieme paramŠtre, c'est un pointeur vers la chaine de caractŠres qui contient le message … afficher. Le quatrieme paramŠtre est un handle qui indique quelle application est propri‚taire de cette fenˆtre, 0 = aucun propri‚taire Un handle est en g‚n‚ral un double mot, utilis‚ par Windows pour son bon fonctionnement. Windows attribue des handles pour tout. IV) TroisiŠme exemple: affichage hexad‚cimal. On veut ‚crire un programme capable de visualiser dans une fenˆtre le contenu du registre eax, en hexad‚cimal. Que signifie hexad‚cimal? Il existe plusieurs systŠmes de num‚ration possible pour compter. Le plus utilis‚ est le systŠme d‚cimal. Il est dit d‚cimal car nous utilisons dix symboles pour ‚crire un nombre dans ce systŠme : 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‚ utilis‚s 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: hexad‚cimal 0 1 2 3 4 5 6 7 8 9 A B C D E F d‚cimal 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 d‚cimale de AB Pour convertir le nombre hexadecimal 17DE on fait de mˆme: 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 hexad‚cimal, de celle d'un nombre ‚crit en d‚cimal on ajoute un h … ce nombre:ABh,17DEh C'est la fa‡on retenue ,par d‚faut par tasm pour distinguer l'‚criture des nombres. Par d‚faut si "156" non suivi d'un "h" apparait dans un listing contenant des instructions en assembleur, tasm va supposer que 156 est l'‚criture d‚cimale d'un nombre. Notez bien que 156h ,nombre ‚crit en hexad‚cimal, ne s'‚crit pas 156 en notation d‚cimale. En effet, 1 x 256 = 256 5 x 16 = 80 6 x 1 = 6 ----- total = 342 342 est l'‚criture d‚cimale de 156h Pour pouvoir ‚crire notre programme nous avons besoin de lire un nombre ‚crit en hexad‚cimal c'est a dire d'ˆtre capable de savoir quels chiffres hexad‚cimaux (0,1,..9,a,...,f) le composent. En d‚cimal 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 pr‚c‚dant 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 maniŠre de programmer ceci : mov eax,342 ;342 est le nombre qu'on veut voir afficher en hexad‚cimal mov ecx,10h ;on met 16 dans le registre ecx Chiffre: xor edx,edx ;on met … z‚ro 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 Hexad‚cimal 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 utilis‚s pour ‚crire 342 en hexad‚cimal. 342 a 156h pour ‚criture hexad‚cimale. Nous avons ‚crit dans le paragraphe III) un programme qui cr‚ait une fenˆtre. Le titre de la fenˆtre ‚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 hexad‚cimales. En fait, tasm32 traduit la chaine de caractŠre: "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 ‚quip‚s de Windows comprennent cette codification. Nous, pour notre programme, nous avons besoin d'afficher les caractŠres suivants: 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f les valeurs ASCII correspondantes sont: CaractŠre "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" Code ASCII 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h CaractŠre "a" "b" "c" "d" "e" "f" Code ASCII 61h 62h 63h 64h 65h 66h Pour pouvoir afficher les caractŠres "0","1",....,"9","a",..."f" qui servent … ‚crire un nombre en hexad‚cimal 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 Hexad‚cimal compris entre 0 et 9 il suffit de faire l addition: X+30h Pour obtenir le code ASCII d'un chiffre Y Hexad‚cimal 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 Hexad‚cimal 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 compr‚hension des m‚thodes d'infection sous Win32. N‚ammoins, la compr‚hension du systŠme d'‚criture binaire et surtout hexad‚cimal est n‚cessaire pour programmer en assembleur. Ce qui suit est un exemple de programme un peu plus ‚labor‚ que ceux d‚ja rencontr‚s. On peut ‚crire un programme, plus court, accomplissant la mˆme tƒche, en utilisant une API suppl‚mentaire, mais le code source n‚cessaire est sans grande utilit‚ pour notre sujet. Voici le programme promis: <----------------------D‚but--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 Hexad‚cimale lea esi,FIN_Message ;esi contient un pointeur vers le dernier caractŠre ;de la chaine qui va contenir la repr‚sentation ;en code ASCII du nombre … afficher en Hexad‚cimal mov eax,14789 ;valeur dont on veut connaitre l'‚criture hexad‚cimale 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 caractŠre est compl‚tee 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 r‚sultat 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'espŠre 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 fa‡on 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 cit‚s et de deux fichiers suppl‚mentaires qui vont vous faciliter la tƒche. Un modŠle 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 <----------------------D‚but--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 mˆme r‚pertoire (ou dans le mˆme sous-r‚pertoire). Il faut taper : compile.bat monprog si vous voulez compiler un listing qui s'appelle monprog.asm et non pas: compile.bat monprog.asm