Introduction à l'assembleur x86 ( ASM )

 

Un peut d'histoire... :

John Von Neuman, tout repose sur cette personne. Considéré comme le plus grand génie de ce siècle (certains de ses amis et proches pensaient même que s'était un extra-terrestre qui avait pris une apparence humaine). Il est le père de l'informatique moderne, c'est de lui que le cyber est né. A la base il voulait concevoir une machine capable de penser, il atteindra son but en 1946 en concevant un ordinateur digne de se nom, programmable et pouvant prendre certaines initiatives basique. Mais à l'époque ce n'était qu'un balbutiment, il continua ses travaux chez IBM qui lui doit beaucoup, c'est dans cette période qu'est adopter le "bit" comme unité de mesure de mémoire pour ordinateurs. Il fut aussi à l'origine de la finalisation de travaux mathématique sur la géneration aléatoire de nombres et autres systemes de probabilitées d'une complexité extrême, encore mal saisie de nos jours par les plus grands mathématiciens. Il s'eteind à Washington en février 1957 à l'âge de 53 ans.

J.VN ayant inventé le bit, tous les ordinateurs se programmaient bit par bit en binaire. Il fallait donc faire de fastidieuses convertions pour réussir à faire des instructions correctes. C'est par cette difficulté à former un programme que des ingenieurs des laboratoires Bell (à qui l'on doit aussi le C le C++ quand à lui à été crée par Bjarné Stroustrup) ont crée l'assembleur. Ce language permettrai d'assembler differentes instructions avec des mots clés basiques pour former un programme en programmant la machine directement mais de façon plus lisible et compréhensible pour pouvoir developper un programme et de le mettre plus facilement à jour. L'assembleur etait né...

Dans ce cours qui s'etendra sur plusieurs numéros, nous allond étudier l'assembleur, appelé courament asm.

 

Résumé sur l'asm :

L'assembleur est un language de très bas niveau, très proche de la machine, on appelle ca un language machine tout simplement. C'est le language de plus bas niveau qui existe. C'est pour cette raison qu'il presente plusieurs avantages :

 

Hardware :

Comme nous l'avons vu, l'assembleur est un language machine pour savoir s'en servir il faut connaitre un minimum sont anatomie, à la machine... :

  1. traiter les données venant de la mémoire
  2. contenir les adresses de début de programme, de données, de macro-codes, etc...
  3. accumuler des données pour leurs traitement
  4. etc,etc....

Il existe 8 registres courant :

  1. L'Accumulateur : EAX } 32 bits / AX } 16 bits / AH et AL } 8 bits
  2. La Base : EBX } 32 bits / BX } 16 bits / BH et BL } 8 bits
  3. Le Compteur : ECX } 32 bits / CX } 16 bits / CH et CL } 8 bits
  4. Les Données : EDX } 32 bits / DX } 16 bits / DH et DL } 8 bits
  5. L' Index de source : ESI } 32 bits / SI } 16 bits
  6. L' Index de destination : EDI } 32 bits / DX } 16 bits
  7. Le pointeur de pile (stack) : ESP } 32 bits / SP } 16 bits
  8. Le pointeur de base : EBP } 32 bits / BP } 16 bits

A l'origine, les registres courant étaient AX,BX,SP, etc... mais avant l'étendue à 32 bits. On ajoute donc E devant pour dire Extended, soit EAX = Accumulateur étendu.

Comme on peut le voir, les quatres registre AX, BX, CX et DX peuvent être divisés en deux sous-registres de 8 bits, l'octect de poids fort étant indiqué par la lettre H (Hight) et celui de poid faible par la lettre L (Low). De cette menière on peut manipuler juste un morceau de registre mais le restant ne sera pas indépendant, par exmple si l'on touche à AL, les registres EAX et AX s'en veront aussi modifier mais AH et AX resteront indépendants.

 

Passons au code source :

Tout d'abord je tiens à remercier vivement Kheo pour m'avoir aider à terminer ce patcheur!

Je remerci aussi Neo BerSerKeR pour l'ASCII :)

Dans ce sode source vous ne comprendrez pas grand chose (si cous êtes debutant) mais il sera commenté dans les endroits clefs.

Voilà le source, pour le compiler vous aurez besoin du Tasm; de ses fichier Tasm.exe et Tlink.exe. Le fichier de compilation est fourni ici avec le code source. Comme d' habitude tout ce qui est en rouge peut être modifier sans problemes :

----------------------------------------[ Début ]----------------------------------------

;code source Alpha et finalisations: Static REvenge 
; moteur du patch revus et corrigé par Kheo 
.MODEL TINY
.CODE
.486
ORG 100h
;Déclaration de fichier com
;Ici ORG 100h définit l'adresse ou la 1ere instruction du programme va se placer
;Par conséquent qi vous débugger ce prog, la première instruction sera en XXXX:0100

start: jmp main

;------------------------[Zone à modifier]------------------------------*

