wintersnowaAa
Portable Executable - PE Header 본문
일단 PE 파일의 구조와는 별개로 PE 파일에 대해서 알아둬야할 것 같다...
PE 파일은 윈도우 실행파일로 인식이 강하고, 원래는 UNIX의 COFF라는 형태를 기반으로 만들어졌다고한다.
PE 파일을 통해서 알아낼 수 있는 정보로는 프로그램이 사용하는 API, DLL 등 프로그램, 프로세스가 다른 프로그램, 프로세스 혹은 자신이 정보를 사용하기 위해 필요한 내용을 알 수 있다.
종류는 4가지가 있다고 한다.
1. 실행 계열 : EXE, SCR
2. 라이브러리 계열 : DLL, OCX, CPL, DRV
3. 드라이버 계열 : SYS, VXD
4. 오브젝트 파일 계열 : OBJ
뭐...크게 신경써야할건 실행 파일의 EXE, 라이브러리의 DLL, 드라이버의 SYS, 오브젝트의 OBJ 정도가 있을듯하다.
가변적 크기를 갖는 구조에 약했지만, 최근 눈치가 빨라져서 괜찮지 않을까
시작해보자.
요건 집에 있던 windows 구조와 원리라는 책에서 나온 PE 파일 구조이다.
앞서 다른분이 포스팅해주신 구조와 비교하면, NT Header가 PE 헤더라고 이전에 불렸거나 파일 형태가 업데이트 되면서 바뀌었을 수도 있다. (집에 있는 책이 좀 예전꺼다.)
왼쪽이 실행 파일이고, 오른쪽은 실행 프로세스의 형태를 말한다.
실행 파일은 물리 오프셋으로 위치를 표현, 프로세스는 VA(Virtual Address)로 위치를 표현한다고 한다.
일단 지금은 PE 헤더 (책) = NT Header (다른분 포스팅) 으로 기준을 잡고 분석해보자.
http://wjradburn.com/software/
WJR Software - PEview (PE/COFF file viewer),...
Utilities (for use with Windows® XP operating system or later) PEview provides a quick and easy way to view the structure and content of 32-bit Portable Executable (PE) and Component Object File Format (COFF) files. This PE/COFF file viewer displays heade
wjradburn.com
원래대로라면 HxD로 일일히 분석했겠지만, 도구의 검증을 받기로 했다.
PEview를 설치하도록 하자.
1. DOS Header

일단 시작하기 위해서는 대상 exe 파일이 있어야한다.
그래서 PEview로 PEview.exe 를 분석하기로 했다. (사실 추천 받을라했는데 애들이 다 바쁜가보다...)

구조를 보면 정직하게 사진처럼 명확하게 나와있다.
DOS Header는 IMAGE_DOS_HEADER 라는 구조체를 사용해서 만들어진다.

PE 파일은 웬만해서는 WINNT.h 구조체를 따라 헤더를 만든다.

대부분 WORD로 2바이트 단위로 이루어져있으며, 마지막에 e_Ifanew 는 LONG 4바이트로 이루어져있다.
필드 이름 | 설명 | 실제 디스크 값 (리틀엔디안) |
e_magic | 매직넘버 | 0x4D5A (MZ 문자열이 보통 보인다.) |
e_cparhdr | 헤더 크기 (16바이트 단위) | 0x2 (0x20만큼의 크기를 IMAGE_DOS_HEADER가 가진다. 이후에는 MS-DOS Studb Program 영역이 들어온다.) |
e_lfanew | PE 헤더의 오프셋 | 0x60 (0x60부터 나오는 NT_Header 영역의 오프셋) |
다른 값들은 의미가 크게 없기도하고 실제 파일의 포맷과는 다르게 채워진 경우도 있는 것 같아 중요한 애들만 그때그때 찾아서 쓰려고한다.
2. MS-DOS Stub
DOS Stub 영역은 PE 파일에서 앞부분에 존재하는 작은 실행 코드 영역으로 MS-DOS에서 파일이 실행되었을 때의 부가 설명을 위해 존재한다...
DOS 환경에서 사용되던 MZ 파일 포맷을 Windows 환경에서도 그대로 가져오기 위해 PE 파일 또한 MZ 파일 포맷을 확장시켜 하위 호환성을 보장한채로 만들어졌다.
그 과정에서 DOS Header와 DOS Stub 또한 구조적으로 필수로 필요하게 되어서 함께 PE 파일 포맷에 내장되게 되었다.

