Double Free
Reading time: 5 minutes
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Basic Information
메모리 블록을 두 번 이상 해제하면 할당자의 데이터가 엉망이 되어 공격의 길을 열 수 있습니다. 이는 다음과 같이 발생합니다: 메모리 블록을 해제하면, 그것은 무료 청크 목록(예: "fast bin")으로 돌아갑니다. 동일한 블록을 연속으로 두 번 해제하면, 할당자는 이를 감지하고 오류를 발생시킵니다. 그러나 그 사이에 다른 청크를 해제하면, 이중 해제 검사가 우회되어 손상이 발생합니다.
이제 새로운 메모리를 요청할 때(malloc
사용), 할당자는 두 번 해제된 블록을 제공할 수 있습니다. 이로 인해 두 개의 서로 다른 포인터가 동일한 메모리 위치를 가리키게 됩니다. 공격자가 그 포인터 중 하나를 제어하면, 그 메모리의 내용을 변경할 수 있으며, 이는 보안 문제를 일으키거나 심지어 코드를 실행할 수 있게 할 수 있습니다.
Example:
#include <stdio.h>
#include <stdlib.h>
int main() {
// Allocate memory for three chunks
char *a = (char *)malloc(10);
char *b = (char *)malloc(10);
char *c = (char *)malloc(10);
char *d = (char *)malloc(10);
char *e = (char *)malloc(10);
char *f = (char *)malloc(10);
char *g = (char *)malloc(10);
char *h = (char *)malloc(10);
char *i = (char *)malloc(10);
// Print initial memory addresses
printf("Initial allocations:\n");
printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i);
// Fill tcache
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);
// Introduce double-free vulnerability in fast bin
free(h);
free(i);
free(h);
// Reallocate memory and print the addresses
char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10);
// Print initial memory addresses
printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2);
return 0;
}
이 예제에서, 여러 개의 해제된 청크(7)로 tcache를 채운 후, 코드는 청크 h
를 해제한 다음 청크 i
를 해제하고 다시 h
를 해제하여 이중 해제를 발생시킵니다(Fast Bin dup이라고도 함). 이는 재할당 시 겹치는 메모리 주소를 받을 가능성을 열어주며, 두 개 이상의 포인터가 동일한 메모리 위치를 가리킬 수 있습니다. 하나의 포인터를 통해 데이터를 조작하면 다른 포인터에 영향을 미칠 수 있어, 이는 심각한 보안 위험과 악용 가능성을 초래합니다.
실행할 때, i1
과 i2
가 동일한 주소를 가졌음을 주목하세요:
초기 할당:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
d: 0xaaab0f0c2300
e: 0xaaab0f0c2320
f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
재할당 후:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
d1: 0xaaab0f0c2300
e1: 0xaaab0f0c22e0
f1: 0xaaab0f0c22c0
g1: 0xaaab0f0c22a0
h1: 0xaaab0f0c2380
i1: 0xaaab0f0c23a0
i2: 0xaaab0f0c23a0
예제
- Dragon Army. Hack The Box
- 우리는 일반적인
__malloc_hook
덮어쓰기를 방지하는 크기0x70
를 제외하고는 Fast-Bin 크기의 청크만 할당할 수 있습니다. - 대신, Fast Bin dup의 대상으로
0x56
로 시작하는 PIE 주소를 사용합니다(1/2 확률). - PIE 주소가 저장되는 한 곳은 Glibc 내부의
main_arena
이며,__malloc_hook
근처에 있습니다. - 우리는
main_arena
의 특정 오프셋을 목표로 하여 그곳에 청크를 할당하고,__malloc_hook
에 도달할 때까지 청크를 계속 할당하여 코드 실행을 얻습니다. - zero_to_hero. PicoCTF
- Tcache 빈과 널 바이트 오버플로우를 사용하여 이중 해제 상황을 달성할 수 있습니다:
- 우리는 크기
0x110
의 청크 세 개(A
,B
,C
)를 할당합니다. B
를 해제합니다.A
를 해제하고 널 바이트 오버플로우를 사용하기 위해 다시 할당합니다.- 이제
B
의 크기 필드는0x100
이 되어,0x111
대신 다시 해제할 수 있습니다. - 우리는 동일한 주소를 가리키는 크기
0x110
의 Tcache-bin 하나와 크기0x100
의 Tcache-bin 하나를 가지고 있습니다. 따라서 이중 해제가 발생합니다. - 우리는 Tcache poisoning을 사용하여 이중 해제를 활용합니다.
참고문헌
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.