Introduction au Reverse engineering
Présentation
Nofix
Qu'est ce que le Reverse engineering?
#include <stdio.h>
#include <stdlib.h>
void hello(char* str){
printf("%s\n", str);
}
int main(char** argv, int argc){
char* str = "Hello from the stack!";
hello(str);
return EXIT_SUCCESS;
}
Architectures
- x86
- x64-86
- ARM
- MIPS
Composition d'un programme
-
Processeur (registres)
-
Mémoire
Composition d'un programme
En x86 :
- EAX, ECX, EDX, EBX
- ESP, EBP
- ESI, EDI
- EIP (ou PC ou RIP pour Register Instruction Pointer)
Le proceseur
Registres processeur
32 bits | EAX |
16 bits | |
8 bits |
AX |
---|
AH | AL |
---|
Exemple de l'accumulateur (EAX)
mov eax, 4
mov al, 4
Les syntaxes
AT&T
INTEL
mov $5, %eax
mov eax, 5
movb $5, %eax
mov al, 5
Configuration
echo "set disassembly-flavor intel" >> ~/.gdbinit
echo "set pagination off" >> ~/.gdbinit
Le .gdbinit
La mémoire
Les segments
- Beaucoup de segments
- Repartis en plusieurs parties
$ readelf -l a.out
Correspondance section/segment :
Sections de segment...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym
.dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init
.plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got
La mémoire
- Beaucoup de segments
- Repartis en plusieurs parties
#include <stdio.h>
#include <stdlib.h>
char* strBss = "Hello from bss!"; //initialised -> .data section
int variable; //Not initialised -> .bss section
void hello(char* str){
printf("%s\n", str);
}
int main(char** argv, int argc){
char* str = "Hello from the stack!"; //Stack
char* strFromHeap = malloc(sizeof(char) * 21); //Heap
sprintf(strFromHeap, "Hello from the Heap!");
hello(str);
free(strFromHeap); //Always free() dynamically allocated var
return 1;
}
La mémoire
La pile et le tas
Quelques instructions essentielles
mov <destination> <source>
mov eax, 4 ;met la valeur 4 dans le registre EAX
add <destination> <source>
add eax, 4 ;ajoute 4 à EAX
sub <destination> <source>
push <source>
push eax ; pousse la valeur EAX sur la pile
pop <destination>
pop eax ; retire la dernière valeur de la pile et la place dans EAX
jmp <addr>
jmp eax ; jmp à l'adresse EAX (équivalent du GOTO)
Quelques instructions essentielles
mov <destination> <source>
mov eax, 4 ;met la valeur 4 dans le registre EAX
add <destination> <source>
add eax, 4 ;ajoute 4 à EAX
sub <destination> <source>
push <source>
push eax ; pousse la valeur EAX sur la pile
pop <destination>
pop eax ; retire la dernière valeur de la pile et la place dans EAX
jmp <addr>
jmp eax ; jmp à l'adresse EAX (équivalent du GOTO)
Autres accès aux valeurs
mov eax, [esp + 4]
;met la valeur à l'adresse pointé par ESP + 4 dans EAX
Les conditions en assembleur
mov <destination> <source>
mov eax, 4 ;met la valeur 4 dans le registre EAX
add <destination> <source>
add eax, 4 ;ajoute 4 à EAX
sub <destination> <source>
push <source>
push eax ; pousse la valeur EAX sur la pile
pop <destination>
pop eax ; retire la dernière valeur de la pile et la place dans EAX
jmp <addr>
jmp eax ; jmp à l'adresse EAX (équivalent du GOTO)
Retour à l'exemple
void hello(char* str){
printf("%s\n", str);
}
$ gcc example.c
$ peda a.out
gdb-peda$ disas hello
Dump of assembler code for function hello:
0x0804841d <+0>: push ebp
0x0804841e <+1>: mov ebp,esp ;On prépare la pile
0x08048420 <+3>: sub esp,0x18 ;On alloue de la place sur la pile
0x08048423 <+6>: mov eax,DWORD PTR [ebp+0x8]
0x08048426 <+9>: push eax ;On push le pointeur vers notre chaine
0x08048429 <+12>: call 0x80482f0 <puts@plt>;Appel à la fonction puts de libc
0x0804842e <+17>: leave
0x0804842f <+18>: ret
End of assembler dump.
void hello(char* str){
printf("%s\n", str);
}
push ebp
mov ebp,esp
sub esp,0x18
mov eax,DWORD PTR [ebp+0x8]
push eax
call 0x80482f0 <puts@plt>
leave
ret
Introduction au Reverse
By Nofix
Introduction au Reverse
- 344