magic code는 linux에서의 ELF 헤더에서 ASCII값이 "ELF"를 확인할 수 있듯이 MS-DOS 헤더는 "MZ"로 식별가능
typedef struct _IMAGE_DOS_HEADER
{
WORD e_magic; // Magic number
WORD e_cblp; // Byte on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Checksum
WORD e_ip; // Initital IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
이 구조체에서 확인할 점은 e_magic과 e_lfanew만 알아두면 된다. 나머지는 잘 사용하지 않음
e_magic은 2byte
e_lfanew은 4byte의 크기를 가지고 있음
e_lfanew는 IMAGE_NT_HEADER의 구조체 위치를 가르키고 있음(Little Endian)
e_lfanew는 000000D8을 가르키고 있고 해당 주소에 위치하는 값을 확인하면 "PE"(4byte)라는 값이 담겨있는 것을 확인
해당 부분이 PE Header의 시작이라는 점을 알 수 있다
중간 결론
IMAGE_DOS_HEADER에서 e_magic의 값이 0x5A4D는 PE 파일이라는 것과
e_lfanew의 값은 IMAGE_NT_HEADER의 시작 오프셋 값
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;
source : https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_file_header
Machine : 어떤 CPU에서 실행 가능한지 정보
NumberOfSections : 파일이 가진 섹션의 갯수( .text, .data, .rdata, .rsrc )
TimeDateStamp : obj -> EXE파일을 만든 시간을 알림 (델파이 program은 1992년으로 표기)
SizeofOptionalHeader : IMAGE_OPTIONAL_HEADER32의 구조체 크기를 가짐 ( OS마다 크기가 다르기에 PE로더에서는 해당 값을 먼저 확인)
Characteristics : 파일의 형식
IMAGE_OPTIONAL_HEADER
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;
source : https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32
Magic : 32bit -> 0x10B
64bit -> 0x20B
SizeofCode : 코드 양의 전체 크기( executable )
AddressOfEntryPoint : 파일이 메모리에서 시작되는 지점 ( main문 시작 지점?) 보안을 위해 ASLR 적용된 상태
BaseOfCode : 실행 코드 위치 (ImageBase + BaseofCode 의 값부터 코드 시작) 좀더 정확한 주소를 알려주는 것으로 추정
AddressOfEntryPoint와 BaseOfCode의 차이를 잘 모르겠다...
ImageBase : 로드할 가상 메모리 주소 (Linux에서 readelf -h <file> 했을때 EntryPoint 정보와 같은 의미로 느껴짐)
SizeOfImage : 메모리 로드시에 전체 크기
SizeOfHeader : PE header의 크기
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
- VirtualAddress와 Size 필드
- Export, Import, Rsrc 디렉터리와 IAT등의 가상 주소와 크기 정보
각각의 Directory정보는 https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_data_directory
IMAGE_DATA_DIRECTORY (winnt.h) - Win32 apps
Represents the data directory.
learn.microsoft.com
에서 확인함
Sections
프로그램의 실제 내용을 담고 있는 block
IMAGE_SECTION_HEADER
- 각 섹션에 대한 이름, 시작 주소, 사이즈 등의 정보를 관리하는 구조체
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
SOURCE : https://learn.microsoft.com/ko-kr/windows/win32/api/winnt/ns-winnt-image_section_header
처음 공부할때는 뭔 소리인지 정말 모르겠고 어렵게 느껴졌는데 학교에서 linux에 대해서 공부하고 방학기간에 다시 공부하니까 linux 파일 구조와 유사한 점도 있어서 그런지 이해가 조금씩 되는것 같다.
해당 글은 일단 이런게 있다 라는 정도로 나중에 필요한 정보를 찾기 위해 가독성 없이 마구잡이로 넣은 느낌이 있는데 추후에 좀더 공부하면서 정리해 나가는 것이 좋다고 생각한다.
'공부 > Reversing' 카테고리의 다른 글
PE Packer (0) | 2023.12.29 |
---|---|
PE구조 (1) | 2023.12.22 |
리버싱 핵심원리 Day1 (0) | 2023.08.02 |