본문 바로가기
카테고리 없음

2부. 13장 PE File Format(1)

by HHack 2024. 12. 29.
반응형

13.1 소개

  PE(Portable Executable) 파일은 Windows 운영체제에서 사용되는 실행 파일 형식으로, Microsoft가 기존 UNIX의 COFF(Common Object File Format)를 기반으로 설계한 형식입니다.

  PE 파일 형식은 32비트와 64비트 실행 파일 모두를 포함하며, 64비트 실행 파일 형식은 PE32+로 불립니다. PE32+는 PE32(32비트) 형식의 확장된 형태로, 64비트 주소 공간 지원 및 추가 헤더 필드를 제공합니다. 따라서 PE 파일 형식은 현대 Windows 운영체제에서 실행 파일과 라이브러리 파일(DLL)을 아우르는 범용적인 파일 형식으로 자리 잡고 있습니다.


13.2 PE File Format

종류 주요 확장자 종류 주요 확장자
실행 계열 EXE, SCR 드라이버 계열 SYS, VXD
라이브러리 계열 DLL, OCX, CPL, DRV 오브젝트 파일 계열 OBJ

  이 중 OBJ 파일을 제외한 모든 것은 실행 가능한 파일입니다. DLL, SYS 파일은 셸(Explorer.exe)에서 직접 실행할 순 없지만 다른 형태의 방법(디버거, 서비스, 기타)을 이용하여 실행이 가능한 파일입니다.

 

  간단한 설명을 위해 노트패드(notepad.exe) 파일을 헥스 에디터 HxD를 이용해서 열어보겠습니다.

그림 13.1 notepad.exe 파일

  그림 13.1은 notepad.exe 파일의 시작 부분이며, PE파일의 헤더 부분입니다. 이 PE 헤더에 notepad.exe 파일이 실행되기 위해 필요한 모든 정보가 적혀있습니다. 어떻게 메모리에 적재되고, 어디서부터 실행되어야 하며, 실행에 필요한 DLL들은 어떤 것들이 있고, 필요한 stack/heap 메모리의 크기를 얼마로 할지 등등 수많은 정보가 PE헤더에 구조체 형식으로 저장되어 있습니다.

13.2.1 기본 구조

그림 13.2 PE 파일(notepad.exe)이 메모리에 로딩되는 모습

DOS 헤더부터 Section 헤더까지를 PE헤더, 그 밑의 Section들을 합쳐 PE 바디라고 합니다. 파일에서는 offset으로 메모리에서는 VA(Virtual Address)로 위치를 표한합니다. 파일이 메모리에 로딩되면 모양이 달라집니다. 파일의 내용은 보통 코드(.text), 데이터(.data), 리소스(.rsrc) 섹션에 나뉘어서 저장됩니다.

  • 섹션 헤더에 각 Section에 대한 파일/메모리에서의 크기, 위치, 속성 등이 정의되어 있습니다.
  • PE 헤더의 끝부분과 각 섹션의 끝에는 NULL Padding 이라고 불리는 영역이 존재합니다.(최소 기본단위의 배수로 맞추기 위해)

13.2.2 VA & RVA

  • VA (Virtual Address): 프로세스의 가상 메모리에서 특정 데이터나 코드의 절대적인 주소입니다. 예를 들어, 0x400000처럼 특정 메모리 위치를 나타냅니다.
  • RVA (Relative Virtual Address): 파일이 로드된 기준 주소(Base Address)를 기준으로 한 상대적인 주소입니다. 예를 들어, Base Address가 0x400000이고 RVA가 0x1000이라면, 실제 VA는 0x401000이 됩니다.

※ 왜 VA가 아니라 RVA를 사용하는가?

PE 파일은 메모리에 로드되기 전에 디스크에 저장되어 있는 상태입니다. 이 디스크 상태에서 VA를 사용할 경우, 다음과 같은 문제가 발생합니다:

  1. 재배치 가능성
    프로세스가 실행될 때, PE 파일이 메모리의 기본 주소(Base Address)로 로드되지 않고, 이미 사용 중인 영역을 피해서 다른 위치에 로드될 수 있습니다.
    • 예: 기본 주소가 0x400000인데, 다른 파일이 이미 이 주소를 사용 중이라면, PE 파일은 0x500000에 로드될 수 있습니다.
  2. VA는 고정된 주소이므로 재배치 시 비효율적
    만약 PE 파일이 디스크에 절대 VA로 저장되어 있다면, 파일을 새로운 위치에 로드할 때 모든 주소를 수정해야 합니다. 이는 매우 비효율적이고 복잡한 작업입니다.
  3. RVA는 재배치에 유리
    반면, RVA는 Base Address에 상대적인 주소이므로 PE 파일이 어디에 로드되든 간에 Base Address만 더하면 VA를 계산할 수 있습니다. 즉, 파일 자체의 구조를 수정하지 않아도 됩니다.

예시:

  1. Base Address가 0x400000인 상황
    디스크에 저장된 PE 파일이 메모리로 로드되며, Base Address는 0x400000으로 설정됩니다.
    • .text 섹션의 RVA: 0x1000
      • 실제 VA: Base Address(0x400000) + RVA(0x1000) = 0x401000
    • .data 섹션의 RVA: 0x2000
      • 실제 VA: Base Address(0x400000) + RVA(0x2000) = 0x402000
  2. Base Address가 0x500000으로 변경된 상황 (재배치 발생)
    만약 이 PE 파일이 이미 0x400000에 다른 파일이 로드되어 있어 0x500000으로 이동되었다면:
    • .text 섹션의 RVA는 여전히 0x1000
      • 새로운 VA: Base Address(0x500000) + RVA(0x1000) = 0x501000
    • .data 섹션의 RVA는 여전히 0x2000
      • 새로운 VA: Base Address(0x500000) + RVA(0x2000) = 0x502000
    → 즉, RVA 값은 변경되지 않으며, Base Address만 바뀌어도 올바른 VA를 계산할 수 있습니다.

만약 VA만 사용했다면?

디스크에 절대 VA를 기록했다고 가정해 봅시다:

  • .text 섹션의 VA: 0x401000
  • .data 섹션의 VA: 0x402000

