← 목록으로

패킹과 언패킹: 실행 파일을 압축/암호화해서 숨기기

[Rev] 리버싱 · 작성: 2026-07-19 19:32:50 · 조회 1

패킹(Packing)은 원본 실행 파일을 압축하거나 암호화해서 별도의 스텁(stub) 코드로 감싸는 기법이다. 원래는 파일 크기를 줄이려는 목적이었지만, 정적 분석(strings, 디스어셈블)을 무력화하는 효과가 있어서 악성코드에서 분석 회피 목적으로 널리 쓰인다.

동작 원리

패킹된 파일을 실행하면:

  1. 겉으로 보이는 코드(스텁)가 먼저 실행된다
  2. 스텁이 메모리 상에서 원본 코드를 압축 해제/복호화한다
  3. 복호화된 원본 코드가 실행 가능한 메모리 영역에 써지고, 그쪽으로 실행 흐름이 넘어간다 (Original Entry Point, OEP)

파일 상태에서는 원본 코드가 아예 존재하지 않고, 실행되는 순간에만 메모리에 나타난다. 그래서 파일을 그대로 디스어셈블해봐야 스텁 코드만 보이고 strings도 의미 있는 문자열을 거의 못 찾는다.

패커 식별

# Detect It Easy(DIE) — GUI/CLI 모두 지원, 패커/컴파일러 시그니처 DB 보유
diec ./target

# PEiD (Windows, 구식이지만 여전히 참고됨)

엔트로피(entropy)가 비정상적으로 높은 섹션이 있으면 압축/암호화되어 있다는 신호다. 많은 도구가 섹션별 엔트로피를 같이 보여준다.

언패킹 방법

1. 알려진 패커라면 전용 언패커 사용

UPX는 가장 흔한 오픈소스 패커라서 자체 언패킹 옵션이 있다.

upx -d ./packed_target

2. 커스텀/상용 패커는 동적으로 덤프

전용 언패커가 없다면, 실행시켜서 원본 코드가 메모리에 다 풀린 시점(OEP 도달 시점)을 잡아 그 순간의 메모리를 통째로 덤프한다.

  1. 디버거로 실행하면서 VirtualAlloc(Windows) / mmap(Linux)처럼 새 실행 가능 메모리를 할당하는 API에 브레이크포인트를 건다
  2. 압축 해제가 끝나고 그 메모리 영역으로 점프하는 시점(OEP)을 찾는다 — 보통 스택이 갑자기 큰 폭으로 바뀌거나(pushad/popad 패턴), 방금 풀린 영역으로의 jmp가 나타난다
  3. OEP에서 프로세스 메모리를 덤프한다 (Windows는 Scylla, PE-sieve 같은 도구가 이 과정을 도와줌)
  4. 덤프한 이미지는 Import Table이 깨져있는 경우가 많아서, IAT(Import Address Table) 복구 작업이 추가로 필요할 수 있다

3. 그냥 동적 분석으로 우회

파일을 완전히 언패킹하지 않고, 그냥 디버거/Frida로 실행 중인 프로세스의 동작만 관찰하는 것으로 충분한 경우도 많다. 목적이 "정적 코드를 완전히 복원하는 것"이 아니라 "무슨 동작을 하는지 아는 것"이라면 이쪽이 훨씬 빠르다.

실전 팁

패킹된 파일을 만나면 먼저 알려진 패커인지부터 확인하고(DIE), 알려진 패커면 전용 도구로 몇 초 만에 끝나는 경우가 많다. 커스텀 패커일 때만 위의 수동 언패킹 과정이 필요하다 — 순서를 거꾸로 하면 시간을 많이 버린다.

리버싱 카테고리의 글 (5/11)

  1. 리버싱이란 무엇인가: 정적 분석 기초
  2. 어셈블리어 읽기 기초 (x86-64)
  3. 동적 분석: 디버거로 실행 흐름 추적하기
  4. 안티 디버깅 / 안티 리버싱 기법과 우회
  5. 패킹과 언패킹: 실행 파일을 압축/암호화해서 숨기기
  6. Frida로 동적 계측/후킹하기
  7. 안드로이드 앱 리버싱: APK 분석 기초
  8. iOS 앱 리버싱 기초
  9. 크랙미(Crackme) 실습 방법론
  10. PE 포맷 내부 구조: Windows 실행 파일 뜯어보기
  11. 코드 난독화 해제: Control Flow Flattening 분석하기
← 안티 디버깅 / 안티 리버싱 기법과 우회 Frida로 동적 계측/후킹하기 →