만약 DOS 에서 실행된다면 PEview.exe는 Win32 Program! 이라는 문자열을 출력 후 프로그램을 종료하며, DOS 환경에서는 실행되지 않음을 보여줄 것이다.
사실 현재로서는 거의 안쓰이는 영역이라서 이정도만 보고 넘어가도록...하겠다...
3. NT Header (Signature, FILE_HEADER)

그 다음은 NT_HEADERS 영역으로 0x60 ~ 0x157로 총 0xF8 만큼의 크기를 갖는 영역이다.
시그니처와 IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER 를 한꺼번에 정리해보자.

처음 0x50450000 은 문자열 PE 를 가지며, 단순 시그니처 값이다.

IMAGE_FILE_HEADER 영역은 WIndows가 파일이 실행 가능한 구조인지 파악하고, 실행에 필요한 정보가 담긴 영역이다.
필드 이름 | 설명 | 실제 디스크 값 (리틀엔디안) |
Machine | 실행 대상 CPU 아키텍처 | 0x014C (32비트 Intel 아키텍처)![]() |
Number Of Sections | 섹션 갯수 | 0x5 |
Time Date Stamp | 생성 시간 (UNIX 기준) | 0x4DD1B0D7 (2011년 5월 16일 23시 18분 47초 UTC 기준) |
Pointer to Symbol Table |
심볼 테이블 위치 | 0x0 (현재는 거의 쓰이지 않음) |
Number of Symbols | 심볼 갯수 | 0x0 (현재는 거의 쓰이지 않음) |
Size of Optional Header |
뒤에 나오는 OPTIONAL_HEADER의 크기 | 0xE0 |
Characteristics | 실행 파일 속성 | 0x010F (0x0100 + 0x0008 + 0x0004 + 0x0002 + 0x0001) 32비트 아키텍처 + 지역 심볼 정보 제거 + 라인 번호 정보 제거 + 유효한 실행 파일 + 재배치 정보가 제거 ![]() |
4. NT Header (OPTIONAL_HEADER)

일일히 다 적기에는 많으니....
내용을 보면서 중요한 것만 보자.

OPTIONAL_HEADER 값
필드 이름 | 설명 | 실제 디스크 값 (리틀엔디안) |
Magic | 매직넘버 | 0x010B (PE32로 32비트 기준이라는 뜻이다. 다른 값도 있다. 0x20B는 64비트 기준이라는 뜻이다.) |
Address of Entry Point |
실행 시작 RVA | 0x1000 |
Image Base | 메모리에 로드될 기본 주소 | 0x4000000 |
Section Alignment | 메모리에서 섹션 정렬 단위 | 0x1000 |
File Alignment | 디스크 상에서 섹션 정렬 단위 | 0x200 |
Size of Image | 전체 이미지의 메모리 크기 | 0x15000 |
Subsystem | GUI, CLI 구분 | 0x2 (GUI이다.)![]() |
EXPORT Table RVA & Size |
RVA | 0x0 |
Size | 0x0 | |
IMPORT Table RVA & Size |
RVA | 0x14264 |
Size | 0xA0 |

