develicit
← 글 목록으로

힙 펭수이 (Heap Feng Shui) — 힙 메모리 레이아웃을 정밀 조작하는 익스플로잇 기법

·읽는 시간 21분

TL;DR — 힙 펭수이는 비결정적인 힙 할당기 동작을 공격자가 원하는 순서·인접성·재사용 패턴으로 강제하여, UAF/overflow 같은 corruption primitive를 신뢰성 있는 코드 실행으로 전환하는 메타 기법이다. 유저스페이스(Scudo, libmalloc)·커널(SLUB, kalloc) 모두에서 핵심 무기이며, 현대 mitigation(MTE, PAC, freelist randomization, SLAB_VIRTUAL, kalloc_type)을 다루는 연구의 출발점이 된다.

1. 핵심 개념

힙 취약점(UAF, heap overflow, double-free, type confusion 등)을 악용하려면 메모리에서 특정 객체가 특정 위치에 배치되어야 한다. 그러나 일반적인 힙 할당기는 다음 이유로 비결정적이다:

  • Freelist 단편화 — 이전 할당/해제 이력에 따라 free chunk 분포가 달라짐
  • Thread cache (tcache, per-CPU cache, magazine) — 스레드/CPU별 LIFO 캐시로 인해 같은 크기여도 위치가 갈림
  • Randomization mitigation — Scudo의 chunk header XOR, SLUB의 randomized freelist, libmalloc의 nano/scalable zone 무작위화
  • Allocator 내부 정책 — 크기 클래스 라운딩, region/slab/zone 경계, large alloc 분기

힙 펭수이는 이 비결정성을 할당/해제 시퀀스로 길들여서(taming) 결정적(deterministic) 상태로 만든다. 이름은 공간 배치의 미학인 풍수(風水)에서 따왔으며, 2007년 Alexander Sotirov가 Black Hat USA에서 발표한 "Heap Feng Shui in JavaScript" 논문에서 처음 명명되었다.

2. 역사와 발전

연도이벤트의의
1997Solar Designer — return-into-libc스택 corruption → 제어 흐름 탈취 시초
2007Sotirov — Heap Feng Shui in JavaScriptIE 브라우저 힙 결정화 명명, heaplib.js 공개
2010Chen — Pool Feng Shui (Windows kernel)커널 힙으로 개념 확장
2013Tarjei Mandt — iOS kernel heap feng shuiiOS kalloc / zone allocator 결정화 연구 시초
2016VUSec — Flip Feng Shui / DrammerRowhammer + 힙 배치로 하드웨어 결함 익스플로잇
2020–2021Scudo 기본화 (Android 11, 2020) · kalloc_type (iOS 15, 2021 → iOS 16/Ventura 확대)유저·커널 양쪽에서 힙 익스플로잇 비용 대폭 상승
2021Maze (USENIX Security) — 자동화 힙 펭수이심볼릭 실행 기반 자동 배치 합성
2023CVE-2023-20938 (Android Binder UAF), CVE-2023-32434 (iOS kernel)모바일 양 진영에서 SLUB/zone 펭수이 실전 사용
2024WOOT '24 — Scudo 우회 2종hardened allocator도 구조적 약점 존재
2024Dirty Pagedirectory (CVE-2024-1086, nf_tables) — Flipping Pagesbuddy로 반환된 page를 PTE로 재활용하는 page-level feng shui 정착
2025CROSS-X (ACM CCS) — 일반화·고신뢰 cross-cachecross-cache를 안정적·범용으로 자동화 (SLUBStick 후속)
2025Apple MIE (iPhone 17 / A19, EMTE 기반)커널 + 70여 유저 프로세스에 상시 메모리 태깅 — 펭수이의 전제(조용한 corruption) 차단
2025CVE-2025-0072 (Mali GPU) — MTE 우회 · CVE-2025-38352 in-the-wild LPE하드웨어 태깅·강력한 mitigation도 우회 가능 — 모바일 실전 공방 지속
  1. 2007
    Heap Feng Shui in JS
    Sotirov (Black Hat) — IE 힙을 결정화, heaplib.js 공개. 기법 명명.
  2. 2010
    Pool Feng Shui
    Windows 커널 풀로 개념 확장 (Chen).
  3. 2013
    iOS kernel feng shui
    Mandt — XNU kalloc / zone 결정화 연구 시초.
  4. 2016
    Drammer / Flip Feng Shui
    VUSec — Rowhammer 비트플립 + 페이지 배치로 모바일 루트.
  5. 2020
    Scudo · kalloc_type
    Android 11 Scudo(2020) · iOS 15 kalloc_type(2021) — 유저·커널 양쪽 익스플로잇 비용 급상승.
  6. 2021
    Maze (USENIX)
    심볼릭 실행으로 힙 배치 시퀀스 자동 합성.
  7. 2023
    CVE-2023-20938 / -32434
    Android Binder UAF · iOS Triangulation — 양 진영 실전 펭수이.
  8. 2024
    Scudo 우회 2종 (WOOT)
    hardened allocator도 구조적 약점이 있음을 증명.
  9. 2024
    Dirty Pagedirectory
    CVE-2024-1086(nf_tables) — buddy로 반환된 page를 PTE로 재활용하는 page-level feng shui.
  10. 2025
    CROSS-X (CCS)
    cross-cache를 일반화·고신뢰화 (대상 객체 대부분 99%+, pipe_inode_info는 94%). SLUBStick 계보.
  11. 2025
    Apple MIE (EMTE)
    iPhone 17/A19 — 커널+70여 유저 프로세스에 EMTE 상시 적용. (Android MTE는 CVE-2025-0072로 우회 사례 — 별개 플랫폼)