재배치로 Base Address가 0x500000으로 변경되었다면:

  • VA를 모두 새로 계산하고 파일을 수정해야 합니다.
  • .text의 새로운 VA: 0x501000
  • .data의 새로운 VA: 0x502000

→ 매번 파일을 수정해야 하므로 비효율적입니다.


요약:

  • RVA는 Base Address를 기준으로 한 상대 주소이므로, PE 파일이 어디로 로드되든 Base Address만 추가하면 쉽게 원하는 데이터를 찾을 수 있습니다.
  • VA는 고정된 주소라 재배치가 발생하면 모든 주소를 수정해야 하는 불편함이 있습니다.
  • RVA를 사용함으로써 파일을 수정할 필요 없이 효율적으로 재배치가 가능합니다.

13.3 PE 헤더

13.3.1 DOS Header

  MS는 PE File Format을 만들 때 당시에 널리 사용되던 DOS 파일에 대한 하위 호환성을 고려해서 만들었습니다. 그 결과로 EP헤더의 제일 앞부분에는 기존 DOS EXE Header를 확장시킨 IMAGE_DOS_HEADER 구조체가 존재합니다.

IMAGE_DOS_HEADER 구조체

typedef struct _IMAGE_DOS_HEADER {
     WORD e_magic;      // DOS signature : "MZ" (0x4D 0x5A)
     WORD e_cblp;       // 파일 마지막 페이지의 바이트 수
     WORD e_cp;         // 파일 전체 페이지 수
     WORD e_crlc;       // 재배치 항목 수
     WORD e_parhdr;     // 헤더 크기(단위: 파라그래프)
     WORD e_minalloc;   // 최소 추가 메모리 요구량(단위: 파라그래프)
     WORD e_maxalloc;   // 최대 추가 메모리 요구량(단위: 파라그래프)
     WORD e_ss;         // 초기 스택 세그먼트
     WORD e_sp;         // 초기 스택 포인터
     WORD e_csum;       // 파일 체크섬
     WORD e_ip;         // 초기 명령어 포인터 (Entry Point)
     WORD e_cs;         // 초기 코드 세그먼트
     WORD e_lfarlc;     // 재배치 테이블의 파일 오프셋
     WORD e_ovno;       // 오버레이 번호
     WORD e_res[4];     // 예약된 필드 (0으로 채움)
     WORD e_oemid;      // OEM 식별자
     WORD e_oeminfo;    // OEM 정보
     WORD e_res2[10];   // 예약된 필드 (0으로 채움)
     LONG e_lfanew;     // NT Header(PE Header)의 파일 오프셋
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

 

주요 필드와 그 용도:

  1. e_magic
    • 값: 0x4D5A (ASCII로 "MZ")
    • DOS 실행 파일임을 나타내는 서명(Signature).
    • 모든 PE 파일은 이 값으로 시작됩니다.
  2. e_lfanew
    • **NT Header(PE Header)**가 시작되는 파일 오프셋(Offset)을 가리킵니다.
    • PE 파일 분석에서 가장 중요한 필드 중 하나입니다.
    • 예를 들어, e_lfanew 값이 0xE0이면, 파일의 0xE0 위치에서 NT Header가 시작됩니다.
  3. e_cblp, e_cp
    • DOS 실행 파일이 메모리로 로드될 때 필요한 크기 정보를 나타냅니다.
    • PE 파일에서는 크게 사용되지 않음.
  4. e_res, e_res2
    • 예약된 필드로, 특별한 값이 저장되지 않고 주로 0으로 채워져 있습니다.
  5. e_oemid, e_oeminfo
    • OEM(Original Equipment Manufacturer) 관련 정보로, 일반적으로 사용되지 않습니다.
  6. e_lfarlc
    • DOS 실행 환경에서 사용하는 재배치 테이블의 오프셋을 나타냅니다.
    • PE 파일에서는 무시됩니다.

활용 예:

PE 파일 분석에서는 주로 e_magic과 e_lfanew를 사용합니다.

예시: e_lfanew를 이용한 NT Header 위치 찾기

  1. 파일의 첫 번째 64바이트를 읽어 IMAGE_DOS_HEADER로 해석합니다.
  2. e_lfanew 값을 읽어 해당 값의 위치로 이동합니다.
  3. 이동한 위치에서 "PE\0\0" 시그니처를 확인하면 NT Header가 시작됩니다.

예제 코드 (C언어):

#include <windows.h>
#include <stdio.h>

void analyzePE(const char* filename) {
    FILE* file = fopen(filename, "rb");
    if (!file) {
        printf("파일 열기 실패\n");
        return;
    }

    IMAGE_DOS_HEADER dosHeader;
    fread(&dosHeader, sizeof(IMAGE_DOS_HEADER), 1, file);

    // DOS Header 확인
    if (dosHeader.e_magic != 0x5A4D) {
        printf("유효하지 않은 DOS 헤더 (MZ 시그니처 없음)\n");
        fclose(file);
        return;
    }
    printf("DOS 헤더 확인됨 (MZ 시그니처)\n");

    // NT Header 위치로 이동
    fseek(file, dosHeader.e_lfanew, SEEK_SET);
    DWORD peSignature;
    fread(&peSignature, sizeof(DWORD), 1, file);

    // PE Header 확인
    if (peSignature == 0x00004550) {  // "PE\0\0"
        printf("PE 헤더 확인됨 (PE 시그니처)\n");
    } else {
        printf("유효하지 않은 PE 헤더\n");
    }

    fclose(file);
}

int main() {
    analyzePE("example.exe");
    return 0;
}

요약:

IMAGE_DOS_HEADER는 PE 파일 분석의 시작점으로, NT Header의 위치를 찾아주는 e_lfanew 필드가 핵심입니다. 이를 기반으로 PE 파일의 구조를 분석하고, 실행 파일의 내부 데이터를 효율적으로 탐색할 수 있습니다.


notepad.exe를 hex editor로 열어서 IMAGE_DOS_HEADER 구조체를 확인해 보겠습니다.

그림 13.3 IMAGE_DOS_HEADER

PE 스펙에 맞게 파일 시작 2바이트는 4D5A이며, e_lfanew 값은 000000E0 입니다.(리틀 엔디언)

13.3.2 DOS Stub

DOS Header 밑에는 DOS Stub가 존재합니다. DOS Stub 존재 여부는 옵션이며 크기도 일정하지 않습니다. DOS Stub는 코드와 데이터의 혼합으로 이루어져 있으며, 그림 13.4에 notepad.exe의 DOS Stub가 나타나 있습니다.

그림 13.4 DOS Stub

  • 40 ~ 4D 영역은 16비트 어셈블리 명령어입니다. 32비트 Windows OS에서는 이쪽 명령어가 실행되지 않습니다.(PE파일로 인식)
  • Windows 환경에서는 PE 파일로 인식되므로, DOS Stub 코드는 무시됩니다.
  • DOS 환경에서 PE 파일을 실행하려 하면, DOS Stub이 실행되어 호환 메시지를 출력합니다.
  • 이 코드의 주요 목적은 DOS 환경에서 PE 파일을 실행하려는 시도를 방지하는 것입니다.

최신 Windows 환경에서 DOS Stub 실행 가능성

1. Windows XP 이후 환경

  • Windows XP 이후 운영체제부터는 32비트 커맨드 창(cmd.exe)에서도 PE 파일로 인식되므로, DOS Stub 코드를 직접 실행하는 것이 불가능합니다.
  • DOS Stub 코드를 실행하려면 DOS 전용 환경 또는 DOS 에뮬레이터가 필요합니다.
  • 최신 Windows 환경에서는 **NTVDM(NT Virtual DOS Machine)**이 제거되었기 때문에, 기본적으로 16비트 프로그램을 실행할 수 없습니다.

2. DOS Stub 실행 방법

  • 최신 Windows 운영체제(예: Windows 10, 11)에서는 DOS Stub 코드를 실행하려면 DOSBox와 같은 에뮬레이터를 사용해야 합니다.
  • DOSBox는 MS-DOS를 가상화하여, DOS Stub 코드 실행을 포함한 16비트 프로그램 실행을 지원합니다.

DOS Stub 코드 실행 방법

1. DOSBox 설치 및 실행

  • DOSBox를 설치하고 실행합니다.
  • PE 파일이 있는 디렉터리를 DOSBox에 마운트 합니다: 
  • mount c C:\Windows\ c:

2. DOS Stub 실행

  • DOSBox 내에서 PE 파일(예: notepad.exe)을 실행합니다:
    debug notepad.exe
    
  • 디버거에서 u(Unassemble) 명령어를 입력하여 DOS Stub 코드를 확인합니다.

16비트 어셈블리 코드의 작동 방식

DOS Stub 코드 예시 (16비트 어셈블리):

MOV  DX, OFFSET message  ; 메시지 출력 주소 설정
MOV  AH, 09h             ; DOS interrupt: 출력 문자열
INT  21h                 ; DOS interrupt 실행

MOV  AX, 4C00h           ; 프로그램 종료 코드
INT  21h                 ; 종료
message DB "This program cannot be run in DOS mode.$"
  • 동작: 메시지 "This program cannot be run in DOS mode."를 출력하고 프로그램을 종료합니다.

DOS와 Windows의 멀티 플랫폼 실행 가능성

1. PE 파일의 DOS Stub을 커스터마이징

  • DOS Stub을 수정하여, PE 파일이 DOS와 Windows 환경에서 다른 동작을 수행할 수 있도록 설정 가능합니다.
  • DOS 환경에서는 16비트 어셈블리 코드가 실행되고, Windows에서는 32비트 PE 코드가 실행됩니다.

2. 멀티플랫폼 EXE 제작 예시

  • DOS 환경에서 실행 시 특정 기능 수행 (예: 메시지 출력).
  • Windows 환경에서 GUI 프로그램 실행.

요약

  1. DOS Stub은 현대 Windows 환경에서 실행되지 않음.
    • 최신 Windows에서는 DOS Stub이 무시되고, PE 파일의 32비트 코드가 실행됩니다.
    • DOS Stub 코드를 확인하거나 실행하려면 DOSBox 또는 다른 DOS 에뮬레이터를 사용해야 합니다.
  2. 멀티플랫폼 실행 가능.
    • PE 파일에 맞춤형 DOS Stub을 작성하여, DOS와 Windows에서 각각 다른 코드를 실행할 수 있습니다.
  3. 16비트 코드 작성 및 실행:
    • DOS Stub은 간단한 어셈블리 코드로 메시지를 출력하거나 다른 동작을 수행하도록 작성 가능합니다.
  4. 최신 개발 도구와 DOS Stub:
    • Visual Studio, GCC 등의 현대 개발 도구에서도 PE 파일 작성 시 기본적인 DOS Stub을 지원합니다.
    • 필요에 따라 DOS Stub을 커스터마이징 할 수 있습니다.

13.3.3 NT Header

IMAGE_NT_HEADERS 구조체

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;                      // PE Signature ("PE\0\0")
    IMAGE_FILE_HEADER FileHeader;         // 파일 헤더 (File Header)
    IMAGE_OPTIONAL_HEADER OptionalHeader; // Optional Header
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

구조체 필드 설명:

  1. DWORD Signature (4 bytes)
    • 값: "PE\0\0" (0x00004550)
    • 이 필드는 NT Header의 시작을 나타내는 고유 시그니처로 항상 "PE\0\0" 값을 가집니다.
  2. IMAGE_FILE_HEADER FileHeader (20 bytes)
    • 파일 헤더로, PE 파일의 주요 정보를 포함합니다.
    • 섹션 수, 타임스탬프, 머신 아키텍처 등의 정보가 들어 있습니다.
  3. IMAGE_OPTIONAL_HEADER OptionalHeader (224 bytes 또는 240 bytes)
    • 실행 파일에 필요한 추가 정보를 포함하는 헤더입니다.
    • 이 필드는 "Optional"이라는 이름과 달리 필수 필드이며, PE 파일 실행에 필요한 중요한 정보를 담고 있습니다.
    • 크기는 32비트(PE32)일 경우 224바이트, 64비트(PE32+)일 경우 240바이트입니다.

그림 13.5 IMAGE_NT_HEADERS

13.3.4 NT Header - File Header

파일의 개략적인 속성을 나타내는 IMAGE_FILE_HEADER 구조체입니다.

typedef struct _IMAGE_FILE_HEADER {
    WORD  Machine;              // 실행 대상 아키텍처 (예: x86, x64)
    WORD  NumberOfSections;     // 섹션 수
    DWORD TimeDateStamp;        // 파일 생성 시간 (타임스탬프)
    DWORD PointerToSymbolTable; // 심볼 테이블의 파일 오프셋 (일반적으로 0)
    DWORD NumberOfSymbols;      // 심볼 수 (일반적으로 0)
    WORD  SizeOfOptionalHeader; // Optional Header 크기
    WORD  Characteristics;      // 파일 속성 플래그
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

#1. Machine

Machine 넘버는 CPU별 고유한 값이며 32비트 Intel x86 호환 칩은 14C의 값을 가집니다. 아래는 winnt.h 파일에 정의된 Machine 넘버의 값들입니다.

매크로 이름값 (16진수)설명

주요 Machine 넘버 값

 매크로 이름  값 (16진수)  설명
 IMAGE_FILE_MACHINE_UNKNOWN  0x0000  알 수 없는 머신 타입
 IMAGE_FILE_MACHINE_I386  0x014C  Intel 386 이상 (x86)
 IMAGE_FILE_MACHINE_R3000  0x0162  MIPS R3000
 IMAGE_FILE_MACHINE_R4000  0x0166  MIPS R4000
 IMAGE_FILE_MACHINE_R10000  0x0168  MIPS R10000
 IMAGE_FILE_MACHINE_WCEMIPSV2  0x0169  MIPS WCE v2
 IMAGE_FILE_MACHINE_ALPHA  0x0184  DEC Alpha AXP
 IMAGE_FILE_MACHINE_SH3  0x01A2  Hitachi SH3
 IMAGE_FILE_MACHINE_SH3DSP  0x01A3  Hitachi SH3 DSP
 IMAGE_FILE_MACHINE_SH3E  0x01A4  Hitachi SH3E
 IMAGE_FILE_MACHINE_SH4  0x01A6  Hitachi SH4
 IMAGE_FILE_MACHINE_SH5  0x01A8  Hitachi SH5
 IMAGE_FILE_MACHINE_ARM  0x01C0  ARM 리틀 엔디언
 IMAGE_FILE_MACHINE_THUMB  0x01C2  ARM Thumb
 IMAGE_FILE_MACHINE_ARMNT  0x01C4  ARM Thumb-2 리틀 엔디언
 IMAGE_FILE_MACHINE_AM33  0x01D3  Matsushita AM33
 IMAGE_FILE_MACHINE_POWERPC  0x01F0  PowerPC 리틀 엔디언
 IMAGE_FILE_MACHINE_POWERPCFP  0x01F1  PowerPC 부동 소수점 지원
 IMAGE_FILE_MACHINE_IA64  0x0200  Intel Itanium
 IMAGE_FILE_MACHINE_MIPS16  0x0266  MIPS16
 IMAGE_FILE_MACHINE_ALPHA64  0x0284  DEC Alpha AXP 64-bit
 IMAGE_FILE_MACHINE_MIPSFPU  0x0366  MIPS 부동 소수점 지원
 IMAGE_FILE_MACHINE_MIPSFPU16  0x0466  MIPS16 부동 소수점 지원
 IMAGE_FILE_MACHINE_TRICORE  0x0520  Infineon TriCore
 IMAGE_FILE_MACHINE_CEF  0x0CEF  Common Executable Format (CEF)
 IMAGE_FILE_MACHINE_EBC  0x0EBC  EFI 바이트 코드
 IMAGE_FILE_MACHINE_AMD64  0x8664  AMD64 (x64)
 IMAGE_FILE_MACHINE_M32R  0x9041  Mitsubishi M32R 리틀 엔디언
 IMAGE_FILE_MACHINE_ARM64  0xAA64  ARM64 리틀 엔디언
 IMAGE_FILE_MACHINE_CEE  0xC0EE  Common Language Runtime 실행 가능 파일

#2. NumberOfSections

PE 파일은 여러 개의 섹션(Section)으로 구성됩니다. 섹션은 실행 파일의 코드, 데이터, 리소스, 디버깅 정보 등을 포함하는 논리적인 블록입니다. NumberOfSections 필드는 이러한 섹션의 총 개수를 나타내며, PE 파일을 분석하거나 로드할 때 매우 중요한 역할을 합니다.

 

PE 파일의 주요 섹션 예시

 섹션 이름  설명
 .text  실행 코드(Instructions)가 포함된 섹션. CPU가 실행할 명령어들이 들어 있음.
 .data  초기화된 데이터가 포함된 섹션. 전역 변수나 정적 변수가 위치함.
 .rdata  읽기 전용 데이터(상수, 문자열 등)가 포함된 섹션.
 .bss  초기화되지 않은 데이터가 포함된 섹션. (PE 파일에서는 .data와 통합됨)
 .rsrc  리소스(아이콘, 메뉴, 대화 상자 등)가 포함된 섹션.
 .reloc  재배치 정보(Relocation Information)가 포함된 섹션.
 .debug  디버그 정보가 포함된 섹션. (디버깅 빌드일 경우에만 포함됨)

#3. SizeOfOptionalHeader

   IMAGE_NT_HEADERS 구조체의 마지막 멤버는 IMAGE_OPTIIONAL_HEADER32 구조체입니다. SizeOfOptionalHeader 멤버는 바로 이 IMAGE_OPTIIONAL_HEADER32 구조체의 크기를 나타냅니다. IMAGE_OPTIIONAL_HEADER32는 C언어의 구조체이기 때문에 이미 그 크기가 결정되어 있습니다. 그런데 Windows PE 로더는 IMAGE_FILE_HEADER의 SizeOfOptioanlHeader 값을 보고 IMAGE_OPTIIONAL_HEADER32 구조체의 크기를 인식합니다.

  정확한 Optional Header 크기를 알면 이후 섹션 헤더(Section Header)를 올바르게 파싱 할 수 있습니다.

#4. Characteristics

파일의 속성을 나타내는 값으로, 실행이 가능한 형태인지 혹은 DLL 파일인지 등의 정보들이 bit OR 형식으로 조합됩니다.

 

주요 플래그 값과 설명

 비트   플래그 이름   값(16진수)  설명
 Bit 0  IMAGE_FILE_RELOCS_STRIPPED  0x0001  재배치 정보 제거 (고정 주소로 로드)
 Bit 1  IMAGE_FILE_EXECUTABLE_IMAGE  0x0002  실행 가능한 파일
 Bit 2  IMAGE_FILE_LINE_NUMS_STRIPPED  0x0004  라인 번호 제거 (디버그 정보 제거됨)
 Bit 3  IMAGE_FILE_LOCAL_SYMS_STRIPPED  0x0008  심볼 제거 (디버그 정보 제거됨)
 Bit 4  IMAGE_FILE_AGGRESIVE_WS_TRIM  0x0010  워킹 세트(Working Set) 트리밍 가능
 Bit 5  IMAGE_FILE_LARGE_ADDRESS_AWARE  0x0020  2GB 이상의 가상 메모리 주소 사용 가능 (LAA 플래그)
 Bit 7  IMAGE_FILE_BYTES_REVERSED_LO  0x0080  리틀 엔디언(Little Endian)로 저장됨
 Bit 8  IMAGE_FILE_32BIT_MACHINE  0x0100  32비트 머신용 파일
 Bit 9  IMAGE_FILE_DEBUG_STRIPPED  0x0200  디버그 정보 제거됨
 Bit 10  IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP  0x0400  이동식 미디어에서 실행 시 스왑 가능
 Bit 11  IMAGE_FILE_NET_RUN_FROM_SWAP  0x0800  네트워크에서 실행 시 스왑 가능
 Bit 12  IMAGE_FILE_SYSTEM  0x1000  시스템 파일 (OS 커널, 드라이버 등)
 Bit 13  IMAGE_FILE_DLL  0x2000  DLL 파일
 Bit 14  IMAGE_FILE_UP_SYSTEM_ONLY  0x4000  단일 CPU 시스템에서만 실행 가능
 Bit 15  IMAGE_FILE_BYTES_REVERSED_HI  0x8000  리틀 엔디언(Little Endian)로 저장됨 (비트 반전)

주요 플래그 설명

  1. IMAGE_FILE_RELOCS_STRIPPED (0x0001)
    • 재배치 정보가 제거된 경우 설정됩니다.
    • 이 플래그가 설정된 파일은 고정된 주소에만 로드될 수 있습니다.
    • 일반적으로 커널 모드 드라이버나 특정 시스템 바이너리에서 사용됩니다.
  2. IMAGE_FILE_EXECUTABLE_IMAGE (0x0002)
    • 실행 가능한 이미지 파일임을 나타냅니다.
    • PE 파일이 실행 파일(EXE)인지 여부를 나타내며, DLL에도 설정될 수 있습니다.
  3. IMAGE_FILE_LARGE_ADDRESS_AWARE (0x0020)
    • 이 플래그가 설정된 파일은 2GB 이상의 가상 주소 공간을 사용할 수 있습니다.
    • 32비트 프로그램에서 설정되면 4GB까지 메모리를 사용할 수 있으며, 64비트 프로그램에서는 이 플래그가 항상 설정되어 있습니다.
  4. IMAGE_FILE_32BIT_MACHINE (0x0100)
    • 이 플래그는 파일이 32비트 머신용으로 작성되었음을 나타냅니다.
    • 64비트 프로그램에서는 이 플래그가 설정되지 않습니다.
  5. IMAGE_FILE_DLL (0x2000)
    • PE 파일이 DLL(동적 링크 라이브러리) 파일일 경우 설정됩니다.
  6. IMAGE_FILE_SYSTEM (0x1000)
    • 이 플래그가 설정된 파일은 시스템 파일로 간주됩니다.
    • 일반적으로 운영체제의 커널, 드라이버 또는 시스템 라이브러리에서 설정됩니다.

★ notepad.exe의 IMAGE_FILE_HEADER 구조체

그림 13.6 IMAGE_FILE_HEADER

[ IMAGE_FILE_HEADER ] - notepad.exe

 offset   value   description
-------------------------------------------------------------------------------
000000E4     014C machine
000000E6     0003 number of sections
000000E8 48025287 time date stamp (Mon Apr 14 03:35:51 2008)
000000EC 00000000 offset to symbol table
000000F0 00000000 number of symbols
000000F4     00E0 size of optional header
000000F6     010F characteristics
                      IMAGE_FILE_RELOCS_STRIPPED
                      IMAGE_FILE_EXECUTABLE_IMAGE
                      IMAGE_FILE_LINE_NUMS_STRIPPED
                      IMAGE_FILE_LOCAL_SYMS_STRIPPED
                      IMAGE_FILE_32BIT_MACHINE

멤버별 해석

  1. Machine (WORD)
    • 값: 4C 01
    • 리틀 엔디언이므로 "0x014C"로 해석됩니다.
    • 설명: Intel 386 이상 아키텍처 (즉, x86 프로그램)
  2. NumberOfSections (WORD)
    • 값: 03 00
    • 리틀 엔디언이므로 "0x0003"로 해석됩니다.
    • 설명: 섹션의 수는 3개
  3. TimeDateStamp (DWORD)
    • 값: 87 52 02 48
    • 리틀 엔디언이므로 "0x48025287"로 해석됩니다.
    • 설명: 컴파일된 시간의 타임스탬프 (Unix 시간 형식, 1970년 1월 1일부터 초 단위 경과 시간)
  4. PointerToSymbolTable (DWORD)
    • 값: 00 00 00 00
    • 설명: 심볼 테이블 오프셋 (일반적으로 0)
  5. NumberOfSymbols (DWORD)
    • 값: 00 00 00 00
    • 설명: 심볼의 개수 (일반적으로 0)
  6. SizeOfOptionalHeader (WORD)
    • 값: E0 00
    • 리틀 엔디언이므로 "0x00E0"로 해석됩니다.
    • 설명: Optional Header의 크기는 224바이트 (PE32 형식)
  7. Characteristics (WORD)
    • 값: 0F 01
    • 리틀 엔디언이므로 "0x010F"로 해석됩니다.
    • 설명: 파일 속성 플래그
      • 0x0001: 재배치 정보 제거 (IMAGE_FILE_RELOCS_STRIPPED)
      • 0x0002: 실행 가능한 파일 (IMAGE_FILE_EXECUTABLE_IMAGE)
      • 0x0004: 디버그 라인 번호 제거 (IMAGE_FILE_LINE_NUMS_STRIPPED)
      • 0x0100: 32비트 머신용 파일 (IMAGE_FILE_32BIT_MACHINE)

13.3.5 NT Header - Optional Header

typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

typedef struct _IMAGE_OPTIONAL_HEADER {
    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;
    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

구조체 멤버 설명

1. Standard Fields (표준 필드)

필드 이름 크기 설명
Magic 2바이트 PE 파일 형식 (PE32: 0x10B, PE32+: 0x20B)
MajorLinkerVersion 1바이트 링커의 주요 버전
MinorLinkerVersion 1바이트 링커의 부 버전
SizeOfCode 4바이트 코드 섹션(.text)의 크기
SizeOfInitializedData 4바이트 초기화된 데이터 섹션(.data)의 크기
SizeOfUninitializedData 4바이트 초기화되지 않은 데이터 섹션(.bss)의 크기
AddressOfEntryPoint 4바이트 프로그램 시작 주소 (진입점)의 RVA
BaseOfCode 4바이트 코드 섹션(.text)의 시작 RVA
BaseOfData 4바이트 데이터 섹션(.data)의 시작 RVA (PE32에만 존재)

 

2. Windows-Specific Fields (Windows 관련 필드)

필드 이름 크기 설명
ImageBase 4바이트 프로그램이 메모리에 로드될 기본 주소 (PE32: 32비트 주소, PE32+: 64비트 주소)
SectionAlignment 4바이트 메모리에서 섹션 간의 정렬 크기
FileAlignment 4바이트 파일 내에서 섹션 간의 정렬 크기
MajorOperatingSystemVersion 2바이트 지원하는 운영체제의 주요 버전
MinorOperatingSystemVersion 2바이트 지원하는 운영체제의 부 버전
MajorImageVersion 2바이트 프로그램의 주요 버전
MinorImageVersion 2바이트 프로그램의 부 버전
MajorSubsystemVersion 2바이트 서브시스템의 주요 버전 (예: GUI, CUI)
MinorSubsystemVersion 2바이트 서브시스템의 부 버전
Win32VersionValue 4바이트 예약된 필드 (항상 0)
SizeOfImage 4바이트 메모리에 로드될 이미지의 전체 크기 (섹션 정렬 기준)
SizeOfHeaders 4바이트 파일의 헤더 크기 (파일 정렬 기준)
CheckSum 4바이트 파일 체크섬 (일부 시스템 파일에만 사용)
Subsystem 2바이트 프로그램의 서브시스템 종류 (예: Windows GUI, CUI)
DllCharacteristics 2바이트 DLL의 속성 플래그 (예: ASLR, DEP 등)
SizeOfStackReserve 4바이트 예약된 스택 크기
SizeOfStackCommit 4바이트 커밋된 스택 크기
SizeOfHeapReserve 4바이트 예약된 힙 크기
SizeOfHeapCommit 4바이트 커밋된 힙 크기
LoaderFlags 4바이트 로더 플래그 (일반적으로 0으로 설정)
NumberOfRvaAndSizes 4바이트 데이터 디렉터리의 개수 (기본값: 16)

#1. Magic

Magic 넘버는 IMAGE_OPTIONAL_HEADER32 구조체인 경우 10B, IMAGE_OPTIONAL_HEADER64 구조체인 경우 20B를 가집니다.

#2. AddressOfEntryPoint

Entry Point의 RVA 값을 가지고 있으며, 프로그램에서 최초로 실행되는 코드의 시작 주소.

#3. ImageBase

프로세스의 가상 메모리의 범위는 0 ~ FFFFFFFF입니다(32비트인 경우). ImageBase는 이 메모리에서 PE파일이 로딩되는 시작 주소를 나타냅니다.

EXE, DLL 파일은 user memory 영역인 0 ~ 7FFFFFFF 범위에 로딩되고, SYS 파일은 kernel memory 영역인 80000000 ~ FFFFFFFF 번위에 로딩됩니다.

PE로더는 PE파일을 실행시키기 위해 프로세스를 생성하고 파일을 메모리에 로딩한 후 EIP 레지스터 값을 ImageBase + AddressOfEntryPoint 값으로 세팅합니다.

#4. SectionAlignment, FileAlignment

파일에서 섹션의 최소 단위를 나타내는 것이 FileAlignment.

메모리에서 섹션의 최소 단위를 나타내는 것이 SectionAlignment.

파일/메모리의 섹션 크기는 반드시 FileAlignment / SectionAlignment의 배수가 되어야 합니다.

#5. SizeOfImage

PE 파일이 메모리에 로딩되었을 때 가상 메모리에서 PE Image가 차지하는 크기를 나타냅니다.

#6. SizeOfHeader

PE 헤더의 전체 크기를 나타냅니다. 이 값 역시 FileAlignment의 배수여야 합니다. 파일 시작에서 SizeOfHeader 오프셋만큼 떨어진 위치에 첫 번째 섹션이 위치합니다.

#7. Subsystem

이 값을 보고 시스템 드라이버 파일(*.sys)인지, 일반 실행 파일(*.exe, *.dll)인지 구분할 수 있습니다.

  • 1 : Driver file (*.sys)
  • 2 : GUI (Graphic User Interface) 파일 -> notepad.exe 와 같은 윈도우 기반 애플리케이션
  • 3 : CUI (Console User Interface) 파일 -> cmd.exe 와 같은 콘솔 기반 애플리케이션

#8. NumberOfRvaAndSizes

IMAGE_OPRITONAL_HEADER32 구조체의 마지막 멤버인 DataDirectory 배열의 개수를 나타냅니다. PE로더는 이 값을 보고 배열의 크기를 인식합니다.

#9. DataDirectory

IMAGE_DATA_DIRECTROY 구조체 배열로, 배열의 각 항목마다 정의된 값을 가집니다.

DataDirectory[0] = EXPORT Directory(★)         
DataDirectory[1] = IMPORT Directory(★)         
DataDirectory[2] = RESOURCE Directory(★)       
DataDirectory[3] = EXCEPTION Directory      
DataDirectory[4] = SECURITY Directory       
DataDirectory[5] = BASERELOC Directory      
DataDirectory[6] = DEBUG Directory          
DataDirectory[7] = COPYRIGHT Directory      
DataDirectory[8] = GLOBALPTR Directory      
DataDirectory[9] = TLS Directory(★)            
DataDirectory[A] = LOAD_CONFIG Directory    
DataDirectory[B] = BOUND_IMPORT Directory   
DataDirectory[C] = IAT Directory            
DataDirectory[D] = DELAY_IMPORT Directory   
DataDirectory[E] = COM_DESCRIPTOR Directory 
DataDirectory[F] = Reserved Directory

★ notepad.exe의 IMAGE_OPTIONAL_HEADER 구조체

그림 13.7 notepad.exe의 IMAGE_OPTIONAL_HEADER

[ IMAGE_OPTIONAL_HEADER ] - notepad.exe

 offset   value   description
-------------------------------------------------------------------------------
000000F8     010B magic
000000FA       07 major linker version
000000FB       0A minor linker version
000000FC 00007800 size of code
00000100 00008C00 size of initialized data
00000104 00000000 size of uninitialized data
00000108 0000739D address of entry point
0000010C 00001000 base of code
00000110 00009000 base of data
00000114 01000000 image base
00000118 00001000 section alignment
0000011C 00000200 file alignment
00000120     0005 major OS version
00000122     0001 minor OS version
00000124     0005 major image version
00000126     0001 minor image version
00000128     0004 major subsystem version
0000012A     0000 minor subsystem version
0000012C 00000000 win32 version value
00000130 00014000 size of image
00000134 00000400 size of headers
00000138 000126CE checksum
0000013C     0002 subsystem
0000013E     8000 DLL characteristics
00000140 00040000 size of stack reserve
00000144 00011000 size of stack commit
00000148 00100000 size of heap reserve
0000014C 00001000 size of heap commit
00000150 00000000 loader flags
00000154 00000010 number of directories
00000158 00000000 RVA  of EXPORT Directory
0000015C 00000000 size of EXPORT Directory
00000160 00007604 RVA  of IMPORT Directory
00000164 000000C8 size of IMPORT Directory
00000168 0000B000 RVA  of RESOURCE Directory
0000016C 00008304 size of RESOURCE Directory
00000170 00000000 RVA  of EXCEPTION Directory
00000174 00000000 size of EXCEPTION Directory
00000178 00000000 RVA  of SECURITY Directory
0000017C 00000000 size of SECURITY Directory
00000180 00000000 RVA  of BASERELOC Directory
00000184 00000000 size of BASERELOC Directory
00000188 00001350 RVA  of DEBUG Directory
0000018C 0000001C size of DEBUG Directory
00000190 00000000 RVA  of COPYRIGHT Directory
00000194 00000000 size of COPYRIGHT Directory
00000198 00000000 RVA  of GLOBALPTR Directory
0000019C 00000000 size of GLOBALPTR Directory
000001A0 00000000 RVA  of TLS Directory
000001A4 00000000 size of TLS Directory
000001A8 000018A8 RVA  of LOAD_CONFIG Directory
000001AC 00000040 size of LOAD_CONFIG Directory
000001B0 00000250 RVA  of BOUND_IMPORT Directory
000001B4 000000D0 size of BOUND_IMPORT Directory
000001B8 00001000 RVA  of IAT Directory
000001BC 00000348 size of IAT Directory
000001C0 00000000 RVA  of DELAY_IMPORT Directory
000001C4 00000000 size of DELAY_IMPORT Directory
000001C8 00000000 RVA  of COM_DESCRIPTOR Directory
000001CC 00000000 size of COM_DESCRIPTOR Directory
000001D0 00000000 RVA  of Reserved Directory
000001D4 00000000 size of Reserved Directory

13.3.6 섹션 헤더

  각 섹션의 속성을 정의한 것이 섹션헤더입니다. PE파일을 여러 개의 섹션 구조로 만들었을 때 장점은 프로그램의 안정성입니다. 만약 code와 data가 하나의 섹션으로 되어 있고 서로 뒤죽박죽 섞여있다면 안정성에 문제가 생길 수 있습니다.

  예를 들어, data에 값을 쓰다가 어떤 이유로 overflow가 발생하여 바로 다음의 code를 그대로 덮어쓴다면 프로그램은 큰 문제가 발생합니다. 이러한 문제를 방지하기 위해 비슷한 성격의 자료들을 섹션이라는 범주 안에 모아두고 각각의 섹션의 속성을 기술할 섹션 헤더가 필요해지게 된 겁니다.

  즉, code/data/resource 마다 각각의 특성, 접근 권한 등을 다르게 설정할 필요가 있는 겁니다.

IMAGE_SECTION_HEADER

#define IMAGE_SIZEOF_SHORT_NAME              8

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
        DWORD PhysicalAddress;   // 물리적 주소 (사용되지 않음)
        DWORD VirtualSize;       // 섹션의 가상 크기
    } Misc;
    DWORD VirtualAddress;        // 섹션의 RVA (메모리 내 상대 주소)
    DWORD SizeOfRawData;         // 파일 내에서 섹션의 크기 (파일 정렬 기준)
    DWORD PointerToRawData;      // 파일 내에서 섹션 시작 위치
    DWORD PointerToRelocations;  // 재배치 정보 위치 (일반적으로 0)
    DWORD PointerToLinenumbers;  // 라인 번호 테이블 위치 (일반적으로 0)
    WORD  NumberOfRelocations;   // 재배치 정보 개수 (일반적으로 0)
    WORD  NumberOfLinenumbers;   // 라인 번호 개수 (일반적으로 0)
    DWORD Characteristics;       // 섹션 속성 플래그
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

 

구조체 멤버 설명

1. BYTE Name[8] (8바이트)

  • 섹션의 이름을 최대 8바이트로 저장합니다.
  • 일반적으로 .text, .data, .rdata, .rsrc, .reloc 등과 같은 이름을 가집니다.
  • 이름이 8바이트보다 짧으면 나머지 부분은 0으로 패딩됩니다.

2. DWORD Misc.VirtualSize (4바이트)

  • 섹션의 **가상 크기(Virtual Size)**를 나타냅니다.
  • 실제 메모리에 로드될 때 필요한 섹션의 크기를 의미하며, SectionAlignment에 따라 정렬됩니다.
  • 중요: 이 값은 파일 내에서의 크기와 다를 수 있으며, 메모리에 로드될 때 필요한 크기입니다.

3. DWORD VirtualAddress (4바이트)

  • 섹션의 **RVA(Relative Virtual Address)**입니다.
  • 메모리 내에서의 상대 주소를 나타내며, PE 파일이 메모리에 로드될 때 기준 주소(Base Address)에서 상대적으로 떨어진 위치입니다.

4. DWORD SizeOfRawData (4바이트)

  • 파일 내에서의 섹션 크기를 나타냅니다.
  • FileAlignment에 따라 정렬된 크기입니다.
  • 일반적으로 이 값은 VirtualSize보다 크거나 같으며, 파일에서 섹션을 읽어올 때 사용하는 크기입니다.

5. DWORD PointerToRawData (4바이트)

  • **파일 내에서 섹션이 시작되는 위치(오프셋)**를 나타냅니다.
  • 이 값은 PE 파일 내에서 실제로 섹션 데이터가 저장된 위치를 가리킵니다.

6. DWORD PointerToRelocations (4바이트)

  • 재배치 테이블의 위치를 나타냅니다.
  • 일반적으로 PE 파일에서는 이 값이 사용되지 않으며, 0으로 설정됩니다.

7. DWORD PointerToLinenumbers (4바이트)

  • 라인 번호 테이블의 위치를 나타냅니다.
  • 디버깅 정보가 포함된 특수한 경우에만 사용되며, 일반적으로 0으로 설정됩니다.

8. WORD NumberOfRelocations (2바이트)

  • 재배치 항목의 개수를 나타냅니다.
  • 일반적으로 사용되지 않으며, 0으로 설정됩니다.

9. WORD NumberOfLinenumbers (2바이트)

  • 라인 번호 항목의 개수를 나타냅니다.
  • 디버깅 정보가 포함된 특수한 경우에만 사용되며, 일반적으로 0으로 설정됩니다.

10. DWORD Characteristics (4바이트)

  • 섹션의 속성 플래그를 나타냅니다.
  • 이 플래그는 섹션이 코드, 데이터, 읽기 전용, 쓰기 가능 등 어떤 속성을 가지는지를 정의합니다.

 

 - VirtualAddress와 PointerToRawData의 값은 아무 값이나 가질 수 없고, 각각 (IMAGE_OPTIONAL_HEADER32에 정의된) SectionAlignment와 FileAlignment에 맞게 결정됩니다.

-  VirtualSize와 SizeOfRawData는 일반적으로 서로 다른 값을 가진다. 즉, 파일에서의 섹션 크기와 메모리에 로딩된 섹션의 크기는 다른다는 것이다.

섹션 속성 플래그 (Characteristics)

 플래그 값  매크로 이름  설명
 0x00000020  IMAGE_SCN_CNT_CODE  실행 코드 섹션
 0x00000040  IMAGE_SCN_CNT_INITIALIZED_DATA  초기화된 데이터 섹션
 0x00000080  IMAGE_SCN_CNT_UNINITIALIZED_DATA  초기화되지 않은 데이터 섹션
 0x20000000  IMAGE_SCN_MEM_EXECUTE  실행 가능한 섹션
 0x40000000  IMAGE_SCN_MEM_READ  읽기 가능한 섹션
 0x80000000  IMAGE_SCN_MEM_WRITE  쓰기 가능한 섹션

Name 멤버는 C언어의 문자열처럼 NULL로 끝나지 않습니다. 또한 ASCII 값만 와야한다는 제한도 없습니다. PE 스펙에는 섹션 Name에 대한 어떠한 명시적인 규칙이 없기 때문에 어떠한 값을 넣어도 되고 심지어 NULL로 채워도 됩니다.

그림 13.8 notepad.exe의 IMAGE_SECTION_HEADER 구조체 배열

[ IMAGE_SECTION_HEADER ]

 offset   value   description
-------------------------------------------------------------------------------
000001D8 2E746578 Name (.text)
000001DC 74000000
000001E0 00007748 virtual size
000001E4 00001000 RVA
000001E8 00007800 size of raw data
000001EC 00000400 offset to raw data
000001F0 00000000 offset to relocations
000001F4 00000000 offset to line numbers
000001F8     0000 number of relocations
000001FA     0000 number of line numbers
000001FC 60000020 characteristics
                    IMAGE_SCN_CNT_CODE
                    IMAGE_SCN_MEM_EXECUTE
                    IMAGE_SCN_MEM_READ

00000200 2E646174 Name (.data)
00000204 61000000
00000208 00001BA8 virtual size
0000020C 00009000 RVA
00000210 00000800 size of raw data
00000214 00007C00 offset to raw data
00000218 00000000 offset to relocations
0000021C 00000000 offset to line numbers
00000220     0000 number of relocations
00000222     0000 number of line numbers
00000224 C0000040 characteristics
                    IMAGE_SCN_CNT_INITIALIZED_DATA
                    IMAGE_SCN_MEM_READ
                    IMAGE_SCN_MEM_WRITE

00000228 2E727372 Name (.rsrc)
0000022C 63000000
00000230 00008304 virtual size
00000234 0000B000 RVA
00000238 00008400 size of raw data
0000023C 00008400 offset to raw data
00000240 00000000 offset to relocations
00000244 00000000 offset to line numbers
00000248     0000 number of relocations
0000024A     0000 number of line numbers
0000024C 40000040 characteristics
                             IMAGE_SCN_CNT_INITIALIZED_DATA
                             IMAGE_SCN_MEM_READ

 

반응형