checksec은 바이너리 파일에 적용된 보안 보호 기법을 확인하는 도구로 시스템 해킹이나 CTF 문제를 풀 때 가장 먼저 하는 일은 checksec 명령어를 통해 바이너리에 적용된 보안 기법을 확인하는 것이다.
checksec가 아래의 보호기법을 탐지하는 방법과 아래 기법들이 무엇을 의미하는지 알아보자

1. Arch (Architecture), Stripped, Debuginfo
- Arch :CPU 아키텍처와 데이터 저장 방식(Endian)을 나타낸다.(예: amd64-64-little )
- Stripped: 심볼 테이블 제거 여부를 나타낸다. No라면 함수 이름이나 변수명이 살아있다.
- Debuginfo: 디버깅 정보 포함 여부이다.
2. RELRO (Relocation Read-Only)
RELRO란?
GOT overwrite(함수 호출 주소를 변조하여 공격자가 원하는 코드를 실행하는 공격)를 보호하기 위한 기법이다.
GOT는 프로그램이 실행되는 동안 외부 라이브러리 함수(예: printf, scanf 등)의 실제 메모리 주소를 저장하는 테이블이다. 이 테이블을 덮어씌워 해커가 원하는 함수를 실행하거나 문자열을 저장할 수 있기 때문에 got의 권한을 조정해 방어한다.
적용 범위에 따라 RELRO는 partal RELRO와 Full RELRO로 나뉜다.
#PLT GOT(예정)
partal RELRO
GOT를 프로그램 bss 위로 주소를 옮겨서 전역 변수 Overflow를 통한 GOT overwrite를 방지한다.
gcc -o output source.c -Wl,-z,relro
Full RELRO
GOT의 모든 심볼 주소를 컴파일 시에 채우고 GOT를 읽기 전용으로 만든다.
gcc -o output source.c -Wl,-z,relro,-z,now
컴파일 옵션
- -Wl: 뒤에 오는 옵션들을 콤마(,)로 구분하여 링커(Linker)에게 전달하라는 뜻이다.
- -z: 링커에게 특정 키워드(relro, now 등)를 전달할 때 사용하는 플래그이다.
- relro: 메모리에 로드된 후 재배치(Relocation) 영역을 읽기 전용으로 만든다.
- now: 함수 호출 시점이 아니라, 프로그램 시작 시점에 모든 심볼을 즉시 바인딩한다. (Full RELRO의 핵심)
Checksec 탐지 로직
GNU_RELRO와 Full RELRO, Partial RELRO를 헤더에서 찾아 RELRO를 확인한다.
# check for RELRO support
if [[ $(${readelf} -l "${1}" 2> /dev/null) =~ "no program headers" ]]; then
echo_message '\033[32mN/A \033[m ' 'N/A,' '<file relro="n/a"' " \"${1}\": { \"relro\":\"n/a\","
elif ${readelf} -l "${1}" 2> /dev/null | grep -q 'GNU_RELRO'; then
if ${readelf} -d "${1}" 2> /dev/null | grep -q 'BIND_NOW' || ! ${readelf} -l "${1}" 2> /dev/null | grep -q '\.got\.plt'; then
echo_message '\033[32mFull RELRO \033[m ' 'Full RELRO,' '<file relro="full"' " \"${1}\": { \"relro\":\"full\","
else
echo_message '\033[33mPartial RELRO\033[m ' 'Partial RELRO,' '<file relro="partial"' " \"${1}\": { \"relro\":\"partial\","
fi
else
echo_message '\033[31mNo RELRO \033[m ' 'No RELRO,' '<file relro="no"' " \"${1}\": { \"relro\":\"no\","
fi
3. Stack Canary
스택 카나리란?
Stack Canary는 스택 버퍼 오버플로우(BOF)를 탐지하기 위한 기법이다.
카나리는 함수 프롤로그에 스택에 fs:0x28의 값을 저장하고 함수 애필로그에 fs:0x28과 저장한 스택을 비교해 BOF를 탐지한다.