왼쪽 띠 색이 시대를 구분한다 — 태동(유저) → 커널 확장 → 모바일 실전 → 하드웨어 mitigation → 자동화.

Fig 1. 힙 펭수이 계보 — 브라우저 힙 결정화에서 출발해 커널·모바일로 번지고, 하드웨어 mitigation이 비용을 끌어올린 흐름.

최근 동향 (2024~2026) — 세 갈래로 압축된다.

  1. Page-level feng shui — slab/zone을 넘어, buddy allocator로 반환된 page를 page table(PTE) 로 재활용하는 DirtyPagetable·Dirty Pagedirectory(CVE-2024-1086) 계열이 강력한 최신 경로로 자리 잡았다(임의 PTE 조작 → 물리 메모리 R/W → 커널 패치). 다만 CROSS-X 분석에 따르면 page-level 재활용은 상대적으로 드물고 추가 권한·조건이 필요할 수 있어, 모든 cross-cache의 종착지는 아니다.
  2. Cross-cache 일반화 — SLUBStick(성공률 99%+)과 CROSS-X(ACM CCS '25)가 과거 ~40%에 그치던 cross-cache 신뢰성을 실전 수준으로 끌어올렸다.
  3. 하드웨어 태깅 군비경쟁 — Apple MIE(2025, iPhone 17/A19)가 EMTE를 커널+70여 유저 프로세스에 상시 적용해 펭수이의 전제인 '조용한 corruption'을 정면으로 노린다. 그러나 같은 해 Mali GPU의 CVE-2025-0072가 MTE를 우회한 사례처럼, 방어는 비용을 올릴 뿐 공방을 종결시키지는 못한다.

3. 동작 원리

전체 흐름은 다음과 같이 7단계로 진행된다.

배치 제어
1Defragmentation

빈 hole을 채워 힙을 단정렬화

2Hole 생성

타겟 크기의 free slot 확보

3Victim 할당

취약 객체를 정확한 위치에 배치

4Adjacent placement

공격자 제어 객체를 인접 슬롯에

primitive 활용
5Trigger

UAF / overflow / double-free 트리거

6Corruption

메타데이터 · vtable · fn ptr 덮어쓰기

7Pwned

임의 R/W 또는 RIP 제어

1~4 단계가 ‘배치 제어' (deterministic 만들기), 5~7 단계가 ‘primitive 활용' (실제 익스플로잇).

Fig 2. 힙 펭수이 파이프라인 — corruption primitive를 신뢰성 있는 코드 실행으로 끌어올리는 7단계.
  1. Defragmentation — 빈 hole을 채워 힙을 단정렬화
  2. Hole 생성 — 타겟 크기의 free slot을 의도적으로 확보
  3. Victim 할당 — 취약 객체를 정확한 위치에 배치
  4. Adjacent placement — 공격자 제어 객체를 인접 슬롯에 배치
  5. Trigger primitive — UAF / overflow / double-free 트리거
  6. Corruption — 메타데이터 / vtable / 함수 포인터 덮어쓰기
  7. Arbitrary R/W 또는 RIP control — 임의 읽기/쓰기 또는 코드 흐름 탈취

3.1 핵심 4가지 빌딩 블록

  1. Massage(매시지) — 같은 크기 객체를 대량 할당해서 freelist를 비우고 새 슬랩/region/zone을 강제 생성
  2. Punch hole — 의도한 위치만 free하여 다음 할당이 그 자리에 들어가도록 유도
  3. Pin victim — 취약 객체가 hole에 들어가도록 타이밍·크기를 제어
  4. Place attacker chunk adjacent — 인접 슬롯에 공격자 제어 데이터(payload-ready object)를 배치
0. 초기 상태
힙은 단편화되어 있고 hole 위치가 예측 불가
F
A
F
A
A
F
A
F
A
F
1. Massage
같은 크기 객체를 대량 할당 → freelist 비움, 새 slab 강제 생성
A
A
A
A
A
A
A
A
A
A
2. Punch hole
원하는 위치만 free → 다음 할당이 그 자리로 들어가도록 유도
A
A
A
A
H
A
A
A
A
A
3. Pin victim
취약 객체를 hole에 정확히 배치
A
A
A
A
V
A
A
A
A
A
4. Place attacker
공격자 제어 객체를 victim 인접 슬롯에 배치
A
A
A
X
V
X
A
A
A
A
F
free
A
기타 할당
H
공격자가 뚫은 hole
V
취약(victim)
X
공격자 제어

실제로는 슬롯이 수백~수만 개. 그림은 핵심 5개 슬롯만 확대해 보여준다.

Fig 3. 힙 상태 변화 — Massage → Hole → Victim → Attacker 순으로 동일한 슬롯 행이 어떻게 변하는지.

4. Heap Spraying vs Heap Feng Shui

Heap SprayingHeap Feng Shui
목적셸코드/ROP gadget을 메모리 넓은 영역에 뿌림특정 객체를 특정 슬롯에 정확히 배치
정밀도낮음 (확률적, 주소 예측)매우 높음 (결정적, 슬롯 단위)
용도점프 타겟 주소 안정화corruption primitive → 코드 실행 전환
전형 도구NOP sled + 셸코드 반복size class 매칭 + free 패턴 제어

실전 익스플로잇은 보통 둘을 결합한다 — 펭수이로 corruption을 만든 뒤, 스프레이로 RIP 점프 타겟을 안정화.

Heap Spraying
payload를 메모리 전역에 도배 → 점프 타겟이 어디든 맞도록
  • ·확률적 (주소 예측)
  • ·낮은 정밀도
  • ·NOP sled + 셸코드 반복
  • ·점프 타겟 주소 안정화
Heap Feng Shui
단 하나의 슬롯을 victim 옆에 결정적으로 배치
victimattacker
  • ·결정적 (슬롯 단위)
  • ·매우 높은 정밀도
  • ·size class 매칭 + free 패턴 제어
  • ·primitive → 코드 실행 전환

실전 익스플로잇은 둘을 결합한다 — 펭수이로 corruption을 만든 뒤, 스프레이로 점프 타겟을 안정화.

Fig 4. Heap Spraying vs Heap Feng Shui — 넓게 뿌려 확률을 높이는 전략 vs 단 한 슬롯을 결정적으로 점유하는 전략.

5. 플랫폼별 Allocator 비교

Android
AOSP / bionic / Linux kernel
Page-level 보호
SLAB_VIRTUAL (실험적)
slab page를 가상 풀로 격리
pkey · eBPF lockdown
권한 정책 강화
커널 할당자
Linux SLUB
kmalloc-* size class 캐시
FREELIST_HARDENED · RANDOM
freelist ptr XOR + 슬롯 순서 무작위
RANDOM_KMALLOC_CACHES (6.6+)
같은 size 캐시 16개 사본 (optional)
유저스페이스 할당자
Scudo (Android 11+)
Primary region + Secondary mmap
cookie · quarantine
CRC32 checksum 손상 시 abort
MTE (Pixel 8+)
ARMv8.5 HW 태그 · opt-in/설정 기반
iOS
Darwin / XNU
Page-level 보호
PPL → SPTM/TXM (A15+)
페이지 테이블 자체를 별도 monitor가 보호
MIE · EMTE (A19+, 2025)
Enhanced MTE 상시 적용
PAC-CFI
signed function ptr / return addr
커널 할당자
XNU zalloc / kalloc
수백 개의 named zone
kalloc_type (iOS 15+)
타입 시그니처를 randomized bucket으로 격리
Zone require · GC
free 시 zone 일치 검증, page 회수
유저스페이스 할당자
libmalloc
nano / tiny / small / large zone
PAC freelist (arm64e)
freelist ptr를 IB key로 sign
Magazine secret · cookie
chunk metadata XOR 보호

Android는 ‘같은 크기 캐시'를 공유하는 SLUB 게임. iOS는 kalloc_type의 ‘randomized bucket' 게임으로, 같은 크기여도 타입 bucket이 다르면 잘 안 섞인다(확률적).

Fig 5. Android vs iOS 힙 스택 — 유저 → 커널 → 페이지 보호 계층까지의 mitigation 분포.

5.1 한눈에 보기: Android vs iOS

Android (AOSP)iOS (Darwin / XNU)
유저스페이스 할당자Scudo (Android 11+) — bionic libclibmalloc — nano / tiny / small / large zone
커널 할당자Linux SLUB (kmalloc-*)XNU zalloc / kalloc (zone-based)
커널 객체 격리일반 캐시 + 일부 dedicated cache (SLAB_ACCOUNT, kvmalloc)kalloc_type (iOS 15+, randomized bucketed type isolation)
Freelist 보호CONFIG_SLAB_FREELIST_HARDENED (XOR), CONFIG_SLAB_FREELIST_RANDOMzone freelist는 PAC로 sign된 포인터 (arm64e), zone secret cookie
메모리 태깅MTE (ARMv8.5+, Pixel 8 이후 — 앱/프로세스별 opt-in·설정 기반)PAC (arm64e, A12+) + kASLR · zone redzone
CFILLVM CFI (커널 + 유저)PAC 기반 CFI (signed function pointer, return address)
Page-level 보호SLAB_VIRTUAL (실험적), pkey, eBPF lockdownPPL (Page Protection Layer) → SPTM/TXM (A15+) — 페이지 테이블 자체를 별도 모니터가 보호
대표 sandbox escape 표적system_server, mediaserver, binder, GPU driverlaunchd, MIG 서버, IOKit user client, AppleAVD/IOMobileFrameBuffer
대표 spray primitivemsg_msg, pipe_buffer, sk_buff, Binder transaction buffermach_msg OOL descriptors, OSData, IOSurface, ipc_kmsg

5.2 Android Scudo (유저스페이스)

Android 11부터 기본 유저스페이스 할당자가 Scudo로 변경되었다.

  • Primary allocator: 버전/설정별 size class map을 쓰는 region 기반 (Android 14 기준 WOOT '24 분석은 primary class ID 1~32를 제시 — "정확히 16개"는 버전 의존적). region 내부 freelist는 per-thread cache(TransferBatch)와 슬롯 randomization을 거치므로 단순 LIFO보다 복잡하다.
  • Secondary allocator: 큰 할당(기본 64KB↑)은 guard page로 둘러싸인 mmap 영역에 단독 배치.
  • Chunk header: global secret/cookie를 포함한 CRC32 기반 checksum으로 header integrity를 검증 — 손상 감지 시 즉시 abort.
  • Quarantine: free된 chunk를 잠시 격리해 즉각적 UAF 재사용 차단.
  • MTE 통합: 하드웨어 태그가 켜진 기기에서는 tag mismatch 시 SIGSEGV.

WOOT '24 우회 요약

기법 1 — Scudo 내부 캐시 메커니즘을 악용해 chunk를 임의 주소에 가깝게 유도 (이후 패치됨).

기법 2 — Secondary allocator의 대형 chunk 처리 구조를 이용 — 구조적 문제라 패치 난이도가 높음.

5.3 Linux SLUB (Android 커널)

Android 커널은 Linux SLUB을 사용한다.

  • 범용 할당은 kmalloc-* 캐시 (8B ~ 8KB, 2의 거듭제곱 + 96B/192B 예외, 최근에는 kmalloc-cg-* 분리).
  • 같은 크기 캐시에 할당된 객체끼리만 인접 → 타겟 객체와 같은 크기의 유용한 커널 객체를 찾는 것이 핵심.
  • Per-CPU active slab + partial list + node partial 3단계 구조.
  • CONFIG_SLAB_FREELIST_HARDENED — freelist 포인터를 ptr XOR random XOR &ptr로 난독화.
  • CONFIG_SLAB_FREELIST_RANDOM — slab 내 슬롯 순서 랜덤화 (slab 생성 시점 1회).
  • CONFIG_RANDOM_KMALLOC_CACHES — 같은 크기에 대해 16개 사본 캐시 중 hash로 랜덤 선택 (Linux 6.6+ optional — GKI/기기별로 꺼져 있을 수 있음).
  • SLAB_VIRTUAL (실험) — slab page를 virtual address 전용 풀로 격리해 cross-cache 재사용 차단.

5.4 iOS libmalloc (유저스페이스)

iOS/macOS의 기본 유저스페이스 할당자.

  • Nanozone: 256B 이하 초소형 할당 전용. 16B 단위, magazine(per-CPU) 구조.
  • Scalable zone (tiny/small/large):
    • tiny: ≤1KB, 16B 양자화
    • small: ≤15KB(또는 32KB on 16K page), 512B 양자화
    • large: 그 이상, vm_allocate 직접
  • Pointer Authentication (arm64e): zone freelist 포인터에 IB key로 PAC 서명. 위조 시 fault.
  • Magazine secret / cookie: chunk metadata XOR 보호.
  • Guard malloc / libgmalloc: 디버깅용, 모든 할당을 page 단위로 격리 (production 비활성).

5.5 XNU zalloc / kalloc_type (iOS 커널)

iOS 커널 힙은 SLUB과 구조가 다르며, 펭수이 전략도 다르다.

  • Zone: 같은 element size + 같은 "용도"의 할당을 모은 free list. kalloc.*, ipc.ports, OSData 등 수백 개의 named zone이 존재.
  • kalloc heap 분리 (iOS 14+): KHEAP_DEFAULT, KHEAP_DATA_BUFFERS, KHEAP_KEXT 등 용도별 heap 격리 → 데이터/포인터를 같은 zone에 못 섞음.
  • kalloc_type (iOS 15+): 타입 시그니처를 randomized bucket에 배치하는 bucketed type isolation. 같은 bucket에 여러 타입이 섞일 수 있지만, UAF 재할당 후보(같은 슬롯을 노릴 만한 타입)를 크게 줄여 type confusion 익스플로잇을 어렵게 만든다 — 모든 type confusion을 원천 차단하는 것은 아니다.
  • Zone require / zone_id check: free 시 zone 일치 여부 검증.
  • Zone gc: 비어 있는 page를 회수해 cross-zone reuse를 어렵게 함.
  • PPL → SPTM/TXM (A15+): 페이지 테이블 entry 자체를 별도 monitor가 검증해 R/W gadget으로 kernel text 패치 불가.
  • Memory Integrity Enforcement (MIE) · Enhanced MTE (A19/M5+, 2025): EMTE를 상시 적용해 메모리 안전 위반을 하드웨어로 즉시 차단 — 펭수이의 전제인 '조용한 corruption'을 깨는 최신 방어.

Android SLUB vs iOS zalloc 한 줄 정리

SLUB은 "같은 size class는 한 풀에 다 들어간다 → 같은 크기 유용 객체 찾기 게임". iOS는 kalloc_type 이후 "같은 크기여도 타입 bucket이 다르면 잘 안 섞인다(randomized bucketing이라 확률적) → 같은 bucket 안에서 무엇이 유용한지 찾는 게임".

Linux SLUB — 크기 기준
kmalloc-1k : 1KB짜리는 타입과 무관하게 한 캐시
kmalloc-1k
victim (1KB)
msg_msg
tty_struct
pipe_buffer

같은 크기 유용 객체를 victim 옆에 둘 수 있다 → 펭수이 가능

iOS kalloc_type — 타입 기준
같은 1KB라도 타입 시그니처를 randomized bucket으로 분리
bucket A (type A…)
victim (type A)
type A obj
bucket B (type B…)
attacker (type B)
type B obj

다른 bucket의 타입은 같은 슬롯 재활용이 어려움 → 재할당 후보를 확률적으로 축소 (완전 차단은 아님)

취약 객체공격자 객체
Fig 6. SLUB(크기 기준) vs kalloc_type(타입 기준) — 무엇이 같은 풀을 공유하는가가 펭수이의 난이도를 가른다.

6. 유용한 커널/IPC 객체 카탈로그

익스플로잇 신뢰성은 "corruption 시점에 인접 슬롯에 어떤 객체를 둘 수 있는가"로 결정된다.

Android (Linux SLUB)

객체크기 / 캐시왜 유용한가
msg_msgkmalloc-64 ~ kmalloc-4k (msgsnd 크기 제어)크기·내용 모두 유저 제어, OOB read/write primitive로 전환 용이
pipe_bufferkmalloc-1k (16개 단위)pipe_buf_operations 함수 포인터 → RIP 제어 (Dirty Pipe 류)
sk_buff (skb->data)kmalloc-512 / 1k / 2k / 4k (트래픽 크기)임의 크기/내용 spray, 네트워크로 원격 트리거 가능
tty_structkmalloc-1ktty_operations 함수 포인터, 정보 누출에 자주 사용
shm_file_data, seq_operationskmalloc-32 / 64작은 캐시에서 함수 포인터 확보
Binder transaction buffer임의 크기 (process별 mmap region)Android 특화, system_server와 동일 캐시 공유

iOS (XNU zalloc)

객체Zone왜 유용한가
ipc_kmsgipc.kmsgsmach_msg로 크기·내용 spray, OOL descriptor로 포인터 spray
OOL ports arrayipc.portssend right 배열을 임의 크기로 — fake port 만들기에 사용
OSData / OSStringkalloc.data.* (KHEAP_DATA_BUFFERS)IOKit user client로 유저랜드에서 직접 spray, 내용 100% 제어
IOSurface propertieskalloc.* (size 다양)IOSurfaceRoot로 유저에서 set/get → R/W primitive 변환의 고전
Mach voucheripc.vouchers참조 카운트 조작 + UAF 결합 시 강력
vm_map_entryVM map entriesVM subsystem corruption → 페이지 매핑 탈취

7. Cross-cache / Cross-zone 공격

같은 캐시/zone 안에 둘 수 있는 유용한 객체가 없을 때, slab/zone page 자체를 다른 캐시로 재활용시키는 기법.

1victim 격리

victim이 dedicated/cg 캐시에 갇힘 — 같은 캐시에 쓸 만한 객체가 없다.

victim 전용 캐시
2slab 전체 free

그 캐시의 slab page를 모두 비워 page를 buddy allocator로 반환시킨다.

buddy allocator (page pool)
3page 재할당 유도

다른 캐시(msg_msg 등)가 같은 물리 page를 즉시 가져오도록 경합.

attacker 캐시
4overlap 확보

공격자 객체가 victim의 옛 메모리에 겹쳐 — cross-cache UAF 성립.

attacker 캐시

재활용된 page를 page table(PTE)로 다시 써 DirtyPagetable·Dirty Pagedirectory(CVE-2024-1086)로 잇는 경로가 강력하다(단 page-level 재활용은 상대적으로 드물고 조건이 필요). 방어: SLAB_VIRTUAL(가상 풀 격리), kvmalloc 분리, page tagging. iOS는 kalloc_type + zone GC + PAC/SPTM으로 cross-zone을 훨씬 어렵게 만든다.

Fig 7. Cross-cache 공격 — 같은 캐시 안에 유용한 객체가 없을 때, slab page 자체를 buddy allocator를 거쳐 다른 캐시로 재활용시킨다.
  • Android: kmalloc-cg-* 또는 dedicated cache에 갇힌 victim을 노릴 때, 해당 캐시의 slab page를 모두 free시켜 buddy allocator로 반환되게 한 뒤, 다른 캐시(msg_msg 등)가 그 페이지를 가져오도록 유도.
    • 핵심 도구: pcpu_alloc, kvfree, __free_pages_ok 경합.
    • 방어: SLAB_VIRTUAL, kvmalloc 분리, page tagging.
  • iOS: kalloc_type 도입 이후 같은 type만 한 zone을 공유하므로 cross-zone이 더 어렵다. 대신 zone garbage collection으로 page를 다른 zone에 재할당시키는 "zone-level feng shui" 연구가 진행 중.
    • PAC와 SPTM이 추가로 cross-zone fake pointer 공격을 차단.

8. 실전 사례

CVE-2023-20938 — Android Binder UAF → Root

Google Android Offensive Security가 Binder UAF를 SLUB 펭수이로 익스플로잇하여 untrusted app에서 root를 획득.

  • GKI 커널 5.4 / 5.10 영향. 2023-02 / 2023-07 Security Bulletin에서 패치.
  • 핵심: binder_node UAF(kmalloc-128)를 sendmsg spray와 eventpoll(epitem) 객체로의 cross-cache 재사용으로 확장 (Google AndroidOffSec 공개 분석).
Drammer — Rowhammer + Flip Feng Shui → Mobile Root

Rowhammer 하드웨어 비트플립 + 페이지 배치 제어로 권한 없는 앱에서 Android 루트.

  • 소프트웨어 취약점 없이 DRAM 결함만으로 결정적 루트.
  • 메모리 deduplication 없이도 성공 — 페이지 풀에서 PTE가 들어갈 슬롯을 펭수이로 확보한 결과.
CVE-2023-32434 — iOS kernel integer overflow (Operation Triangulation)

Kaspersky가 공개한 "Operation Triangulation" 체인의 커널 LPE 단계. XNU의 integer overflow(mach_make_memory_entry / vm_map 계열)로 물리 메모리 R/W를 얻고, 별도의 CVE-2023-38606(미공개 MMIO 레지스터)으로 하드웨어 메모리 보호(PPL)를 우회했다.

  • iOS 15.7.7, 16.5.1에서 패치.
  • 의의: PAC·PPL 같은 강력한 mitigation 환경에서도 메모리 안전 취약점이 실전 익스플로잇 체인으로 이어짐을 보여준다.
CVE-2021-30883 — IOMobileFrameBuffer (FORCEDENTRY 후속 LPE)

IOMobileFrameBuffer 힙 overflow. IOSurface property를 인접 zone에 spray해 함수 포인터 영역을 덮어 RIP 제어.

  • in-the-wild 0-day로 사용됨. iOS 15.0.2에서 패치.

9. 현대 방어 기제 정리

Massage
Hole
Adjacent
Trigger
Corruption
Exec
Freelist 난독화
슬롯 순서 무작위화
캐시/zone 격리 (kalloc_type)
Quarantine / GC
MTE / PAC · MIE/EMTE
CFI
PPL · SPTM/TXM
강력 차단
부분 차단
영향 없음

어떤 단일 방어도 모든 단계를 막지 못한다 — 다층 방어가 필수.

Fig 8. mitigation × 공격 단계 커버리지 — 어떤 방어가 펭수이의 어느 단계를 막는가.
방어AndroidiOS펭수이에 미치는 영향
Freelist 난독화SLAB_FREELIST_HARDENEDPAC-signed freelist (arm64e)fake free chunk 주입 차단
슬롯 순서 무작위화SLAB_FREELIST_RANDOMzone slot randomization인접성 예측 어려워짐 — spray 양으로 보완
캐시 무작위화RANDOM_KMALLOC_CACHES (6.6+ optional)kalloc_type (randomized bucket)같은 크기 객체 매칭 후보를 확률적으로 축소
메모리 태깅 / 인증MTE (HW tag)PAC (HW signed pointer)UAF/overflow 자체를 즉시 검출 가능 (확률적/결정적)
페이지 권한 모니터SLAB_VIRTUAL (실험), pkeyPPL → SPTM/TXMkernel text 패치를 R/W primitive로 못 함
CFILLVM CFIPAC-CFIvtable/fn ptr 덮어쓰기로 임의 점프 불가
Quarantine / GCScudo quarantinezone gc + zone require즉각 UAF 재사용 차단, race window 강제 확대

10. 자동화 / 연구 도구

  • Maze (USENIX Security '21) — 심볼릭 실행 기반 자동 힙 배치 합성. 익스플로잇 시나리오 입력 → 할당/해제 시퀀스 출력.
  • SLUBStick (USENIX Security '24) — Linux SLUB cross-cache 공격 자동화 프레임워크.
  • Syzkaller + KASAN — 트리거 시퀀스 발견 + 힙 상태 추적.
  • kasld / kbase finder — KASLR 우회용 정보 누출 자동화.
  • iOS 측: KTRR/SPTM bypass research, panic log diffing — 공개 도구가 적어 직접 PoC 작성이 일반적.
  • MTE-aware fuzzing (HWASAN, scudo_standalone) — 태그 mismatch를 코너 케이스로 활용.

11. 참고 자료

기초 / 역사

Android / Linux SLUB

iOS / XNU


댓글