PE 포맷 개발 시 고려사항
PE 포맷 ( Portable Executable Format ) 개발 시 고려사항은 다음과 같습니다. IMAGE_NT_HEADERS
구조체 크기가 플랫폼 ( x86 또는 x64 )에 따라서 다르기 때문에 분석할 이미지의 플랫폼을 먼저 판단하여 주소를 계산해야 합니다.
보통 PE 분석 코드는 대부분 다음과 같이 PIMAGE_NT_HEADERS
구조체로 부터 필요한 테이블의 주소를 구하여 계산합니다.
PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((LPBYTE)pData + ((PIMAGE_DOS_HEADER)pData)->e_lfanew);
위와 같이 코드를 작성한 경우 실행 플랫폼과 분석할 이미지 플랫폼이 다르면 문제가 없지만 다르면 문제가 발생합니다.
분석 대상 ( x86 ) | 분석 대상 ( x64 ) | |
32 비트 애플리케이션 | 문제 없음 | 문제 발생 |
64 비트 애플리케이션 | 문제 발생 | 문제 없음 |
아래 코드와 같이 IMAGE_NT_HEADER 정의 값이 x86 및 x64가 다르기 때문에 잘못된 주소가 매핑되어 프로그램이 종료될 수 있습니다.
typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
#ifdef _WIN64
typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS;
typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS;
#else
typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS;
typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;
#endif
아래 그림에서와 같이 Optional Header에서 PE32 또는 PE32+ 로 PE 포맷을 구분할 수 있으며 분석 대상이 32비트 애플리케이션, 즉 PE32일 경우는 IMAGE_NT_HEADERS32 구조체를로 그리고 분석 대상이 64비트 애플리케이션, 즉 PE32+일 경우는 IMAGE_NT_HEADER64 구조체를 사용해야 합니다.