Prérequis

Hello ! o/

Je vais vous introduire le format ELF (Executable and Linkable Format) sous architecture Intel x86_64 qui est le format de fichier le plus populaire pour la conception d’un fichier exécutable sous système Unix-like. On va commencer par la base, c’est-à-dire comment vous, lecteur, vous pouvez concevoir un programme. Un programme peut vous apparaître comme ceci:

#include <stdio.h>
#include <stdlib.h>

int
main (int argc,
      char * argv [])
{
    if (argc > 1)
    {
        fprintf(stderr, "[!] Error: Usage: ./program\n");
        exit(EXIT_FAILURE);
    }
    fprintf(stdout, "Hello World !\n");
    return EXIT_SUCCESS;
}
$ gcc source.c -o program
$ ./program
Hello world !
$ ./program ARG
[!] Error: Usage: ./program

Par conséquent on peut dire que notre programme source est source.c et que le programme exécutable est program. Et lorsque nous utilisons la commande file, nous voyons que notre programme exécutable est bien de format ELF :).

Sans rentrer dans les détails, si on exécute strings sur program, voici la sortie qu’on obtient:

/lib64/ld-linux-x86-64.so.2
LE]l
libc.so.6
exit
stdout
stderr
fwrite
__cxa_finalize
__libc_start_main
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
u/UH
[]A\A]A^A_
[!] Error: Usage: ./program
Hello World !
;*3$"
GCC: (Debian 8.3.0-6) 8.3.0
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.7325
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
source.c
__FRAME_END__
__init_array_end
_DYNAMIC
__init_array_start
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__libc_csu_fini
_ITM_deregisterTMCloneTable
stdout@@GLIBC_2.2.5
_edata
__libc_start_main@@GLIBC_2.2.5
__data_start
__gmon_start__
__dso_handle
_IO_stdin_used
__libc_csu_init
__bss_start
main
exit@@GLIBC_2.2.5
fwrite@@GLIBC_2.2.5
__TMC_END__
_ITM_registerTMCloneTable
__cxa_finalize@@GLIBC_2.2.5
stderr@@GLIBC_2.2.5
.symtab
.strtab
.shstrtab
.interp
.note.ABI-tag
.note.gnu.build-id
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.got.plt
.data
.bss
.comment

Alors en effet, ceci est très étrange, on remarque que nos chaînes de caractères sont hardcodées (mises en brut) dans le programme exécutable, et qu’on reconnait quelques motifs:

Donc on peut faire quelques corrélations mais on remarque qu’on apprend pas beaucoup de choses.. Mais il est intéressant de voir que le contenu du programme exécutable encapsule le programme source.

Enfin, la seule chose que j’ajouterai à cette introduction, c’est le fait qu’un programme exécutable s’exécute sur le CPU, la mémoire chargée peut se situer physiquement en cache, en RAM, sur le DD ou autre, et le programme ne se charge pas dans un gros bloc d’adresses virtuelles, c’est divisé en plusieurs segments dans la mémoire.

La suite ici !