首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对双自由攻击的认识

对双自由攻击的认识
EN

Stack Overflow用户
提问于 2016-04-04 14:53:35
回答 3查看 4.6K关注 0票数 0

我从这里得到了一小部分代码,dup.c

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

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));
}
  1. 为什么我不能连续两次释放A?
  2. 为什么我能在释放B之后再释放A?
  3. 如果我又犯了同样的错误,为什么要把同样的块还给我两次?

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-04-04 15:48:29

这是一个编译器特定的“利用漏洞”。首先,让我们把房间里的大象叫出来:

  1. 您是有意使用未定义的行为(UB)的,因此从这一点开始,所有的赌注都取消了。
  2. 您没有使用任何静态代码分析工具(如cppcheck或lint ),也没有使用任何像缬磨这样的调试工具来捕捉这种情况。在生产系统中,您至少可以使用这些工具来捕获这些bug。
  3. 您可以随时提取最新的glibc源,并为您自己发现:)

现在说到问题上。首先,这种利用只有在GCC启用“快速箱”的情况下才能真正发挥作用。如果您只是在代码中添加以下内容:

代码语言:javascript
复制
#include <malloc.h>
// ...
mallopt(M_MXFAST, 0);

然后它会更快崩溃:

代码语言:javascript
复制
This file demonstrates a simple double-free attack with fastbins.
Allocating 3 buffers.
1st malloc(8): 0x556f373b1010
2nd malloc(8): 0x556f373b1030
3rd malloc(8): 0x556f373b1050
Freeing the first one...
If we free 0x556f373b1010 again, things will crash because 0x556f373b1010 is at the top of the free list.
So, instead, we'll free 0x556f373b1030.
Now, we can free 0x556f373b1010 again, since it's not the head of the free list.
*** Error in `./a.out': double free or corruption (!prev): 0x0000556f373b1010 ***
Aborted (core dumped)

这要归功于“扣件箱”的工作方式:

M_MXFAST (因为glibc2.3)设置了使用“allocation”满足的内存分配请求的上限。(此参数的测量单元为字节。)Fastbins是保存相同大小的已分配内存块而不合并相邻空闲块的存储区域。同样大小的块的后续重新分配可以非常快地通过从快箱分配来处理,尽管内存碎片和程序的总体内存占用可以增加。这个参数的默认值是64 *size_t(/4)(即32位架构上的64)。此参数的范围为0-80*size_t(/4)。将M_MXFAST设置为0将禁用快速箱的使用。

空闲调用不会立即释放内存,只是将其标记为可用于未来的malloc()调用。如果您立即尝试对同一内存块连续两次发出free()调用,内部指针检查将捕获它,但损坏已经完成(UB调用),但相同的检查将无法处理所提供的示例情况。

至于最后的3个malloc()调用,产生了两次相同的地址: UB已经被调用,并且破坏了空闲列表。

票数 1
EN

Stack Overflow用户

发布于 2018-08-15 17:49:54

以前的答案并没有真正解释。在此:

为什么我不能连续两次释放A?

因为glibc实现包含基本的检查,以确保当一个块被添加到自由职业者时,它还没有出现在列表中(您的结果是一个自引用指针)。它本身并不是一种安全防御,而是一种防止明显缺陷的幸运防护措施。

为什么我能在释放B之后再释放A?

因为在自由职业者上A不会和A相邻。自由职业者看起来如下:

代码语言:javascript
复制
-->A-->B-->A

所以不会有任何自我引用的指针

,如果我再犯一次错误,为什么要把同一块还给我两次?

当你请求第一个区块时,你得到A,然后是B,然后A,这只是“弹出”自由职业者的下一个项目。

票数 1
EN

Stack Overflow用户

发布于 2016-04-12 08:18:30

正如DevNull所建议的,静态代码分析可以帮助您检测潜在的编码问题。以下是扫描代码时cppcheck的输出:

代码语言:javascript
复制
$ cppcheck --enable=all test.cpp 
  Checking test.cpp...
  [test.cpp:27]: (error) Memory pointed to by 'a' is freed twice.
  [test.cpp:33]: (error) Memory leak: c
  [test.cpp:30]: (error) Allocation with malloc, printf doesn't release it.
  [test.cpp:27]: (error) Deallocating a deallocated pointer: a
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36406041

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档