일단 대부분의 OPTIONAL_HEADER의 구조가 통상적으로 사진처럼 오프셋을 가지나보다.
오른쪽의 Memory에 올라왔을 경우에 Image Base 값이 메모리의 가상주소인 0x4000000에 자리를 잡게된다.
그러고나서는 0x1000으로 RVA 값을 가지며, 이는 Section의 시작 영역이다.
Section Alignment와 FileAlignment로 섹션 단위가 결정되고 정렬하는데,
오른쪽의 메모리에서는 SectionAlignment 단위로 정렬되고, 0x1000 단위이다.
왼쪽의 파일에서는 FileAlignment 단위로 정렬된다. 0x200 단위이다.
Size of Image는 실제 프로세스 (메모리에 올라간 경우 오른쪽)의 크기를 말하며, 이는 헤더 + 섹션 모두 포함이다.
0x15000으로 꽤 크다.
자세히보면 아래에 Number of Data Directories 값이 0x10으로 되어있다. 총 16개인데, 이는 기본적으로 PE 파일이
16개 DataDirectory 인덱스를 갖기 때문이다.
각 인덱스는 RVA 값을 이용하여 메모리로 올렸을 때 마찬가지로 Image Base에 더해서 넣어주면 된다.
메모리에 올라와있는 프로세스를 직접 보면서 실제로 값이 그렇게 있는지, 확인해보고싶지만
시스템 해킹은 아직 크게 흥미가 없었기도하고... 아직 기초가 없고 미숙해서 나중에 기회가 된다면 다른 주제와 엮어서 분석해보도록하겠습니다...
나중에 PE 파일 DataDirectory Index 포스팅하기!
4. Section Header
섹션 영역은

code
data
const
.rsrc
.idata
이렇게 5가지로 PEview.exe에서 구분해서 보여줬다.
근데 다른 분들 포스팅에서는 섹션들을 크게 .text, .data, .rsrc, .idata, .rdata들로 설명해준다.
일단 알아보니...
PE 파일은 여러가지의 형태와 기능을 가질 것이다.
dll 을 사용하는 경우도 있고, PE 파일 내에 실행 코드도 있어야하고, 리소스도 참고 사용해야할 수 도 있고 등등
그에 맞게 섹션들이 생성되고 분포된다.
그리고 그 중 . 이 붙지 않은 code, data, const 섹션은 개발자에 의해 만들어진 이름들의 섹션이라고 한다...
그럼 섹션들이 각각 어떤 기능을 하는지 어떻게 아느냐?
바로 섹션 헤더에 존재하는 Characteristics 플래그 값을 통해서 실제로 어떤 기능을 하는지 알 수 있다.
(앞의 NT Headers 안의 Characteristics 플래그 값과는 다른 Characteristics다! 명심하자.)
플래그 값에 따른 모든 섹션들의 기능과 구조를 공부하는 것은 힘드니 PEview.exe만 분석해보고 나머지는 그때그때 검색해서 공부해야한다.
섹션 헤더의 오프셋은 OPTIONAL_HEADER 이후에 연속적으로 나온다.

