Memory & Control Flow Protection
런타임 공격으로부터 소프트웨어를 보호하기 위해 하드웨어가 제공하는 주소 공간 격리, 실행 권한 제어 및 제어 흐름 무결성(CFI) 기술을 다루는 학습 노드입니다.
Article
M
Me
hyunyoun's Blog
computer-architecture-embedded-systemscomputer-architectureembedded-systemshardware-securitytrusted-physicsmemorycontrol-flow-protectionlearning10 min read
1. Overview
메모리와 제어 흐름 보호(Memory & Control Flow Protection, MCP)는 "C/C++ 프로그래머는 반드시 포인터(Pointer) 실수를 저지르며, 해커는 그 실수를 파고들어 CPU의 제어권(PC)을 탈취한다"는 전제하에, 컴파일러와 하드웨어가 합심하여 쳐놓은 방어선 겹겹의 참호전(Trench Warfare)입니다.
학습자는 버퍼를 넘치게 짜서 반환 주소(Return Address)를 덮어쓰는 클래식한 **버퍼 오버플로우(Buffer Overflow)**를 뜯어보고, 이를 막기 위해 운영체제와 하드웨어가 결합해 힙/스택 메모리를 흔들어 섞어버리는 ASLR (주소 공간 배치 난수화) 및 데이터 실행 방지(DEP/NX 비트) 역학을 해부합니다. 나아가 해커가 내가 짠 코드를 레고 블록처럼 찢어 붙여 공격하는 **ROP (Return-Oriented Programming)**의 기하학을 분석하고, CPU 하드웨어 레벨에서 함수의 시작과 끝 화살표 궤적을 철저히 검열하는 최첨단 CFI (제어 흐름 무결성, Intel CET/ARM BTI) 아키텍처를 통달하여 바이너리 런타임 보안의 마스터 역량을 확보합니다.
2. Scope & Boundaries
In-Scope
- 메모리 손상 기초 (Memory Corruption): 버퍼 오버플로우(Buffer Overflow), 스택 스매싱(Stack Smashing), 힙 오버플로우(Heap Overflow), Use-After-Free.
- 방어 메커니즘 1세대 (OS/Compiler Defenses): 스택 카나리아(Stack Canary / Cookie), 데이터 실행 방지(DEP / NX 비트, W^X), 주소 공간 배치 난수화(ASLR).
- 코드 재사용 공격 (Code Reuse Attacks): ROP (Return-Oriented Programming), JOP (Jump-Oriented Programming), 가젯(Gadget) 조립 역학.
- 방어 메커니즘 2세대 (Hardware Control Flow Integrity, CFI): 하드웨어 섀도우 스택(Shadow Stack, Intel CET), 분기 타겟 식별(Branch Target Identification, ARM BTI), 포인터 인증(Pointer Authentication, ARM PAC).
Out-of-Scope
- 정적 분석 및 퍼징 (Fuzzing): 소스 코드를 실행하지 않고 취약점을 찾는 SonarQube 정적 분석기나 AFL Fuzzer의 알고리즘 09-02-04. Secure Coding & DevSecOps 영역.
- 마이크로아키텍처 부채널 공격 (MAA): 캐시 상태나 분기 예측기를 악용해 메모리를 엿보는 스펙터(Spectre)/멜트다운 02-04-01. Microarchitectural Attacks 영역.
Boundaries
- MCP vs. Memory Management (03-01-02): 운영체제의 메모리 관리(03-01-02)가 가상 메모리와 페이지 테이블을 통해 "다른 프로세스의 공간(남의 집)을 넘보지 못하게" 막는 큼직한 담장이라면, MCP는 "내 집(내 프로세스 주소 공간) 안에서 내가 칼을 들고 내 발등(스택/힙)을 찍어 시스템 제어권을 스스로 넘겨주는 내부 붕괴"를 막아내는 정밀한 외과 수술적 방어입니다.
3. Counterexample
- ASLR 맹신에 의한 립-릭(Lib-Leak) 참사: "ASLR이 켜져 있어서 라이브러리 주소가 매번 바뀌니까 해커가 ROP 공격을 못하겠지"라며 힙 메모리 유출(Use-After-Free) 버그를 방치하는 무지함. ASLR은 주소의 '시작점(Base Address)'만 난수화할 뿐, 함수들 사이의 '상대적 거리(Offset)'는 영원히 고정되어 있습니다. 해커가 힙 버그를 통해
printf함수의 메모리 런타임 주소를 단 하나라도 유출(Leak)하는 순간, 상대적 거리를 덧셈(+)하여system()함수의 주소를 0.001초 만에 박살 내고 루트(Root) 쉘을 땁니다. - CFI 하드웨어 끄기 (Legacy Down-grade): 최신 Intel CET(섀도우 스택) 하드웨어를 돈 주고 사놓고, 구형 레거시 소프트웨어가 "스택을 비정상적으로 조작하는 커스텀 셋점프(setjmp/longjmp) 로직"을 쓴다며 귀찮다고 커널 레벨에서 CET 기능을 통째로 꺼버리는 관리자 붕괴. ROP 공격을 막아낼 최강의 방패를 휴지통에 버리는 꼴이며, 차라리 레거시 코드의 롱점프 로직을 리팩토링해야 합니다.
4. Prerequisites
- 파이프라인과 제어 흐름 (Basic): 함수 호출 명령(
call,ret)이 파이프라인에서 PC(프로그램 카운터)를 어떻게 변경하고 스택(Stack)을 건드리는지 ISA 구조를 완벽히 이해해야 ROP 공격의 궤적을 상상할 수 있습니다. (02-01-03 ICL) - 가상 메모리 기초 (Basic): 페이지 테이블에 읽기(R), 쓰기(W), 실행(X) 권한 비트가 박혀있다는 MMU 뼈대를 알아야 NX 비트 방어를 직관할 수 있습니다. (03-01-02 VMM)
5. Learning Map
6. Learning Topics
Basic
Core Topic 01: 제어 흐름 탈취와 버퍼 오버플로우 (Buffer Overflow Physics)
- Why to Learn: C/C++에서 경계 검사(Bounds Checking)가 없는 낡은 함수(
strcpy,gets)를 썼을 때, 스택 프레임이 물리적으로 어떻게 붕괴하며 CPU 제어권(Program Counter)이 해커에게 통째로 털리는지 밑바닥부터 체감하기 위함입니다. - What to Learn:
- Concepts: 버퍼 오버플로우, 스택 프레임(Stack Frame), 베이스 포인터(SFP), 리턴 주소(Return Address, RET).
- Skills: 스택 스매싱(Stack Smashing), 쉘코드(Shellcode) 주입, 스택 카나리아(Stack Canary) 1차 방어.
- Tools: GDB (GNU Debugger) 스택 덤프 분석.
- Trade-offs: 자바(Java)나 러스트(Rust)처럼 언어 차원에서 배열 경계를 매번 하드웨어적으로 체크하면 보안은 100% 보장되지만 성능(오버헤드)이 깎이는 반면, C언어는 개발자를 맹신하고 속도를 챙긴 대가로 메모리 해킹의 놀이터가 된 근원적 트레이드오프.
- How to Learn:
- 1단계: 크기가 10바이트인 배열 버퍼에 100바이트의 문자열 A(
0x41)를 밀어 넣었을 때, 배열 위쪽에 저장되어 있던 원래 함수의 리턴 주소(RET) 영역이 싹 다0x41414141로 덮어씌워져 버리는 스택 붕괴 구조 다이어그램을 해부합니다. - 2단계: 함수가 종료되면서
ret명령어를 실행할 때, CPU는 방금 덮어씌워 진 가짜 리턴 주소(해커가 스택에 심어놓은 악성 쉘코드의 시작 번지)로 순진하게 점프(PC 변경)해 버리는 기계적 복종을 뜯어봅니다.
- 1단계: 크기가 10바이트인 배열 버퍼에 100바이트의 문자열 A(
- Implement: 파이썬으로 가짜 64바이트 메모리(바이트 배열)와
SP(스택포인터),PC객체를 만들고,[Buffer 32B][SFP 8B][RET 8B]구조를 세팅합니다. 40바이트의 입력을 밀어 넣어 RET 영역 8바이트가 타겟 주소(0xDEADBEEF)로 덮어씌워지고(Overflow), 함수 리턴 루틴을 밟을 때PC가 해커의 주소로 꺾여버리는 현상을 콘솔 로그로 완벽하게 시뮬레이션.
Recommended
Core Topic 02: W^X (DEP/NX 비트)와 주소 공간 배치 난수화 (ASLR)
- Why to Learn: 버퍼 오버플로우 공격이 판치자, 이를 막기 위해 운영체제(OS)와 CPU(MMU)가 협력하여 "메모리에 코드를 쓰게 냅두되 실행은 막아버리고, 남의 코드를 부르려 하면 주소를 못 찾게 섞어버리는" 1세대 방공망을 꿰뚫기 위함입니다.
- What to Learn:
- Concepts: DEP(Data Execution Prevention), NX(No-eXecute) 비트, (Write XOR Execute 정책).
- Skills: ASLR(Address Space Layout Randomization), 베이스 오프셋(Base Offset).
- Tools: 리눅스 커널
/proc/sys/kernel/randomize_va_space. - Trade-offs: 프로세스를 켤 때마다 스택, 힙, 공유 라이브러리의 주소를 미친 듯이 섞어버리는 ASLR의 훌륭한 방어력 vs 그 섞인 주소들이 실제 물리 메모리에 파편화되어 TLB(변환 버퍼) 미스를 높이고, 디버깅을 끔찍한 지옥으로 밀어 넣는 부작용.
- How to Learn:
- 1단계: 스택이나 힙은 데이터를 읽고 쓰는(W=1) 공간이므로, 페이지 테이블 엔트리(PTE)에 NX 비트(X=0)를 꽂아두어 해커가 스택에 악성 쉘코드를 쑤셔 넣고 거기로 점프하더라도 CPU가 "실행 권한 없음(Segmentation Fault)!"을 외치며 프로세스를 사살(Kill)하는 물리를 해부합니다.
- 2단계: 쉘코드를 못 쓰게 막아놨더니, 해커가 스택에 코드를 안 쓰고 대신 이미 메모리에 올라와 있는 정상적인 시스템 함수(
system("/bin/sh"))의 주소로 점프해 버리는 Return-to-Libc 공격을 시도하고, 이를 막기 위해 부팅 시마다system함수의 주소를 수백만 킬로미터(난수) 떨어진 곳으로 날려버리는 ASLR의 방어술을 뜯어봅니다.
- Implement: 0~10000 사이의 임의의 시작 주소(Base Offset)를 난수로 결정하는 가상의 메모리 맵 객체를 만들고, 해커 스크립트가
0x8048000(고정 주소)에 위치할 거라 믿고 때린 공격이 번번이 메모리 미스(Miss)를 내며 격추당하는 ASLR 확률 방어 테스트 구현.
Practical
Core Topic 03: ROP (Return-Oriented Programming)와 가젯(Gadget) 조립
- Why to Learn: W^X와 ASLR 방어선마저 뚫어버리는 현대 해킹의 꽃, 즉 내 코드를 주입하지 않고 상대방의 코드 조각(Gadget)들을 기괴하게 엮어 프랑켄슈타인을 만들어내는 ROP의 마법적 기하학을 장악하기 위함입니다.
- What to Learn:
- Concepts: ROP(Return-Oriented Programming), 가젯(Gadgets), ROP 체인(Chain).
- Skills:
pop rdi; ret같은 레지스터 제어 가젯 탐색, 스택 피버팅(Stack Pivoting). - Tools: ROPgadget, pwntools 툴킷.
- Trade-offs: 소프트웨어 취약점이 터졌을 때 ROP 체인을 막아보겠다고 가젯을 찾기 힘들게 바이너리를 꼬아버리는 난독화(Obfuscation) vs 난독화로 인해 프로그램 용량이 비대해지고 브랜치 예측이 깨져 CPU 성능이 통째로 깎여나가는 보안-성능 딜레마.
- How to Learn:
- 1단계: 바이너리 실행 파일 안에 존재하는 수십만 줄의 어셈블리 코드 중에서, 유용한 명령 한 줄과 꼬리에
ret가 붙어있는 조각(pop rax; ret등)들을 핀셋으로 집어내는(가젯 수집) 해커의 정보 수집 단계를 해부합니다. - 2단계: 해커가 가짜 스택을 만들어놓고 거기에 [가젯1 주소] [가젯1에 먹일 데이터] [가젯2 주소] 순서로 쫙 깔아두면, CPU가 첫 가젯을 실행하고
ret를 칠 때마다 스택을 따라 징검다리 건너듯 가젯2, 가젯3으로 미친 듯이 점프하며 해커가 원하는 거대한 프로그램(쉘 획득)이 완성되는 경이로운 조립 역학을 뜯어봅니다.
- 1단계: 바이너리 실행 파일 안에 존재하는 수십만 줄의 어셈블리 코드 중에서, 유용한 명령 한 줄과 꼬리에
- Implement: 파이썬 리스트 배열 안에
Gadget_1(print),Gadget_2(add),Gadget_3(exit)객체의 가짜 번지를 딕셔너리로 넣어두고. 해커가 작성한 ROP 스택 배열(Payload)을 CPU 루프에 먹였을 때, 함수 호출(call) 없이 오직ret명령에 의한 스택 팝(pop)만으로 3개의 함수가 순서대로 불려 나가는 논리 사슬(Chain) 궤적을 콘솔에 덤프.
Advanced
Core Topic 04: 하드웨어 지원 제어 흐름 무결성 (CFI, Shadow Stack & BTI)
- Why to Learn: 소프트웨어 레벨의 방어(ASLR)가 정보 유출(Leak) 한 방에 무너지는 한계를 직시하고, "애초에 점프할 자격이 없는 곳으로는 절대 점프하지 마!"라고 CPU 실리콘에 강제로 족쇄를 채워 ROP를 원천 봉쇄하는 인텔과 ARM의 최신 아키텍처를 통달하기 위해서입니다.
- What to Learn:
- Concepts: 제어 흐름 무결성(Control Flow Integrity, CFI), 섀도우 스택(Shadow Stack, Intel CET), 분기 타겟 식별(BTI, ARM PAC).
- Skills: 포인터 인증(Pointer Authentication, PAC), 전방향(Forward-edge) / 후방향(Backward-edge) 방어.
- Tools: 컴파일러 CFI 분기 태깅.
- Trade-offs: 섀도우 스택을 유지하기 위해 함수 콜을 할 때마다 스택 메모리를 2군데(일반 스택, 그림자 스택)에 써야 하는 미세한 메모리 대역폭 낭비 vs ROP 공격을 하드웨어 칩 레벨에서 100% 확률로 짓이겨버리는 우주 방어력의 획득.
- How to Learn:
- 1단계: 후방향 방어(Shadow Stack): 함수를 부를 때 리턴 주소를 일반 스택뿐만 아니라, 해커가 절대 덮어쓸 수 없는(하드웨어 격리) 섀도우 스택에 몰래 복사해 두고, 리턴(
ret)할 때 이 두 값을 꺼내어 비교(Compare)해서 값이 다르면 즉시 CPU를 Halt(종료)시켜버리는 인텔 CET 물리 역학을 해부합니다. - 2단계: 전방향 방어(ARM BTI / PAC): 함수 포인터를 변수에 저장할 때 포인터 주소 상위 비트에 암호학적 서명(PAC)을 박아넣고, 점프하기 직전 그 서명을 검증하여 해커가 함수 포인터를 다른 ROP 가젯으로 바꿔치기(조작)했는지 하드웨어가 0.1ns 만에 쳐내는 인증 로직을 뜯어봅니다.
- 1단계: 후방향 방어(Shadow Stack): 함수를 부를 때 리턴 주소를 일반 스택뿐만 아니라, 해커가 절대 덮어쓸 수 없는(하드웨어 격리) 섀도우 스택에 몰래 복사해 두고, 리턴(
- Implement: 일반
Stack(List)과Shadow_Stack(List)두 개를 가진 가상 CPU 환경을 구현.Call명령 시 두 스택에 동시에 리턴 주소를 PUSH 합니다. 이후 해커 모듈이 일반 스택의 리턴 주소만 악의적으로 덮어쓴 뒤Ret명령을 발동하면, 하드웨어가 두 스택의 POP 값을 비교하다가 불일치를 띄우고Security_Violation_Exception을 터트리며 방어하는 CFI 시뮬레이터 작성.
7. Terminology
8. References
Primary
- [P1] CS2023 - AR/System Security Hardware Support — Core requirements.
- [P3] CyBOK v1.1 - Hardware Security / Memory and Control Flow Integrity — Main standard.
Secondary
- [Practical Control Flow Integrity & Hardware Support] — Academic research on CET/CFI.
- [A Guide to Control-flow Enforcement Technology] Intel — Official technical guide.
Industry
- [ARMv8.5-A Memory Tagging Extension (MTE) Whitepaper] — Industry standard for spatial safety.
- [Microsoft Windows Hardware-enforced Stack Protection] — OS integration of MCP.
9. Final Checklist
Primary
- '가상 메모리' 페이지 테이블에서 유저/커널 권한 비트(U/S)가 어떻게 하드웨어적으로 OS 붕괴를 물리적으로 차단하는지 서술 가능한가? (P1)
- NX 비트가 하드웨어 명령어 인출(Fetch) 유닛의 연산을 어떻게 물리적으로 무력화(Neutralize) 시키는지 입증할 수 있는 가? (P1)
Secondary
- '섀도우 스택'이 일반 메모리 접근 명령어(
mov,st)로는 왜 접근이 불가능하게 설계되어야만 하는지 보안상의 근거를 소통 가능한가? - ROP(Return-oriented Programming) 공격이 하드웨어 기반 CFI가 적용된 환경에서 왜 '올바른 체인'을 형성하지 못하고 차단되는지 증명 가능한가?
Industry
- 항공우주나 의료 기기용 프로세서 설계 시, 메모리 오염에 의한 시스템 폭주를 MCP 기술로 어떻게 초단위(Real-time)로 방어할지 제안할 수 있는 가? (SFIA)
- 벤치마킹 도구(Benchmark suites)에서 하드웨어 보안 기능(CET 등) 활성화에 따른 성능 패널티를 정량화하고 수용 가능한 범위를 도출할 수 있는 가?