ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [리버싱 핵심원리 study] 38장 PE32+
    Reverse Engineering 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바이트)로 변경된 것을 확인할 수 있다.

    반응형

    댓글

Designed by Tistory.