首页 > 其他分享 >House of force以及相关例题学习

House of force以及相关例题学习

时间:2023-10-22 09:00:59浏览次数:39  
标签:malloc force House top fprintf stderr 例题 chunk size

学习于:

(1)https://bbs.kanxue.com/thread-262114.htm

(2):https://www.cnblogs.com/ZIKH26/articles/16533388.html

以及经典的wiki:https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/house-of-force/

(可能我的文章会与他们有部分重合因为我是一步步跟着调试进行,如有问题请联系我)

前言:

House of force是一种基于top chunk的攻击手法,是利用glibc2.23以及2.27对top chunk进行size的合法检查的漏洞演变而来的,如果malloc函数执行时发现没有任何的bins中的堆块能够满足需求,就会从top chunk中切下一块内存返回给malloc,如果我们可以修改top chunk的size那么我们就可以将top chunk的大小修改至任意位置,再申请就相当于是任意位置读写了

对top chunk的size位的检查的相关代码如下:

 1 // 获取当前的top chunk,并计算其对应的大小
 2 victim = av->top;
 3 size   = chunksize(victim);
 4 // 如果在分割之后,其大小仍然满足 chunk 的最小大小,那么就可以直接进行分割。
 5 if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE)) 
 6 {
 7     remainder_size = size - nb;
 8     remainder      = chunk_at_offset(victim, nb);
 9     av->top        = remainder;
10     set_head(victim, nb | PREV_INUSE |
11             (av != &main_arena ? NON_MAIN_ARENA : 0));
12     set_head(remainder, remainder_size | PREV_INUSE);
13 
14     check_malloced_chunk(av, victim, nb);
15     void *p = chunk2mem(victim);
16     alloc_perturb(p, bytes);
17     return p;
18 }

 

可以看到这一句比较语句

5 if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE)) 

 