표시 한 부분부터이기도하고 오른쪽에 인코딩된 값을 보면 code라고 적혀있는 것을 보아하니 헤더의 처음 값은 섹션 이름인듯하다. 각 섹션들은 고정적으로 40바이트 = 0x28의 크기를 갖는다.
필드 이름 | 설명 | 실제 디스크 값 (리틀엔디안) |
Name | 이름 | 0x636F6465 (code 문자열을 가지며, 8자리까지 문자를 사용가능) |
PysicalAddress | 물리 주소 | 0x0 (현재는 쓰이지 않는다.) |
VirtualSize | 메모리에서의 섹션 크기 | 0x8110 (메모리에 쓰이는 섹션 크기, 단위는 바이트이다.) |
RVA | 섹션의 RVA | 0x1000 (위의 사진을 예시로 딱 맞아떨어졌으므로 0x1000이다. 아마도 code 다음의 data 섹션 헤더에 있는 섹션 RVA 값은 0x2000일 것이다.) |
Size of Raw Data | 파일에서의 섹션 크기 | 0x8200 (파일 내에 이 섹션의 크기 값인데 패딩도 포함된 값이다. PEview.exe를 통해서 SECTION code영역을 보면 아마 0x8200만큼의 크기를 hex view로 보여줄 것이다.)![]() 0x8600 - 0x400 = 0x8200 (아래 사진도 참고) |
Pointer to Raw Data | 파일 내 실제 데이터 시작 오프셋 | 0x400 (위의 RVA는 프로세스 혹은 메모리로 올라갔을 때의 상대적 주소값이고, 이 값은 파일 내의 상대적 주소 값으로 0x400부터 code 섹션이 시작된다고 보인다. SECTION code 부분은 0x400부터 시작할 것이다.)![]() |
Pointer to Relocations | 재배치 정보 | 0x0 (주로 0으로 이루어져있다. 이유는 obj 파일에서만 사용되는 영역이고, obj는 링커가 obj와 라이브러리를 하나의 exe 혹은 dll 파일로 만들기 전의 파일이기 때문에 이때 라이브러리와 심볼들 링크하지 않았기 때문에 이 영역을 사용해서 링크해준다. 이때 이 영역이 쓰인다.) |
Pointer to Line Numbers | 디버그 정보 | 0x0 (원래 이전의 방식대로라면 컴파일 하기 전의 소스코드의 몇번째 줄의 소스코드가 해당 섹션인지 몇번째줄(Line Number)를 알려줬다. 하지만 현재는 PDB 파일 통한 디버그 방식을 사용하기 때문에 거의 쓰이지 않고 0으로 채워진다고 한다.) |
Number of Relocations | 재배치 수 | 0x0 마찬가지이다. (하지만 pdb파일은 배포가 안될 수도 있다. 왜냐하면 변수명, 소스코드 경로 등 보안 상의 이유로 배포 안하는게 나을 수 도 있기 때문이다.) |
Number of Line Numbers | 디버그 수 | 0x0 마찬가지이다. |
Characteristics | 해당 섹션의 속성 | 0x60000020 (0x40000000 + 0x20000000 + 0x00000020 으로 https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#section-flags 에 나와있는 값들을 참고해서 확인해보면 읽기 가능 + 실행 가능 + 실행 코드가 포함된 섹션이라는 뜻이다.) |
물론 실제로는 Characteristics의 값에 따라서 섹션 자체의 내용이 많이 달라질 것 이다...
출처 및 참고)
윈도우 실행파일 구조(PE파일)
1. 윈도우 실행파일(PE파일) 개요 1.1 PE파일이란? PE(Portable Executable)파일은 윈도우 실행파일이라고 부르며 윈도우OS에서 사용되는 실행파일형식을 의미하며 UNIX의 COFF(Common Object File Format)을 기반으
rninche01.tistory.com
[Analysis] PE(Portable Executable) 파일 포맷 공부
드디어 PE(Portable Executable) 파일 포맷 포스팅을 하고자한다. 내용이 길것으로 예상되나 중요한 파트이므로 천천히 짚고 넘어가자. 1. PE 포맷? PE 포맷이란 Portable Executable 약자로 윈도우 운영체제에
saynot.tistory.com
https://rednooby.tistory.com/33
[악성코드분석] PE (portable Executable) 기초 개념잡기
PE포맷 이란?윈도우 운영체제에서 사용되는 실행파일, DLL Object코드, FON 폰트파일 등을 위한 파일형식입니다.OE파일은 윈도우 로더가 실행가능한 코드를 관리하는데 필요한 정보를 캡슐화한 데이
rednooby.tistory.com
https://mocharoll.tistory.com/15
[악성코드] PE 파일(포맷) Part 1 - 개념 및 생성과정과 구조
기나긴 서론 윈도우 보안을 공부하다보면 기본적으로 PE 파일 구조를 분석해야하는 경우가 존재한다. 왜냐하면 윈도우에서 돌아가는 exe 파일 및 dll, bin, sys 파일들이 다 PE 파일의 일종이기 때문
mocharoll.tistory.com
'포렌식 통합' 카테고리의 다른 글
ext4 file system - Block Group (Journal) (0) | 2025.06.26 |
---|---|
ext4 file system - Block Group (I-node Entry Extent 영역) (1) | 2025.06.21 |
ext4 file system - Block Group (Super Block, GDT , Block & I-node Bitmap, I-node Table) (1) | 2025.06.07 |
이벤트 로그 (참고) [지속수정] (1) | 2024.11.16 |
참고문헌 및 파일 (지속 수정) (1) | 2024.10.23 |