我也不知道为什么我把内存图 贴了上去,可显示不出来。
如果有内存图说起来就比较好理解,可是没有,那我先这样大概的说吧,
首先一个PE文件是有几个结构体组成的 第一个是 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;
}这个结构体是为了解决十六位和32位的兼容性,它里面有一个重要的 成员变量, 即最后一个LONG e_lfanew ,他表示的是IMAGE_NT_HEADER的偏移量,也就是说我们可以通过IMAGE_DOS_HEADER里面的成员变量e_lfanew可以找见IMAGE_NT_HEADER,这里就有人问了,什么事IMAGE_NT_HEADER啊,那好我来解释一下,他也是一个结构体,它里面有四个成员变量,你们查一下MSDN就知道了,算了我还是大概说一下吧
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; //这个参数是用来判断是不是一个PE文件的,当然不是一个绝对的参数,判断一个有效地PE文件还是需要其他参数
IMAGE_FILE_HEADER FileHeader;//这是一个结构体,我下面会说
IMAGE_OPTIONAL_HEADER OptionalHeader;//这个也一样,我下面还会说的 } IMAGE_NT_HEADERS,
*PIMAGE_NT_HEADERS;typedef struct _IMAGE_FILE_HEADER {
WORD Machine; //表示是什么机器型号
WORD NumberOfSections; //表示这个PE文件里面有几个段;你们最好在百度下一个PE文件结构图
DWORD TimeDateStamp; //这个代表一个时间,从1970.1.1好算起
DWORD PointerToSymbolTable; //指向象征表的偏移量
DWORD NumberOfSymbols; //象征表的个数;
WORD SizeOfOptionalHeader;//这个值表示IMAGE_OPTIONAL_HEADER的大小
WORD Characteristics; //这个我不说了 } IMAGE_FILE_HEADER,
*PIMAGE_FILE_HEADER;
我们看见在IMAGE_NT_HEADER里面还有一个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; //这个是映射基地址,对于可执行文件,这个是0x00400000,而对于dll文件这个是0x10000000
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_HEADER,
*PIMAGE_OPTIONAL_HEADER;
今天就写这么多吧,明天继续