size是一个((unsigned long) (size),如果我们给他修改成为-1,那么是不是就可以让size变成一个无限大的数字就可以通过比较了

how2heap例子:

 1 //patchelf --set-interpreter /home/yic/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ld-linux-x86-64.so.2 ./force
 2 //patchelf --set-rpath /home/yic/glibc-all-in-one/libs/2.23-0ubuntu3_amd64 ./force 
 3 //gcc -g force.c -no-pie -o force 
 4 #include <stdio.h>
 5 #include <stdint.h>
 6 #include <stdlib.h>
 7 #include <string.h>
 8 #include <stdint.h>
 9 #include <malloc.h>
10 char bss_var[] = "This is a string that we want to overwrite.";
11 
12 int main(int argc , char* argv[])
13 {
14     fprintf(stderr, "\n欢迎学习 House of Force\n\n");
15     fprintf(stderr, "House of Force 这种方法是去覆写 top chunk 这样 malloc 的时候就可以 malloc 到任意地址\n");
16     fprintf(stderr, "top chunk 是一类特殊的 chunk,在内存最后面。并且是当 malloc 向操作系统请求更多空间时将调整大小的块。\n");
17 
18     fprintf(stderr, "\n最后我们会覆盖这个变量 %p.\n", bss_var);
19     fprintf(stderr, "现在变量值是:%s\n", bss_var);
20 
21     fprintf(stderr, "\n先分配一个 chunk.\n");
22     intptr_t *p1 = malloc(256);
23     fprintf(stderr, "malloc(256) 的地址: %p.\n", p1 - 2);
24 
25     fprintf(stderr, "\n现在有两块,一个我们申请的,一个 top chunk.\n");
26     int real_size = malloc_usable_size(p1);
27     fprintf(stderr, "我们申请的 chunk 加上 chunk 头,大小是:%ld.\n", real_size + sizeof(long)*2);
28 
29     fprintf(stderr, "\n现在假设有一个漏洞,可以覆盖掉 top chunk 的头部分\n");
30 
31     intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size - sizeof(long));
32     fprintf(stderr, "\ntop chunk 起始地址是:%p\n", ptr_top);
33 
34     fprintf(stderr, "\n用一个很大的值覆盖掉 top chunk 的 size 位可以防止 malloc 调用 mmap\n");
35     fprintf(stderr, "top chunk 之前的 size:%#llx\n", *((unsigned long long int *)((char *)ptr_top + sizeof(long))));
36     *(intptr_t *)((char *)ptr_top + sizeof(long)) = -1;
37     fprintf(stderr, "top chunk 现在的 size:%#llx\n", *((unsigned long long int *)((char *)ptr_top + sizeof(long))));
38 
39     fprintf(stderr, "\n因为现在 top chunk 的 size 是很大的,所以我们可以调用 malloc 而不会调用 mmap\n");
40 
41     /*
42 * The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
43 * new_top = old_top + nb
44 * nb = new_top - old_top
45 * req + 2sizeof(long) = new_top - old_top
46 * req = new_top - old_top - 2sizeof(long)
47 * req = dest - 2sizeof(long) - old_top - 2sizeof(long)
48 * req = dest - old_top - 4*sizeof(long)
49 */
50     unsigned long evil_size = (unsigned long)bss_var - sizeof(long)*4 - (unsigned long)ptr_top;
51     fprintf(stderr, "\n我们想把数据写在这里:%p, top chunk 在:%p, 还要把 chunk 头算进去,我们将要申请 %#lx 字节.\n", bss_var, ptr_top, evil_size);
52     void *new_ptr = malloc(evil_size);
53     fprintf(stderr, "新申请的 chunk 将会与之前的 top chunk 在同一个位置: %p\n", new_ptr - sizeof(long)*2);
54 
55     void* ctr_chunk = malloc(100);
56     fprintf(stderr, "\n接下来再申请 chunk 的话将会指向我们想要修改的地方\n");
57     fprintf(stderr, "malloc(100) => %p!\n", ctr_chunk);
58     fprintf(stderr, "现在我们就可以控制 bss_var 这块地方的值了\n");
59 
60     fprintf(stderr, "... 之前内容是: %s\n", bss_var);
61     fprintf(stderr, "... 接下来把 \"YEAH!!!\" 写到那里...\n");
62     strcpy(ctr_chunk, "YEAH!!!");
63     fprintf(stderr, "... 新的内容: %s\n", bss_var);
64     // some further discussion:
65     //fprintf(stderr, "This controlled malloc will be called with a size parameter of evil_size = malloc_got_address - 8 - p2_guessed\n\n");
66     //fprintf(stderr, "This because the main_arena->top pointer is setted to current av->top + malloc_size "
67     //  "and we \nwant to set this result to the address of malloc_got_address-8\n\n");
68     //fprintf(stderr, "In order to do this we have malloc_got_address-8 = p2_guessed + evil_size\n\n");
69     //fprintf(stderr, "The av->top after this big malloc will be setted in this way to malloc_got_address-8\n\n");
70     //fprintf(stderr, "After that a new call to malloc will return av->top+8 ( +8 bytes for the header ),"
71     //  "\nand basically return a chunk at (malloc_got_address-8)+8 = malloc_got_address\n\n");
72 
73     //fprintf(stderr, "The large chunk with evil_size has been allocated here 0x%08x\n",p2);
74     //fprintf(stderr, "The main_arena value av->top has been setted to malloc_got_address-8=0x%08x\n",malloc_got_address);
75 
76     //fprintf(stderr, "This last malloc will be served from the remainder code and will return the av->top+8 injected before\n");
77 }

首先将断点下载第28行,申请了一个chunk,发现topchunk的位置是0x405110

再将断点下在38行,用-1进行绕过检查,将top chunk的size变成很大的数值

 36 *(intptr_t *)((char *)ptr_top + sizeof(long)) =-1;

 假设我们想要让 new_top的地址 到 0x404060,现在要让0x404060-0x20 =old_top的地址(0x405110) + size ,所以这个 size 应该是 0x404040-0x405110=0xffffffffffffef30,

也就是说只要申请 0xffffffffffffef30 大小的 chunk 就能把 top chunk的地址改到0x404060-0x10,然后我们再申请一个chunk的时候就是 0x404060 了

至于为什么减去了0x20呢,我们想要申请到 0x404060 的时候要留出它的 chunk 头有 0x10的大小, 这就是说 0x404060-0x10 = old_top+size,即 size = 0x404060-0x10 - old_top,但是还要注意,我们去malloc的时的 size 的时候实际上申请的是 size+0x10 大小的 chunk,还要把这个 0x10 留出来,则就是最后就是减去0x20(32位程序是减去0x10)

例题:gyctf_2020_force

一道很看起来很简略的题目,我修改了一些函数名和变量名令程序好看一些

main函数:

add函数:

put函数:

 你会发现,根本没有free函数,乐了,而且题目也给提示了,这题可以使用HOF,我们可以看到add函数中

我们可以申请任意大小的chunk却可以输入固定大小0x50字节的内容,如果我们申请小于0x50大小的chunk就可以造成溢出,具体的过程等调试完后继续写

标签:malloc,force,House,top,fprintf,stderr,例题,chunk,size
From: https://www.cnblogs.com/ModesL/p/17779888.html

