Reverse Engineering

[리버싱 핵심원리 study] 38장 PE32+

maple19out 2021. 2. 2. 19:55

64bit Windows OS에서 사용되는 실행 파일 형식인 PE32+에 대해 알아본다. 예가 필요한 경우 notepad.exe의 32bit 버전과 64bit 버전의 비교를 해보자.

 

1. PE32+(PE+, PE64)

(1) IMAGE_NT_HEADERS

- 32bit

typedef struct _IMAGE_NT_HEADERS {
  DWORD                   Signature;
  IMAGE_FILE_HEADER       FileHeader;
  IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

 

- 64bit

typedef struct _IMAGE_NT_HEADERS64 {
  DWORD                   Signature;
  IMAGE_FILE_HEADER       FileHeader;
  IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

위와 같이 마지막 멤버인 IMAGE_OPTIONAL_HEADER 부분이 32bit 혹은 64bit에 의해 IMAGE_NT_HEADERS32 / IMAGE_NT_HEADERS64로 나뉜다.

 

(2) IMAGE_FILE_HEADER

typedef struct _IMAGE_FILE_HEADER {
  WORD  Machine;
  WORD  NumberOfSections;
  DWORD TimeDateStamp;
  DWORD PointerToSymbolTable;
  DWORD NumberOfSymbols;
  WORD  SizeOfOptionalHeader;
  WORD  Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

PE32에서는 Machine 멤버 값이 014C로 고정되었는데, PE32+에서는 8664(AMD64)로 변경되었다.

 

notepad.exe (32bit)

 

notepad.exe (64bit)

 

(3) IMAGE_OPTIONAL_HEADER

- 32bit

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;

 

- 64bit

typedef struct _IMAGE_OPTIONAL_HEADER64 {
  WORD                 Magic;
  BYTE                 MajorLinkerVersion;
  BYTE                 MinorLinkerVersion;
  DWORD                SizeOfCode;
  DWORD                SizeOfInitializedData;
  DWORD                SizeOfUninitializedData;
  DWORD                AddressOfEntryPoint;
  DWORD                BaseOfCode;
  ULONGLONG            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;
  ULONGLONG            SizeOfStackReserve;
  ULONGLONG            SizeOfStackCommit;
  ULONGLONG            SizeOfHeapReserve;
  ULONGLONG            SizeOfHeapCommit;
  DWORD                LoaderFlags;
  DWORD                NumberOfRvaAndSizes;
  IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

PE32+에서 기존과 가장 많이 달라진 부분이다. 달라진 부분은 다음과 같다.

 

- Magic

기존 PE32에서의 Magic 넘버는 010B이지만 PE32+에서는 020B다.

 

- ImageBase

ImageBase의 자료형이 ULONGLONG으로 바꼈다. 이는 64bit 환경에서 가상 메모리 크기가 확장되면서 프로세스가 올라갈 수 있는 주소의 범위도 확장되었기 때문이다. 

 

- Stack & Heap

스택과 힙을 위한 데이터의 자료형의 크기 또한 마찬가지 이유로 ULONGLONG으로 변경되었다.

 

달라진 위 세 부분을 CFF Explorer를 통해 찾아보면 아래와 같다.

notepad.exe 32bit
notepad.exe 64bit

(4) IMAGE_THUNK_DATA

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
	union {
    	DWORD Characteristics;
        DWORD OriginalFirstThunk;
    } DUMMYUNIONNAME;
    DWORD TimeDateStamp;
    DWORD ForwarderChain;
    DWORD Name;
    DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

IMAGE_IMPORT_DESCRIPTOR 구조체의 INT, IAT에 해당하는 OriginalFirstThunk, FirstThunk는 IMAGE_THUNK_DATA 구조체 리스트의 RVA이다. 이때 기존 PE32는 IMAGE_THUNK_DATA가 4바이트 배열을 이루었지만, PE32+에서는 8바이트 배열이 나타난다.

 

(5) IMAGE_TLS_DIRECTORY

- 32bit

typedef struct _IMAGE_TLS_DIRECTORY32
{
    DWORD   StartAddressOfRawData;
    DWORD   EndAddressOfRawData;
    DWORD   AddressOfIndex;           
    DWORD   AddressOfCallBacks;  
    DWORD   SizeOfZeroFill;
    DWORD   Characteristics;
} IMAGE_TLS_DIRECTORY32;
typedef IMAGE_TLS_DIRECTORY32*  PIMAGE_TLS_DIRECTORY32;

 

-64bit

typedef struct _IMAGE_TLS_DIRECTORY64
{
    ULONGLONG   StartAddressOfRawData;
    ULONGLONG   EndAddressOfRawData;
    ULONGLONG   AddressOfIndex;        
    ULONGLONG   AddressOfCallBacks;    
    DWORD           SizeOfZeroFill;
    DWORD           Characteristics;
} IMAGE_TLS_DIRECTORY64;
typedef IMAGE_TLS_DIRECTORY64*  PIMAGE_TLS_DIRECTORY64;

위와 같이 몇 멤버가 DWORD(4바이트)에서 ULONGLONG(8바이트)로 변경된 것을 확인할 수 있다.

반응형