Introduction à l'ASM X86
Sommaire
Exécuter un appel système en assembleur
Appel Système
Ce qu'on appelle un appel système c'est par exemple open(..), write(..), exit() en C
L'intégralité des appels systèmes disponibles et leurs numéros associés sont disponibles dans le fichier :
/usr/include/asm/unistd_32.h /usr/include/asm/unistd_64.h
Les appels systèmes sont appelés en ASM par l'interruption int 0x80
Passer des arguments à un appel système
- EAX : Contient le numéro de l'appel système
- EBX : Première Argument
- ECX : Deuxième Argument
- EDX : Troisième Argument
- ESI : Quatrième Argument
- EDI : Cinquième Argument
Exemple
Ici nous allons appeler la fonction exit(0)
Le prototype C de la fonction exit est :
void _exit(int status);
Tout d'abord on donne le code n°1 (exit) au registre EAX :
movl $1,%eax // movl : permet de déplacer 32 bits (valeur d'un registre) et $1 permet d'affecter la valeur plutôt que l'adresse mémoire
Puis on remplis le statut de la fonction argument n°1 au registre EBX
movl $0,%ebx
Enfin l'interruption système
int $0x80
Programme final
.text .globl _start _start: movl $1,%eax movl $0,%ebx int $0x80
Pour compiler le fichier et le linker
as -o Exittest.o Exittest.s // puis ld -o Exittest Exittest.o
On peut observer les appels systèmes via la commandes strace :
strace ./Exittest
execve("./justExit", ["./justExit"], [/* 36 vars */]) = 0 write(0, NULL, 0 <unfinished ... exit status 0>
Exemple
Afficher un shell
;affichage-shell.asm
segment .data ;déclaration du segment des variables initialisées et globales
cheminshell db "/bin/sh0aaaabbbbb" ;db déclare une chaine de caractères
segment .text ;declaration du segment de code
global _start ;point d'entrée pour le format ELF
_start: ;here we go
mov eax,70 ;on met eax à 70 pour préparer l'appel à setreuid mov ebx,0 ;real uid 0 => root mov ecx,0 ;effective uid 0 => root int 0x80 ;Syscall 70
mov eax,0 ;on met 0 dans eax mov ebx,cheminshell ;on met l'adresse de cheminshell dans ebx mov [ebx+7],al ;on met le 0 (de eax) 7 caractères après le début de la chaîne ;en fait, on réécrit le 0 de la chaine avec un nul byte ;al occupe 1 byte mov [ebx+8],ebx ;on met l'addresse de la chaine 8 caractères après son début ;En fait, on réécrit aaaa par l'adresse de cheminshell mov [ebx+12],eax ;12 caractères après le début, on met les 4 bytes de eax ;en fait, on réécrit bbbb par 0x00000000 mov eax,11 ;on met eax à 11 pour préparer l'appel à execve lea ecx,[ebx+8] ;on charge l'adresse de (anciennement) aaaa dans ecx lea edx,[ebx+12] ;on charge l'adresse de (anciennement) bbbb dans edx int 0x80 ;Syscall 11
Pour compiler:
nasm affichage-shell.asm -o affichage-shell.o -f elf && ld -s affichage-shell.o -o affichage-shell && ./affichage-shell
sh-3.1$