메모리 해킹기법 방어(버퍼 오버플로우)

버퍼 오버플로우는 주로 C/C++ 언어에서의 경계 검사 부재를 이용해,
스택 프레임을 덮어쓰고 RET 주소를 조작하여 공격자가 원하는 코드를 실행하는 공격입니다.

이를 막기 위해 운영체제, 컴파일러, 하드웨어 등 다양한 계층에서 다음과 같은 보호기법이 사용됩니다.

✅ 주요 오버플로우 방어 기법 8가지 (정리표 먼저 보기)

기법명보호 대상주체설명
Stack Canary스택런타임RET 주소 앞에 감시값 삽입
StackGuard스택컴파일러Stack Canary를 구현한 기법
StackShield스택컴파일러RET 주소를 별도 저장해 보호
ASLR메모리 전체운영체제주소 무작위화
DEP/NX bit메모리 영역하드웨어+OS실행 불가 영역 지정
PIE실행파일컴파일러+OS코드 영역 자체도 랜덤화
Fortify Source함수 호출컴파일러위험 함수 감지 및 보호
CFI흐름 제어컴파일러+OS비정상 함수 호출 차단

1. Stack Canary

  • 위치: 스택 내부
  • 도입 계층: 런타임
  • 목적: 스택 프레임 보호

✅ 동작 원리

  1. 함수 호출 시, 지역 변수와 RET 주소 사이에 Canary 값 삽입
  2. 함수 종료 시 Canary 값이 바뀌었는지 확인
  3. 값이 바뀌었으면 스택 오버플로우 공격으로 간주 후 종료

✅ 유형 (GCC 기준)

  • -fstack-protector: 기본 보호 (대상 함수 제한)
  • -fstack-protector-strong: 더 많은 함수 보호
  • -fstack-protector-all: 모든 함수 보호

2. StackGuard

  • Stack Canary 기법의 구현체 중 하나
  • GCC에 통합된 형태로 구현되었고, -fstack-protector 옵션이 사실상 StackGuard입니다.

✅ 핵심 특징

  • 스택 프레임마다 랜덤 Canary 삽입
  • Canary가 손상되면 __stack_chk_fail() 호출로 비정상 종료

3. StackShield

  • RET 주소를 별도의 안전한 공간에 백업해 두는 방식

✅ 동작 방식

  1. 함수 진입 시 RET 주소를 StackShield Table에 저장
  2. 함수 리턴 시, 원래 스택에 있는 RET 주소와 비교
  3. 다르면 프로그램 종료

✅ 장점

  • Canary처럼 변조 감지보다 RET 보호를 직접적으로 수행
  • Canary 우회 공격에 강함

❌ 단점

  • 구현 복잡도 ↑
  • GCC 최신 버전에서는 기본 미지원

4. ASLR (Address Space Layout Randomization)

  • 실행 중인 프로그램의 메모리 구조를 매번 다르게 배치하는 OS 보호 기법

✅ 보호 대상

  • 스택, 힙, 라이브러리, 코드 등 모든 주소 공간

✅ 효과

  • 공격자가 정확한 주소를 알 수 없어, RET 덮기 실패 확률 ↑
  • 쉘코드 주소 예측 불가능

❌ 우회 가능성

  • 정보 유출(vulnerability leak)이 발생하면 ASLR 무력화 가능
  • 일부 환경(Wine, 일부 Windows 환경)에서는 제한적으로 동작

5. DEP / NX-bit (Data Execution Prevention)

  • 데이터 영역을 실행하지 못하게 막는 하드웨어+OS 보안 기술

✅ 주요 원리

  • 스택/힙/데이터 영역에 NX(Non-Executable) 속성 부여
  • 쉘코드를 올려도 실행 불가

✅ 시스템 적용 예

  • Windows: bcdedit /set nx AlwaysOn
  • Linux: exec-shield, PaX, grsecurity

❌ 우회 가능성

  • ROP (Return-Oriented Programming) 등의 기법으로 우회 가능

