我从这里得到了一小部分代码,dup.c
#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));
}谢谢!
发布于 2016-04-04 15:48:29
这是一个编译器特定的“利用漏洞”。首先,让我们把房间里的大象叫出来:
cppcheck或lint ),也没有使用任何像缬磨这样的调试工具来捕捉这种情况。在生产系统中,您至少可以使用这些工具来捕获这些bug。现在说到问题上。首先,这种利用只有在GCC启用“快速箱”的情况下才能真正发挥作用。如果您只是在代码中添加以下内容:
#include <malloc.h>
// ...
mallopt(M_MXFAST, 0);然后它会更快崩溃:
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已经被调用,并且破坏了空闲列表。
发布于 2018-08-15 17:49:54
以前的答案并没有真正解释。在此:
为什么我不能连续两次释放A?
因为glibc实现包含基本的检查,以确保当一个块被添加到自由职业者时,它还没有出现在列表中(您的结果是一个自引用指针)。它本身并不是一种安全防御,而是一种防止明显缺陷的幸运防护措施。
为什么我能在释放B之后再释放A?
因为在自由职业者上A不会和A相邻。自由职业者看起来如下:
-->A-->B-->A所以不会有任何自我引用的指针
,如果我再犯一次错误,为什么要把同一块还给我两次?
当你请求第一个区块时,你得到A,然后是B,然后A,这只是“弹出”自由职业者的下一个项目。
发布于 2016-04-12 08:18:30
正如DevNull所建议的,静态代码分析可以帮助您检测潜在的编码问题。以下是扫描代码时cppcheck的输出:
$ 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: ahttps://stackoverflow.com/questions/36406041
复制相似问题