DOS头IMAGE_DOS_HEADER
2021-07-01
545
0
无论是32位或64位可执行文件,其文件的头部必定是IMAGE_DOS_HEADER.
IMAGE_DOS_HEADER 数据结构定义如下:
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes 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; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial 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;
使用PE工具,查看该结构体的数据内容:
在IMAGE_DOS_HEADER中,最重要的一个成员为e_lfanew,其指向该结构体相对IMAGE_NT_HEADERS的偏移地址。
DOS存根
在IMAGE_DOS_HEADER和IMAGE_NT_HEADERS之间存在一DOS存根,这其实是一段汇编代码:
其功能是当该EXE运行在16位环境下,输出一段文字:“This program cannot be run in DOS mode”,然后并退出该进程。
PE文件是运行在32位或64位操作系统下的。
使用方法
如我们在某一进程中,可通过GetModule获取该进程的内存映射地址,而这个地址其实就是IMAGE_DOS_HEADER的地址,通过IMAGE_DOS_HEADER的地址加上e_lfanew的值即可计算出IMAGE_NT_HEADERS的地址。
HMODULE hMod = ::GetModuleHandle(NULL);
IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)hMod;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((BYTE*)hMod + pDosHeader->e_lfanew);