Exploring the MS-DOS Stub
먼저 PE 헤더를 살펴보겠습니다.
MS-DOS 헤더로 시작하여 16비트 MS-DOS 실행 파일(스텁 프로그램)을 포함합니다.
DOS stub : 실행 파일이 MS-DOS에 로드될 때 실행되는 16비트 프로그램으로, 프로그램이 DOS와 호환되지 않는다는 오류 메시지를 표시합니다. 기본 오류 메시지는 "This program cannot be run in DOS mode."이지만, 사용자가 컴파일하는 동안 변경할 수 있습니다.
다음은 MS-DOS 헤더 _IMAGE_DOS_HEADER의 세부사항입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
#define IMAGE_NT_SIGNATURE 0x00004550 // PE00
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
|
모든 PE 파일은 IMAGE_DOS_SIGNATURE로 시작하는 MS-DOS 실행 파일로 시작합니다.
ASCII 표현은 0x5A4D이며 MZ입니다. 문자 "MZ"는 MS-DOS의 원래 설계자 중 한 명이자 MS-DOS 실행 파일 형식의 설계자인 Mark Zbikowski를 의미합니다.
첫 번째 멤버 _IMAGE_DOS_HEADER.e_magic에는 서명 'MZ' 가 들어 있습니다.
위 이미지에서 오프셋 0x3c는 _IMAGE_DOS_HEADER의 e_lfanew 멤버입니다. 이 주소는 _IMAGE_NT_HEADERS인 새 EXE 헤더를 가리킵니다. 위 사진에서 e_lfanew는 _IMAGE_NT_HEADERS.Signature의 시작을 가리키는 0x00000F8 을 포함합니다.
ASCII 표현은 PE00인 0x00004550입니다. 기본적으로 Windows 로더는 _IMAGE_DOS_HEADER의 e_magic 및 e_lfanew 멤버만 신경 씁니다. DOS 헤더의 나머지 멤버는 MS-DOS가 스텁 프로그램을 실행하는 데 사용되기 때문입니다.
모든 32비트/64비트 PE 파일에서 조그만한 MS-DOS 스텁 프로그램을 볼 수 있습니다. 오프셋 0x40에서 0x7f까지는 64바이트인 이 스텁 프로그램입니다. MS-DOS 헤더를 제외하고 스텁 프로그램 코드를 디스어셈블해 보았습니다.
이것은 "This program cannot be run in DOS mode." 를 인쇄하고 종료하는 간단한 16비트 어셈블리 프로그램입니다.
DOS 내부에서 이 64비트 PE를 실행하면 스텁이 실행되고 해당 메시지를 받게 됩니다.
DOS 헤더를 살펴보면 디버거 내부에서 해당 값을 볼 수 있으며, 이는 MS-DOS 헤더가 MS-DOS가 스텁을 실행하는 데만 필요하다는 것을 증명합니다. 하지만 앞서 언급했듯이 e_magic과 e_lfanew 멤버는 Windows 로더에 중요합니다.
위의 이미지에서 초기 스택 포인터 0x00B8인 e_sp와 초기 명령어 포인터 0x0000인 e_ip는 디버깅을 시작할 때 아래 이미지에서 볼 수 있습니다. 우리가 역어셈블한것과 동일한 16비트 어셈블리 코드를 볼 수 있으며, 이 코드는 해당 텍스트를 실행하고 인쇄합니다.
https://download.microsoft.com/download/9/C/5/9C5B2167-8017-4BAE-9FDE-D599BAC8184A/pecoff.docx