Salut les gens !
Oui oui, vous l'aurez deviné, je présente (façon de parler) ici un truc que je viens de coder : un filesystem FUSE au-dessus des fichiers au format ELF.
Bon alors là, tout de suite, logiquement vous me dites "euh ok c'est bien gentil ton truc mais ça sert à quoi ?", ce à quoi je réponds "rien !". Plus sérieusement, ça sert à se faire un peu la main sur FUSE (donc vous pouvez regarder le code pour vous faire une idée, j'ose espérer qu'il n'est pas trop cracra). Ça peut également servir à des fins pédagogiques : voir la structure d'un fichier ELF, tout ça...
Bon, le but avoué, c'est qu'à terme, on puisse modifier un binaire, ou carrément un processus en cours via le point de montage. Par exemple en faisant un truc du genre :
echo 0x424242 > /mnt/elf/entrypoint sed -i "s:generic_func:myhook_func:g" /mnt/elf/symbols
Ou autres trucs du genre ! Amusant non ? Non ? Bon.. ok... j'retourne coder d'autres crottes en silence...
Sinon pour l'instant on peut juste faire 2-3 trucs en read-only:
- monter un binaire sur disque ou un process en cours d'exécution (expérimental, tout ça...)
$ elfs /usr/bin/screen /mnt/elf ou $ sudo elfs -p $(pidof screen) /mnt/elf
- lister les lib (répertoire /mnt/elf/libs/)
$ ls -l /mnt/elf/libs total 0 -rwxrwxrwx 0 root root 9 1970-01-01 01:00 libc.so.6 -rwxrwxrwx 0 root root 9 1970-01-01 01:00 libm.so.6 -rwxrwxrwx 0 root root 11 1970-01-01 01:00 libX11.so.6 -rwxrwxrwx 0 root root 11 1970-01-01 01:00 libXaw.so.7 -rwxrwxrwx 0 root root 11 1970-01-01 01:00 libXft.so.2 -rwxrwxrwx 0 root root 15 1970-01-01 01:00 libxkbfile.so.1 -rwxrwxrwx 0 root root 11 1970-01-01 01:00 libXmu.so.6 -rwxrwxrwx 0 root root 15 1970-01-01 01:00 libXrender.so.1 -rwxrwxrwx 0 root root 10 1970-01-01 01:00 libXt.so.6
- visualiser le header ELF à-la readelf -h (fichier /mnt/elf/info)
$ cat /mnt/elf/info Ident: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Version: 1 Class: 64 Type: EXEC (Executable file) Version: 1 ELF Header size: 64 bytes Entry point: 0x402550 Program Header offset: 64 bytes Program Header entry size: 56 bytes Number of Program Header entries: 9 Section Header offset: 40768 bytes Section Header entry size: 64 bytes Number of Section Header entries: 28 SH string table index: 27
- lister les sections, dans /mnt/elf/sections : bss, data, symtab, dynsym, etc
$ ls -l /mnt/elf/sections/ total 0 drw------- 1 root root 0 1970-01-01 01:00 bss drw------- 1 root root 0 1970-01-01 01:00 ctors drw------- 1 root root 0 1970-01-01 01:00 data drw------- 1 root root 0 1970-01-01 01:00 dtors drw------- 1 root root 0 1970-01-01 01:00 dynamic dr-------- 1 root root 0 1970-01-01 01:00 dynstr dr-------- 1 root root 0 1970-01-01 01:00 dynsym [...]
- lister les symboles dans /mnt/elf/sections/symtab et /mnt/elf/sections/dynsym
$ ls -l /mnt/elf/sections/dynsym/|tail -5 d--------- 1 root root 0 1970-01-01 01:00 XtStrings d--------- 1 root root 0 1970-01-01 01:00 XtWidgetToApplicationContext d--------- 1 root root 0 1970-01-01 01:00 XtWindow d--------- 1 root root 0 1970-01-01 01:00 XtWindowOfObject d--------- 1 root root 0 1970-01-01 01:00 XUnionRectWithRegion
- pour chaque symbole, lire ses infos (STT_FUNC, etc) et son code, au format binaire ou asm (code.bin et code.asm)... mieux vaut que le binaire soit compilé en debug, ou du moins avec les symboles, et non stripé, sinon vous allez vous retrouvez en galère d'infos
$ ls -l /mnt/elf/sections/symtab/dup_regex_free/ total 0 ---------- 0 root root 363 1970-01-01 01:00 code.asm ---------- 0 root root 78 1970-01-01 01:00 code.bin ---------- 0 root root 69 1970-01-01 01:00 info $ cat /mnt/elf/sections/symtab/dup_regex_free/code.asm push rbp mov rbp, rsp sub rsp, 0x10 mov [rbp-0x8], rdi mov rax, [rbp-0x8] mov rax, [rax+0x48] test rax, rax jz 0x35 mov rax, [rbp-0x8] mov rax, [rax+0x48] mov rdi, rax call dword 0xfffffd9c mov rax, [rbp-0x8] mov qword [rax+0x48], 0x0 mov rax, [rbp-0x8] mov eax, [rax+0x50] test eax, eax jz 0x4c mov rax, [rbp-0x8] mov rdi, rax call dword 0xfffffeac leave ret
Ouala pour l'instant c'est tout....
J'essaie d'ajouter des trucs quand j'ai le temps mais bon, d'une part j'suis pas mal occupé à faire des trucs pas intéressants, et en plus je code comme une buse et à la lenteur d'un cloporte arthritique, c'est pas gagné...
Le code : c'est par ici !
Bref, see ya dudes!
Ah j'oubliais un truc important : c'est Linux-only... hey ouais, j'ai pas trouvé de truc plus malin que checker /proc/pid/exe pour avoir l'adresse de mapping du binaire depuis le PID. On me souffle dans l'oreille de faire des trucs sioux avec ptrace() + les registres, qui donnent un emplacement dans le code, puis checker en arrière les adresses modulo _sysconf(_SC_PAGESIZE) pour essayer de retomber sur les 4 bytes ELF_MAGIC du header. Plus tard plus tard... déjà on va essayer de faire en sorte que ça SIGSEGV pas trop :P
EDIT: hop, apparemment maintenant ça compile/tourne sous freebsd (j'ai pas pu tester mais le bon sbz m'a envoyé un patch qui fait le taff)