6. PIE (Position Independent Executable)

실행 파일 자체를 ASLR처럼 주소 무작위화 가능하게 컴파일하는 방식

✅ PIE vs Non-PIE

항목PIENon-PIE
주소매 실행 시 바뀜고정 주소
보안ASLR 완전 적용ASLR 제한 적용

✅ 사용법 (GCC)

gcc -fPIE -pie hello.c -o hello

→ 실행할 때마다 .text 영역 주소도 바뀜

7. Fortify Source

위험 함수(strcpy, gets 등) 사용 시 자동으로 보안 기능 추가

✅ 특징

  • 컴파일러 레벨 보호
  • 컴파일 시 버퍼 크기를 비교해서 경고 또는 종료 처리

✅ 사용법

gcc -D_FORTIFY_SOURCE=2 -O2 example.c -o example

최적화(-O2 이상) 옵션과 함께 사용해야 활성화됨

8. CFI (Control Flow Integrity)

프로그램 흐름이 예상된 제어 흐름을 벗어나지 않도록 감시하는 기술

✅ 원리

  • 함수 포인터, RET 주소, vtable 등의 호출 흐름을 화이트리스트 기반으로 검증
  • 비정상 호출 시 차단

✅ 적용 예

  • LLVM의 CFI, MS의 Control Flow Guard(CFG), Google의 IFCC

✅ 시각 요약: 스택 보호 중심 구조도

[ 지역 변수 ]  ← 공격자 입력 가능
[ Stack Canary ] ← 변조 감시
[ RET 주소 ] ← 공격자가 노리는 대상
[ StackShield Table ] ← 백업된 RET
  • Canary: 감시
  • Shield: 백업
  • DEP: 실행 차단
  • ASLR: 주소 예측 차단

🔚 마무리 요약표

기법범주주체요약
Stack Canary / StackGuard스택 보호컴파일러/런타임감시값을 통해 RET 덮기 탐지
StackShield스택 보호컴파일러RET 주소 자체를 별도 저장
ASLR메모리 난수화운영체제주소 무작위화
DEP (NX-bit)메모리 실행 차단하드웨어/OS스택/힙에서 코드 실행 차단
PIE실행파일 난수화컴파일러코드 영역 자체의 위치 무작위화
Fortify Source함수 호출 보호컴파일러위험 함수 감지 및 대체
CFI흐름 보호컴파일러/OS비정상 함수 호출 차단

9. Stack Canary / StackGuard

🧨 우회기법

방법설명
Canary 유출포인터 누출/format string 취약점 등을 이용해 Canary 값을 유출하고 동일하게 덮어씀
Partial OverwriteRET 주소만 정확히 덮고, Canary는 건드리지 않도록 정밀하게 오버플로우
Non-RET 공격Canary는 RET만 보호하므로, 함수 포인터, GOT, vtable 등 다른 제어 지점 공격

🔍 탐지기법

방법설명
로그 분석__stack_chk_fail() 호출 여부 (SIGABRT 발생) 로그 추적
ASAN/UBSAN 사용Address Sanitizer 등으로 Canary 손상 여부 추적 가능
스택 프레임 분석GDB로 함수 리턴 전/후 Canary 값 비교

10. StackShield

🧨 우회기법

방법설명
간접 호출 우회StackShield는 직접적인 RET 덮기만 보호하므로,
함수 포인터, GOT를 노리는 공격은 우회 가능
컴파일러 우회StackShield가 적용되지 않은 바이너리나 외부 라이브러리 호출로 우회

🔍 탐지기법

방법설명
RET 주소 위조 감지StackShield Table과 스택의 RET 불일치 확인
공격 시 로그/코어덤프 분석RET Jump 타겟 주소가 비정상적이면 의심
정적 분석 도구 사용Ghidra, IDA로 RET 흐름 확인

11. ASLR

🧨 우회기법

