windows 시스템 실행파일의 구조와 원리 책 내용을 요약 및 정리 하는 포스팅이에요.
PE파일의 PE 시그니처 다음에 이어지는 IMAGE_FILE_HEADER에 대한 내용을 알아볼 거에요.
IMAGE_FILE_HEADER 구조체
IMAGE_FILE_HEADER 구조체는 20바이트로 구성이 되어 있어요.
이것도 당연히 “WinNT.h” 헤더 파일에 정의되어 있어요.
1 | typedef struct _IMAGE_FILE_HEADER { |
구조체 멤버에 대해 하나씩 설명을 해드릴게요.
첫 번째 멤버, WORD Machine
Machine 필드는 PE 파일의 CPU ID를 나타내요. 즉, 사용자가 어떤 CPU를 통해서 PE 파일을 생성했는지 알 수 있어요.
C언어와 C++로 짜여진 코드 같은 경우에는 CPU 의존적이라서 이런 정보가 들어가 있나봐요.
이것도 CPU ID에 해당하는 매크로 상수가 정의되어 있는데, 자주 사용되는 매크로 상수는 아래와 같아요
1 |
두 번째 멤버, WORD NumberOfSections
PE 파일에서의 섹션의 수를 나타내요. IMAGE_SECTION_HEADER 구조체 배열의 원소의 개수. 즉, 해당 PE 파일의 섹션의 개수를 의미해요.
세 번째 멤버, DWORD TimeDateStamp
OBj 파일이라면 컴파일러가, EXE 또는 DLL과 같은 PE 파일이라면 링커가 해당 파일을 만들어낸 시간을 의미해요.
이 값은 1970년 1월 1일 09시(GMT 시간 기준)로부터 해당 파일을 만들어낸 시점까지의 초 단위로 표현해요.
네 번째 멤버, DWOARD PointerToSymbolTable
PointerToSymbolTable 필드는 말 그대로 심볼 테이블의 데이터를 가리키는 주소 값이 들어가는 영역이에요. 즉, COFF 심벌의 파일 오프셋 값을 가지고 있는 거에요.
이 필드 같은 경우에는 컴파일러에 의해 생성되는 OBJ 파일 또는 디버그 모드로 만들어져서 COFF 디버그 정보를 가진 PE 파일에서만 사용이 되요.
PE 파일은 복수의 디버그 포맷을 지원하기 떄문에 IMAGE_DIRECTORY_ENTRY_DEBUG 엔트리를 참조해야 되고요.
요즘에는 COFF 심벌 테이블은 새로운 디버그 포맷에 의해 대체되어서 PE 파일 내에서는 거의 사용하지 않아요.
물론 링커 스위치를 /DEBUGTYPE:COFF로 지정할 경우 생성할 수 있어요.
다섯 번째 멤버, DOWRD NumberOfSymbols
PointerToSymbolTable 필드가 가리키는 COFF 심벌 테이블 내에서의 심벌의 수를 나타냄.
이것도 마찬가지로 새로운 디버그 포맷에 의해 대체되어서 사용되지 않음.
여섯 번째 멤버, WORD SizeOfOptionalHeader
IMAGE_FILE_HEADER 구조체 바로 다음에 이어서 나오는 IMAGE_OPTIONAL_HEADER 구조체의 바이트 수를 나타내요.
이 필드는 OBJ 파일의 경우 0이고, 실행 파일의 경우는 “sizeof(IMAGE_OPTIONAL_HEADER)”의 값을 가져요.
32비트 PE 파일의 경우 0xE0(224)바이트이고, 64비트 PE 파일의 경우 0xF0(240)바이트에요.
일곱 번째 멤버, WORD Characteristics
PE 파일에 대한 특정 정보를 나타내는 플래그에요. 이 필드도 “WinNT.h” 헤더 파일에 정의되어 있어요.
1 |
이 중에서도 중요한 것은 요것들이에요.
매크로명 | 값 | 의미 |
---|---|---|
IMAGE_FILE_RELOCS_STRIPPED | 0x0001 | 현재 파일에 재배치 정보가 없음 |
IMAGE_FILE_EXECUTABLE_IMAGE | 0x0002 | 본 파일은 실행 파일 이미지이다. |
IMAGE_FILE_LINE_NUMS_STRIPPED | 0x0004 | 본 파일에 라인 정보가 없다. |
IMAGE_FILE_LOCAL_SYMS_STRIPPED | 0x0008 | 본 파일에 로컬 심벌이 없다. |
IMAGE_FILE_AGGRESIVE | 0x0010 | OS로 하여금 적극적으로 워킹셋을 정리할 수 있도록 한다 |
IMAGE_FILE_LARGE_ADD_RESS_AWARE | 0x0020 | 애플리케이션이 2G 이상의 가상 주소 번지를 제어할 수 있도록한다. |
IMAGE_FILE_32BIT_MACHINE | 0x0100 | 본 PE는 32비트 워드 머신을 필요로 한다. |
IMAGE_FILE_DEBUG_STRIPPED | 0x0200 | 디버그 정보가 본 파일에는 없고 .DBG 파일에 존재한다. |
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP | 0x0400 | PE 이미지가 이동 가능한 장치 위에 존재할 때 고정 디스크 상의 스왑 파일로 카피해서 실행한다. |
IMAGE_FILE_NET_RUN_FROM_SWAP | 0x0800 | PE 이미지가 네트워크 상에 존재할 때 고정 디스크 상의 스왑 파일로 카피해서 실행한다. |
IMAGE_FILE_DLL | 0x2000 | 본 파일은 동적 링크 라이브러리 파일이다. |
IMAGE_FILE_UP_SYSTEM_ONLYT | 0x4000 | 본 파일은 하나의 프로세서만을 장착한 머신에서 실행된다. |
마지막으로…
IMAGE_FILE_HEADER에 대해서 살펴봤는데요.
여기서 중요한 멤버들은 섹션의 수를 조절할 수 있는 NumberOfSections 하고, PE 파일에 대한 특정 정보는 나타내는 플래그인 Characteristics 이에요.
NumberOfSections을 조절하면, 우리가 원하는대로 임의의 섹션을 추가할 수 있어요. 이러한 방법을 이용해서 악성코드를 삽입도 가능하다고 해요!
PE 파일에 특정 정보를 나타내는 플래그인 Characteristics 값의 조합을 알고 있으면, PE 파일을 분석할 필요 없이 이 값만을 가지고 PE 파일이 어떤 특징을 가지고 있는지 알 수 있을 거에요.