相关文章

  • Codeforces Round 855 (Div. 3) C. Powering the Hero
    有\(n\)张卡的卡堆,你可以自顶向下抽卡。装备卡显示数值为\(a_i(a_i>0)\),英雄卡显示数值为\(a_i=0\)。如果是装备卡,你可以将卡抽出放在装备堆。如果是英雄卡,你可以将装备堆顶端的一张数值为\(x\)的装备卡装备给英雄,英雄数值\(+x\)。无论是否装备,都加入英雄堆。询问......
  • Codeforces Round 857 (Div. 2) B. Settlement of Guinea Pigs
    你非常喜欢豚鼠。每个笼子可以住两只豚鼠,且你不想把每个笼子放入不同性别的豚鼠。豚鼠只有两种性别。假设你买到豚鼠时并不知道性别,只有医生能够分辨。接下来的\(n\)天方案中,若第\(i\)天为\(1\),你买入一只豚鼠;若为\(2\),你请医生分辨你的豚鼠性别。给出方案,你最少需要准......
  • C语言经典例题加解析
    1、假设今天是星期三,编程求20天之后是星期几?#include<stdio.h>intmain(){intcurrentDay=3:1/假设今天是星期三,星期日为0,星期一为1,以此类推intdaysToAdd=20;/计算20天后的星期几intfutureDay=(currentDay+daysToAdd)%7;printf(~20天后是星期bd\n”,futureDay);......
  • Educational Codeforces Round 145 (Rated for Div. 2) B. Points on Plane
    给一个二维平面,你需要在上面放\(n\)个芯片。将一个芯片放在\((x,y)\)的代价为\(|x|+|y|\)。放\(n\)个代价的代价为,所有芯片中耗费的最大代价。并且你需要保证任意两个芯片之间的距离严格\(>1\)。现在给出\(n\)给芯片,询问放\(n\)个芯片的最小代价。一:不难想到......
  • Educational Codeforces Round 149 (Rated for Div. 2)
    这场D被切穿了。A题答案为x或者x-11B题答案就是最长的连续一段的长度+1证明的话大概可以将它看成是几段连续上升和下降的段,然后在峰谷、峰顶分别填上最小、最大,剩下的就依次递增或递减就行。C题将一段连续的0/1视作一个块,那么我们最小化这个块的数量就行。D题如果猜到......
  • Codeforces Round 863 (Div. 3) B. Conveyor Belts
    给一个\(n\timesn\)的矩阵,\(n\)是偶数。将矩阵按圈分割,同一圈的位置可以不消耗代价移动,可以消耗一个代价移动到相邻圈。给出\(n,x_1,y_1,x_2,y_2\),询问\((x_1,y_1)\)移动到\((x_2,y_2)\)的代价最小是多少。显然对每个圈可以选择左上角作为定点。显然直线\(......
  • Codeforces Round 865 (Div. 2) B. Grid Reconstruction
    给一个\(2\timesn\)的网格,且\(n\)是偶数。你需要将\(1\sim2\timesn\)填入这个网格。一条路径是从\((1,1)\)开始,每次只能向右或向下,到\((2,n)\)结束时,所经过的位置。按经过点的顺序标号,一两条路径的代价是\(cost=a_1-a_2+a_3-a_4+\cdots=\sum_{i=1......
  • Codeforces Round 902 (Div. 2, based on COMPFEST 15 - Final Round)
    \(D.EffectsofAntiPimples\)对每个数字能到达的所有位置先预处理最大值,那么就代表选择这个数字之后真实的贡献,那么对这样的预处理值,最小值显然只有一种做法,为\(2^0\),第二小的值应该可以与最小值一起选择,所以答案为\(2^1\),以此类推之后,每个值乘上对应的2的幂次之后求和即......
  • clickhouse常用的函数整理
    转:https://blog.csdn.net/m0_37899908/article/details/118531285一、检测函数类型(clickhouse中数据的类型)SELECTtoTypeName(0);--UInt8(三位数为8)SELECTtoTypeName(-0);--Int8SELECTtoTypeName(-343);--Int16SELECTtoTypeName(12.43);--Float64(默认浮点型的数据......
  • Codeforces Round 872 (Div. 2) B. LuoTianyi and the Table
    给一个\(n\timesm\)的矩阵和\(n\timesm\)个数,你需要把这些数填入矩阵。保证\[\sum_{i=1}^n\sum_{j=1}^m\left(\mathop{max}\limits_{1\leqx\leqi,1\leqy\leqj}a_{x,y}-\mathop{min}\limits_{1\leqx\leqi,1\leqy\leqj}a_{x,y}\right)......