방법설명
Information Leak포인터 누수, format string, /proc/self/maps 등으로 주소 유출 후 우회
Brute Force재시도 가능한 환경에서 반복 실행 (ex: CGI 서비스, 다중 요청 등)
Relative AddressingPIE 미적용 바이너리에서 .text 주소는 고정 → 오프셋 계산 가능

🔍 탐지기법

방법설명
메모리 덤프 분석maps 파일이나 core dump에서 base 주소가 변하는지 확인
시스템 호출 감시mmap, execve 호출 시 주소 랜덤 여부 검사
로그 내 실패 반복 확인반복적인 segmentation fault → brute force 추정 가능

12. DEP / NX-bit

🧨 우회기법

방법설명
ROP (Return-Oriented Programming)실행 가능한 기존 코드 조각(gadget)을 연결해 쉘코드 없이 명령 수행
JOP (Jump-Oriented Programming)RET 대신 JMP를 이용한 우회 공격
RWX 메모리 확보mmap, VirtualAlloc 등을 통해 실행 가능한 메모리 확보

🔍 탐지기법

방법설명
ROP Chain 감지연속된 RET 패턴, 스택의 gadget 주소 확인
메모리 실행 속성 모니터링페이지 속성 변화 감시 (Windows에서는 EMET 등 활용)
동적 분석 도구 사용Cuckoo Sandbox, Valgrind 등으로 메모리 접근 추적

13. PIE

🧨 우회기법

방법설명
정보 유출GOT, 함수 포인터 등으로 base address 추출
동일 바이너리 재사용PIE 없이 빌드된 구버전 또는 외부 공유 라이브러리 악용
Relocation LeakELF의 PLT/GOT를 통해 offset 계산

🔍 탐지기법

방법설명
ELF 헤더 확인readelf -h, checksec 명령어로 PIE 적용 여부 확인
실행 시 base address 추적여러 번 실행하여 .text 주소 변화 여부 확인
정적 분석 도구Ghidra에서 PIE 적용된 코드의 주소가 고정되지 않음 확인 가능

14. Fortify Source

🧨 우회기법

방법설명
보호 대상 함수 외 사용보호되지 않은 memcpy, 직접 포인터 조작으로 우회
정적 링크 우회보호되지 않은 라이브러리 직접 링크
컴파일 시 우회-D_FORTIFY_SOURCE=0로 비활성화된 바이너리 사용

🔍 탐지기법

방법설명
소스 코드 분석취약한 함수 사용 여부 탐지 (strcpy 등)
컴파일 로그 확인보호된 함수는 내부적으로 __chk 함수로 변환됨
GDB 디버깅 중 SIGABRT 감지fortify 충돌 시 종료됨

15. CFI (Control Flow Integrity)

🧨 우회기법

방법설명
타입 일치 악용함수 포인터 타입만 맞으면 호출 가능 → 제한적 우회
vtable 변조C++ 가상 함수 테이블 위조 → 정적 검증 우회
해당 영역 제외 빌드CFI 적용되지 않은 바이너리 조작

🔍 탐지기법

방법설명
정적 분석 도구Clang CFI, LLVM Pass, BinDiff 등으로 흐름 무결성 분석
런타임 모니터링CFG 미스매치 로그 추적 (Windows에서는 CFG 로그 발생)
Fuzzing함수 호출 흐름을 무작위로 유도해 미스매치 유도

🔚 종합 정리표

기법우회기법탐지기법
Stack CanaryCanary 유출, Partial Overwrite__stack_chk_fail, Canary 값 비교
StackShieldRET 이외 제어 공격RET 백업/실제 비교
ASLR주소 유출, Brute ForceBase 주소 변화, maps 확인
DEPROP, JOP, mmap 사용Gadget 감지, 메모리 실행 속성 추적
PIEGOT, PLT leakchecksec, .text 주소 확인
Fortify Source비보호 함수, 빌드 옵션 우회__chk 함수 확인, 소스 분석
CFI타입 우회, vtable 변조런타임 미스매치, CFG 로그 분석

Leave a Comment