Skip to main content

Use-After-Free: 해방된 메모리를 다시 잡아라

UAF(Use-After-Free) 는 heap 메모리를 free() 한 이후에도 해당 포인터를 계속 사용할 때 발생하는 취약점이다. 현대 브라우저, 커널, 서버 소프트웨어에서 끊임없이 발견되며 CTF에서도 단골 주제다.

동작 원리

char *buf = malloc(64);
free(buf);
// buf는 이제 dangling pointer
strcpy(buf, "pwned"); // UAF 발생!

free() 이후 포인터를 NULL로 초기화하지 않으면 bufdangling pointer 가 된다. 이 상태에서 같은 크기의 chunk를 다시 할당하면 tcache/fastbin 재사용 메커니즘으로 인해 공격자가 그 영역을 장악할 수 있다.

공격 시나리오

  1. Heap Spray — 해제된 chunk 크기와 동일한 객체로 heap을 채워 원하는 데이터를 그 위치에 올린다.
  2. Type Confusion — 해제된 포인터가 다른 타입으로 재해석되도록 유도해 vtable 포인터를 덮는다.
  3. Tcache Poisoning — tcache의 fd 포인터를 조작해 임의 주소를 다음 할당 위치로 만든다.

GDB로 UAF 관찰하기

gdb ./vuln
pwndbg> heap
pwndbg> bins # tcache/fastbin 상태 확인
pwndbg> vis_heap_chunks

pwndbgvis_heap_chunks 명령으로 해제된 chunk가 tcache에 어떻게 연결되는지 시각적으로 확인할 수 있다.

방어 기법

기법설명
  • 포인터 NULL화free(p); p = NULL; 습관화
  • Heap Hardening — glibc 2.32+ safe-linking으로 tcache fd 암호화
  • ASAN(AddressSanitizer) — 개발 단계에서 UAF 자동 탐지
  • CFI(Control Flow Integrity) — vtable 포인터 변조 방지

CTF 접근법

UAF 문제를 만나면 다음 순서로 접근하자:

  1. checksec으로 보호 기법 확인 (PIE, RELRO, Canary)
  2. 할당/해제 흐름을 파악해 같은 크기 chunk 재사용 가능 여부 체크
  3. libc 버전 확인 → tcache 구조 파악
  4. pwntools로 익스플로잇 자동화

UAF는 단순해 보이지만 heap 구조에 대한 깊은 이해가 필요하다. heap 마스터리의 시작점이다. 🔥