생성 조건
컴파일러는 오버헤드를 줄이기 위해 모든 함수에 카나리를 넣지 않는다.
- 지역 배열이 선언
- 지역 변수의 주소를 참조(&)하는 경우
우회 전략
- TLS Leak / Master Canary: 스레드를 사용하는 환경에서 TLS 주소를 알아내 원본 카나리 값을 읽거나 변조한다.
- Stack Canary Leak: Format String Bug를 이용해 스택에 있는 카나리 값을 유출한 뒤, BOF 시 해당 값을 그대로 덮어씌운다.
컴파일 옵션
- 끄기 (Disable)
- 옵션 : gcc에서"-fno-stack-protector"으로 카나리를 끌 수 있다.
- 켜기 (Enable): -fstack-protector-strong
Checksec 탐지 로직
심볼 테이블에 스택 보호 관련 함수가 문자열을 확인한다.
# check for stack canary support
if ${readelf} -s "${use_dynamic}" "${1}" 2> /dev/null | grep " UND " | grep -Eq '__stack_chk_fail|__stack_chk_guard|__intel_security_cookie'; then
echo_message '\033[32mCanary found \033[m ' 'Canary found,' ' canary="yes"' '"canary":"yes",'
else
echo_message '\033[31mNo canary found\033[m ' 'No Canary found,' ' canary="no"' '"canary":"no",'
fi
4. NX (No-Execute) / DEP (Data Execution Prevention)
NX는 메모리의 스택이나 힙 영역에 실행 권한(Execute)을 제거하여 쉘코드 실행을 방지하기 위한 기법이다.
스택(Stack)과 힙(Heap) 영역에는 실행 권한(Execute)이 없다. 따라서 쉘코드를 스택에 올리고 실행 흐름을 스택으로 돌려도 실행되지 않고 강제 종료된다.