Nick                 equ     " Kheo & Static REvenge "     ; Ton nick (respecte l'espace entre chaque guillement)
Nom_du_prog          equ     " Progdemerde v1.0 "          ; Le nom du prog cracké
Type_de_patch        equ     " Full !! "                   ; Met ici ce que fait ton patch

filename 	db "Progz.exe",0                           ; Nom du fichier à patcher
nb_blocs 	equ 3 				           ; Nombre de blocs à changer, ici 2
patch_ptr0 	equ 0487Eh    ,488Eh ,4880h  	           ; Offset des octets à patcher
new_val0 	equ 0FFh,0FFh ,0FFh  ,033h,033h,033h,033h  ; Nouvelles valeurs a patcher. Toujours mettre un 0 avant la valeur sinon sa plante avec les caratères alpha. Exemple => ne pas mettre EBh mais 0EBh. PS: le mieux et quand même de toujours mettre 0 pour + le clareté 
long_bloc0 	equ 2         ,1     ,4			   ; Longueur le chaque chaîne, MAX = 65535
taille 		equ 458752 				   ; Ecrire ici la taille exacte du fichier à patcher (en octets)!

texte   db "                             ²",0dh,0ah
        db "                           ²²Û",0dh,0ah
        db "                         ²²²Û",0dh,0ah
        db "         ²²²²²²²       ²²²²Û                 ²²²²²²²",0dh,0ah
        db "        ²²²²²²²Û     ²²²²²Û                 ²²²²²²²Û",0dh,0ah
        db "       ²²²²ÛÛÛÛ   ²²²²²²²Û                  ÛÛ²²²²Û",0dh,0ah
        db "      ²²²²Û     ²²²²²²²²Û                    ²²²²Û",0dh,0ah
        db "     ²²²²Û    ²²²²²²²²²Û    ²²²²²²²²²²²²    ²²²²Û",0dh,0ah
        db "    ²²²²Û   ²²²²²²²²²²²²²² ²²²²²²²²²²²²Û   ²²²²Û°°°°° Û°°°°°°°°°°°  Û°°°°°°°°°",0dh,0ah
        db "   ²²²²Û  ²²²²²²²²²²²²²²²Û²²²²²ÛÛÛÛÛÛÛÛ   ²²²²Û°°°°°° Û°°°°°°°°°°°° Û°°°°°°°°°°",0dh,0ah
        db "  ²²²²²²² ÛÛÛÛÛ²²²²²²²²²Û²²²²²Û       ²²²²²²²Û ÛÛ°°°° Û°°ÛÛÛÛÛÛÛ°°° Û°°°°ÛÛÛÛ°°",0dh,0ah
        db " ²²²²²²²Û     ²²²²²²²²ÛÛ²²²²²Û       ²²²²²²²Û   Û°°°° Û°°°°°°°°°°°° Û°°°°°°°°°°",0dh,0ah
        db " ÛÛÛÛÛÛÛ     ²²²²²²²ÛÛ ²²²²²Û        ÛÛÛÛÛÛÛ    Û°°°° Û°°°°°°°°°°ÛÛ Û°°°°°°°°°Û",0dh,0ah
        db "            ²²²²²²ÛÛ  ²²²²²Û           Û°°°°    Û°°°° Û°°° Û°°°°Û   Û°°°°°ÛÛÛÛ",0dh,0ah
        db "           ²²²²²ÛÛ   ²²²²²²²²²²²²      Û°°°°°°°°°°°°° Û°°°  Û°°°°   Û°°°°",0dh,0ah
        db "          ²²²²ÛÛ    ²²²²²²²²²²²²Û      Û°°°°°°°°°°°°° Û°°°   Û°°°°  Û°°°°",0dh,0ah
        db "         ²²²ÛÛ      ÛÛÛÛÛÛÛÛÛÛÛÛ       ÛÛÛÛÛÛÛÛÛÛÛÛÛÛ ÛÛÛÛ    ÛÛÛÛ  ÛÛÛÛÛ  N.B",0dh,0ah
        db "        ²²ÛÛ",0dh,0ah
        db "       ²ÛÛ",0dh,0ah
        db "       Û",0dh,0ah




;-----------------------------------------------------------------------*

        db "			Crack for  : ",Nom_du_prog,"",0dh,0ah
	db "			Crack type : ",Type_de_patch,"",0dh,0ah
	db "			Cracked by : ",Nick,"",0dh,0ah,"$"

done 	db "CraCk SuccSessFuL!",0dh,0ah,"$"

error 	db "An error as appear!",0dh,0ah,"$"
Error1 	db 0dh,0ah,"Erreur : le fichier a patcher ne fait pas la bonne taille !",0dh,0ah,"$"
Error2 	db 0dh,0ah,"Erreur : le fichier a patcher est introuvable !",0dh,0ah,"$"


;-------------------------[NE PAS MODIFIER A LA SUITE!]----------------------------*
handle dw 0
patch_ptr 	dd patch_ptr0 
new_val 	db new_val0 
long_bloc 	dw long_bloc0 
cmpt 		db 0
ptr_val 	dw 0
ptr_patch 	dw 0
ptr_long 	dw 0

;-----------------------------------------------------------------------* 

main:

  mov ah, 9
  lea dx, texte 
  int 21h
; affichage d'une chaine de caractère.

  call openfile
  call patch
  call closefile

  mov ax, 4C00h
  int 21h
; le programme se fini ici si tout c'est bien passé !

openfile:
; Cette procédure permet d'ouvrir le fichier et de retourner le handle de celui ci dans [handle]
; Si le fichier ne peut etre ouvert alors elle envoie un message d'erreur et termine le programme
; enfin elle teste la taille du fichier de manière à pas se tromper .

  mov ax, 4300h
  lea dx, filename
  int 21h
  jc erreur2
; lecture des attribut du fichier. Permet de savoir s'il existe ...
;OUT:
; ecx contient ces attribut
; si erreur alors CF = 1

  mov ah, 3Dh
  mov al, 11000010b
  lea dx, filename
  int 21h
  jc erreur
; Ouvre un fichier
;IN:
; AL mode d'acces
;OUT:
; CF = 1 -> error
; CF=0 -> AX= handle du fichier

  mov [handle],ax

  mov ah, 42h
  mov al, 02h
  mov bx, [handle]
  xor cx, cx
  xor dx, dx
  int 21h
; ici j'appelle la fonction pour deplacer le pointeur dans le fichier.
; al=2 -> je me refère par rapport à la fin du file et je met 0 0 cx, dx
; de cette manière l'int 2 va positionner le ptr à la fin du fichier et
; me renvoyer ca taille dans dx,ax


  xor bx, bx
  mov bx, dx
  imul ebx, 010000h
  mov bx, ax
; ici je recupère la taille et je la passe sur un registre 32 bits
; pour pouvoir la comparer avec la variable taille

  cmp ebx, taille
  jnz erreur1
; Si ca n'est pas egal alors erreur !
  ret

closefile:

  mov ax, 3E00h
  mov bx, [handle]
  Int 21h
; ferme le fichier et libère le handle 
  jc erreur
  ret

;-------------------------- Gestion des erreurs ------------------------*

erreur2:
  lea dx, error2
  jmp er
erreur1:
  lea dx, error1
  jmp er
erreur:
  lea dx, error
  jmp er

er:
  mov ah, 9 
  int 21h 

; affiche un message d'erreur
  mov ax, 4C01h
  int 21h
; termine le prog avec le code d'erreur 1


;-------------------- Routine d'ecriture du patch ----------------------*
patch:

  mov ptr_val, offset new_val
  mov ptr_patch, offset patch_ptr
  mov ptr_long, offset long_bloc
; recupère les adresse des variables, de manière à pouvoir les incrémenter pour pointer plus loin

bc:
  mov ah, 42h
  xor al, al
  mov bx, [handle]
  mov si, ptr_patch
  mov dx, [si]
  add si, 2
  mov cx, [si]
  int 21h
; deplace le pointeur dans le fichier
;IN:
; cx = poid fort & dx = poid faible
;OUT:
; ax = poid faible & dx = poid fort

; attention en mémoire on lis de gauche à droite, donc le poid faible se lit en premier !
  mov si, ptr_patch
  cmp ax, [si]
  jnz erreur
  add si, 2
  cmp dx, [si]
  jnz erreur
; vérifie si la position dans le fichier est celle voulue ?

  mov ah, 40h
  mov bx, [handle]
  mov si, ptr_long
  mov cx, [si]
  mov si, ptr_val
  mov dx, si
  int 21h
; ici j'écris dans le fichier représenté par le handle [handle] à l'adresse on l'on vient de positionner le ptr
; cx contenant la longueur, le nb de byte à ecrire et ds:dx le ptr sur les byte à ecrire

  inc [cmpt]
  cmp [cmpt],nb_blocs
  jz wrt_ok
; permet de savoir si tout les bytes on été modifié grace à nb_blocs
; etant donné que l'ecriture dans le ficher se fait par blocs de X byte alors il
; faut comparer mon compteur cmpt et nb_bloc

  add ptr_val,cx
  add ptr_patch,4
  add ptr_long,2
; cette partie de code permet de modifier les ptr de manière à ce que la boucle
; modifie les prochains bytes
  jmp bc

wrt_ok:

  mov ah, 9
  lea dx, done
  int 21h 
; affiche le message nous informant que le crack a fonctionné .

  ret

end start

 

----------------------------------------[ Fin ]-----------------------------------------

 

C'est bon, avec ce programme vous pourrez créer des patchs portables, compatibles Windows et vous pourrez mettre de supers ASCII :)

Bien sur, l'assembleur peut parraître fastidieux mais avec un peut de temps et de pratique on se rend vite compte que c'est un language assez simple à mettre en oeuvre pour faire de petits programmes.

Si vous voulez en savoir plus je vais vous conseillez quelques bouquins et liens :

 

See ÿA!