← 목록으로

ASLR과 정보 유출(Leak)

[Pwn] Pwnable · 작성: 2026-07-19 19:31:03 · 조회 3

ASLR(Address Space Layout Randomization)은 스택, 힙, 공유 라이브러리(libc), 그리고 PIE가 켜진 경우 바이너리 자체의 로드 주소까지 프로세스가 실행될 때마다 무작위로 바꾸는 보호 기법이다. 공격자가 미리 계산해둔 고정 주소(가젯 주소, system() 주소 등)를 쓸 수 없게 만드는 게 목적이다.

ASLR이 있으면 뭐가 달라지나

앞선 글들의 ret2libc/ROP 예시는 전부 system()이나 가젯의 절대 주소를 알고 있다는 전제였다. ASLR이 켜지면 이 주소들이 실행할 때마다 바뀌므로, 먼저 실제로 로드된 주소를 알아내는 과정(leak)이 선행되어야 한다.

단, 라이브러리/바이너리가 통째로 랜덤화되어도 내부 함수들 사이의 상대적인 거리(오프셋)는 항상 고정이다. 즉 system()의 실제 주소를 하나만 leak하면, 거기서 고정된 오프셋을 빼거나 더해서 라이브러리의 베이스 주소를 계산하고, 그 베이스 주소에 원하는 다른 함수의 오프셋을 더해 원하는 함수 주소를 전부 계산할 수 있다.

Leak을 얻는 전형적인 방법

  1. GOT(Global Offset Table) 읽기: 프로그램이 이미 printf 같은 libc 함수를 한 번이라도 호출했다면, GOT에 그 함수의 실제 런타임 주소가 채워져 있다. 이 값을 읽을 수 있는 취약점(Format String, 임의 읽기 등)이 있으면 그대로 libc 베이스를 역산할 수 있다.
  2. Format String leak: 앞서 다룬 Format String 취약점으로 스택에 남아있는 리턴 주소(코드 세그먼트 내부 주소, PIE 베이스 역산용)나 저장된 레지스터 값을 그대로 읽어낸다.
  3. 스택 카나리 옆의 값들: 스택 레이아웃에 따라 카나리 근처에 저장된 saved RBP, 리턴 주소가 그대로 유출 대상이 되기도 한다.

계산 예시

# printf@got 값을 leak했다고 가정
leaked_printf = 0x7f1234567890
libc_base = leaked_printf - libc.symbols['printf']
system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + next(libc.search(b'/bin/sh'))

pwntools의 ELF 객체는 심볼 오프셋을 미리 알고 있으므로, 정확한 libc 버전만 알면(libc.symbols['system']) 이 계산을 그대로 코드로 옮길 수 있다. 실전에서는 서버가 사용하는 libc 버전을 모를 수도 있어서, leak한 함수 주소 몇 개의 하위 12비트 패턴으로 버전을 특정하는 libc database 같은 도구를 쓰기도 한다.

정리: leak이 왜 핵심인가

ASLR이 켜진 환경에서 pwnable 문제 대부분은 결국 "①leak할 방법 찾기 → ②베이스 주소 계산 → ③원하는 함수/가젯 주소 계산 → ④익스플로잇 실행" 순서로 흘러간다. 처음 문제를 풀 때 막막하다면, "지금 이 취약점으로 뭘 읽을 수 있는가"부터 다시 물어보는 게 도움이 된다.

Pwnable 카테고리의 글 (6/14)

  1. 메모리 구조 기초: 스택, 힙, 레지스터부터 이해하기
  2. 스택 버퍼 오버플로우: 가장 기본적인 메모리 손상 공격
  3. Format String 취약점: printf가 위험해지는 순간
  4. Stack Canary: 원리와 우회 방법
  5. NX/DEP 우회와 Return-to-libc
  6. ASLR과 정보 유출(Leak)
  7. ROP (Return-Oriented Programming) 완전 정복
  8. 힙 익스플로잇 기초: Use-After-Free와 Double Free
  9. pwntools 실전 활용법
  10. UDF(User-Defined Function) 기반 DB 권한 상승: 원리부터 실전까지
  11. Pass-the-Hash / Pass-the-Ticket: 원리와 실전
  12. eBPF 기반 지속성(Persistence) 기법
  13. Full RELRO 환경에서의 GOT Overwrite와 우회
  14. ret2dlresolve: 심볼 정보 없이 임의 함수 호출하기
← NX/DEP 우회와 Return-to-libc ROP (Return-Oriented Programming) 완전 정복 →