우회 전략 (Bypass)
- 실행 권한이 있는 코드 영역(Code Segment)이나 라이브러리 함수(system 등)를 이용한다.
- RTL (Return to Libc) 또는 ROP (Return Oriented Programming) 기법이 필수적이다.
컴파일 옵션
- 켜기 (기본): -z,noexecstack
- 끄기: -z,execstack
Checksec 탐지 로직
GNU_STACK 헤더의 권한 설정을 확인한다.
# check for NX support
# shellcheck disable=SC2126
if [[ $(${readelf} -l "${1}" 2> /dev/null) =~ "no program headers" ]]; then
echo_message '\033[32mN/A \033[m ' 'N/A,' ' nx="n/a"' '"nx":"n/a",'
elif ${readelf} -l "${1}" 2> /dev/null | grep -q 'GNU_STACK'; then
if [[ $(${readelf} -l "${1}" 2> /dev/null | grep 'GNU_STACK' | grep -oP '(?<=0x).*(?=RW )' | grep -o . | sort -u | tr -d '\n') != " 0x" ]]; then
echo_message '\033[31mNX disabled\033[m ' 'NX disabled,' ' nx="no"' '"nx":"no",'
else
echo_message '\033[32mNX enabled \033[m ' 'NX enabled,' ' nx="yes"' '"nx":"yes",'
fi
else
echo_message '\033[31mNX disabled\033[m ' 'NX disabled,' ' nx="no"' '"nx":"no",'
fi
5. PIE (Position Independent Executable)
PIE는 바이너리 코드 영역의 주소를 랜덤 화하여 고정된 주소를 이용한 공격을 막는 기법이다. ASLR을 코드 영역까지 확장한 개념으로 코드 영역까지 주소를 랜덤화 한다.
ASLR은 커널단에서 설정하는 보호 기법이다. 프로그램이 실행될 때마다 라이브러리, 스택, 힙 영역의 시작 주소를 랜덤하게 변경하여 공격자가 메모리 주소를 예측하기 어렵게 만든다.
PIE는 컴파일러가 바이너리를 만들 때 적용하는 보안 옵션이다. PIE가 적용된 바이너리는 고정된 주소가 아닌, 실행 시 로더에 의해 결정된 임의의 베이스 주소에 로드된다.
- ASLR (OS 설정): 스택, 힙, 라이브러리 영역의 주소를 랜덤화 (/proc/sys/kernel/randomize_va_space).
- 0: 해제, 1: 스택/라이브러리 랜덤, 2: 전체 랜덤(힙 포함)
- PIE (컴파일러 설정): ASLR을 코드 영역(Code Base)까지 확장한 개념.
- 켜기: -fPIE -pie
- 끄기: -no-pie
우회 전략 (Bypass)
- Base Address Leak: FSB 등을 통해 스택에 남은 반환 주소 등을 유출하여 코드 베이스 주소를 구한다.
- Partial Overwrite: 주소의 하위 12비트는 변하지 않는 특성을 이용해, 하위 바이트만 덮어써서 다른 함수로 흐름을 돌힌다.
Checksec 탐지 로직
ELF 파일의 타입을 확인한다.
# check for PIE support
if ${readelf} -h "${1}" 2> /dev/null | grep -q 'Type:[[:space:]]*EXEC'; then
echo_message '\033[31mNo PIE \033[m ' 'No PIE,' ' pie="no"' '"pie":"no",'
elif ${readelf} -h "${1}" 2> /dev/null | grep -q 'Type:[[:space:]]*DYN'; then
if ${readelf} -d "${1}" 2> /dev/null | grep -q 'DEBUG'; then
echo_message '\033[32mPIE enabled \033[m ' 'PIE enabled,' ' pie="yes"' '"pie":"yes",'
else
echo_message '\033[33mDSO \033[m ' 'DSO,' ' pie="dso"' '"pie":"dso",'
fi
elif ${readelf} -h "${1}" 2> /dev/null | grep -q 'Type:[[:space:]]*REL'; then
echo_message '\033[33mREL \033[m ' 'REL,' ' pie="rel"' '"pie":"rel",'
else
echo_message '\033[33mNot an ELF file\033[m ' 'Not an ELF file,' ' pie="not_elf"' '"pie":"not_elf",'
fi
6. Stack (Executable Stack), RWX (Read-Write-Execute)
- Stack (Executable Stack): NX 설정이 모호하거나 커널 호환성 문제로 스택 실행 권한이 살아있는 경우이다. 쉘코드를 바로 실행할 수 있어 매우 취약하다.
- RWX Segments: 읽기(Read), 쓰기(Write), 실행(Execute) 권한을 동시에 가진 세그먼트가 존재한다는 뜻이다. 이곳에 쉘코드를 쓰고 바로 실행할 수 있다.
공략 가이드
| 적용된 보호 기법 | 공략 기법 |
| 보호 기법 없음 | Shellcode Injection (쉘코드 주입 후 실행) |
| NX | RTL (Return to Libc) 또는 ROP (Return Oriented Programming) |
| NX + Canary | Canary Leak (카나리 유출 후 복구) + ROP |
| NX + Canary + PIE | Memory Leak (Base 주소 & 카나리 유출) + ROP |
| Full RELRO | Hook Overwrite |
참고 자료:
https://github.com/slimm609/checksec/blob/main/checksec.bash
checksec/checksec.bash at main · slimm609/checksec
Checksec. Contribute to slimm609/checksec development by creating an account on GitHub.
github.com
https://bpsecblog.wordpress.com/2016/06/28/memory_protect_linux_5/
linux 환경에서의 메모리 보호기법을 알아보자 – checksec.sh
salen 선원이 linux 메모리 보호기법 시리즈에서 주구장창 등장하는 checksec.sh 를 자세히 들여다 보았습니다. 후다닥 퍼다 날라봅니다 :3 1. chechsec.sh 개요 지금껏 우리는 예제 프로그램을 만들고, 예
bpsecblog.wordpress.com
https://chp747.tistory.com/215
어쩌다보니 시작한 checksec 분석글
어쩌다보니 시작한 checksec 분석글 맨날 checksec.sh 같은 툴을 사용해서 편하게 확인하다보니 도구가 없는 이런 상황에서는 어떻게 확인해야 할 지 생각이 안났다 zzzz (반성하도록 하자.)헤더 정보
chp747.tistory.com
'Security > 시스템해킹' 카테고리의 다른 글
| [System hacking] 시스템 보안 수업 후기 (0) | 2025.12.18 |
|---|---|
| [System hacking] FSB (0) | 2025.12.12 |