[Rev] 리버싱 · 작성: 2026-07-19 19:32:50 · 수정: 2026-07-21 23:26:47 · 조회 19
정적 분석을 "실행 안 하고 코드만 보는 것"이라고만 알면, 실제로 무엇을 순서대로 봐야 하는지가 안 잡힌다. 이 글은 바이너리 파일 하나가 실제로 어떤 구조로 이루어져 있고, 그 구조를 어떤 순서로 읽어야 실행 흐름을 재구성할 수 있는지를 ELF 포맷 기준으로 따라간다.
리눅스 실행 파일(ELF)은 크게 세 부분으로 이뤄진다.
readelf -h로 확인..text(실행 코드), .data(초기화된 전역 변수), .bss(초기화 안 된 전역 변수), .rodata(문자열 상수), .symtab/.dynsym(심볼 이름 테이블), .plt/.got(동적 링킹용 테이블)처럼 파일을 논리적 구역으로 나눈다. readelf -S로 목록 확인.execve)가 이 파일을 메모리에 어떻게 매핑할지(어느 세그먼트가 실행 가능/쓰기 가능인지)를 정의 — readelf -l, 이 정보가 바로 NX 비트가 세팅되는 근거다.file, checksec: 아키텍처, 스트리핑 여부, 보호 기법(카나리/NX/PIE/RELRO)부터 확인 — 뒤에서 어떤 익스플로잇 전략이 가능한지가 여기서 절반은 정해진다strings: 바이너리 안에 박혀있는 문자열을 훑는다 — 에러 메시지, 포맷 문자열, 하드코딩된 경로/URL, 디버그 심볼 흔적이 여기서 바로 드러나는 경우가 많다nm, readelf -s): 함수 이름이 스트리핑되지 않았다면, main, vuln, win 같은 함수 이름이 그대로 보인다 — 어디부터 봐야 할지 우선순위를 정하는 데 결정적이다objdump -d / IDA / Ghidra로 디스어셈블/디컴파일: 함수 단위로 로직을 재구성. Ghidra의 디컴파일러는 어셈블리를 C와 비슷한 의사코드로 재구성해줘서, 어셈블리어 읽기 기초 글에서 다루는 명령어 하나하나를 직접 추적하는 부담을 크게 줄여준다gets, strcpy, system 등)를 쓰는지 보면, 취약점 후보가 뭔지 감이 온다 — gets가 import되어 있다면 그 자체로 스택 오버플로우 후보 지점이다바이너리 익스플로잇(스택 버퍼 오버플로우 등)을 시도하기 전에, 정적 분석으로 다음을 미리 알아둬야 한다 — 어떤 함수가 취약한지(strings/objdump), gadget이 어디 있는지(objdump -d, ROPgadget), 어떤 보호 기법이 걸려있는지(checksec). 동적 분석(디버거로 실행하며 크래시 확인)은 정적 분석으로 세운 가설을 검증하는 두 번째 단계에 가깝다 — 순서를 거꾸로 하면(무작정 디버거부터 실행) 방향 없이 헤매게 된다.
strings/objdump가 의미 있는 정보를 거의 못 보여준다면, 먼저 패킹과 언패킹 글에서 다루는 언패킹 과정을 거쳐야 정적 분석 자체가 성립한다정적 분석을 "코드를 눈으로 읽는 것"이 아니라 **"파일 포맷이 정의한 구조를 순서대로 파싱해서, 실행 전에 실행 흐름의 지도를 미리 그려두는 작업"**으로 이해하면, 왜 리버싱의 첫 단계가 항상 헤더·섹션·심볼 확인부터 시작하는지가 같은 논리로 설명된다.