windows PE Image 文件分析
2012-03-10 16:22
435 查看
转自:http://www.mouseos.com/windows/PE_image1.html
![](http://www.mouseos.com/images/pe%20%E7%BB%93%E6%9E%84%E5%9B%BE.png)
上面是 windows PE 可执行文件格式的结构图,分为 4 个部分:DOS 文件头、NT 文件头、Section 表以及 Directory 表格。
windows 的 executable image 文件使用的是这种 PE 格式,而 object 文件使用的是 COFF 文件格式。
这里仍然是延续我的风格,以实例看 image 文件格式,这次以 mircrosoft visual studio 2010 的 VC++ 9.0 编译出来经典 windows 程序为例:
这个例子是:
// helloworld.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "helloworld.h" #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_HELLOWORLD, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_HELLOWORLD)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage are only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELLOWORLD)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_HELLOWORLD); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // // FUNCTION: InitInstance(HINSTANCE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hDC; RECT rect; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hDC = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... GetClientRect(hWnd, &rect); DrawText(hDC, TEXT("hello, world"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Message handler for about box. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; } |
1. MS-DOS 文件头
在 image 文件的最开始处就是 DOS 文件头,DOS 文件头包含了 DOS stub 小程序。 在 WinNT.h 文件里定义了一个结构来描述 DOS 文件头。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; |
结构的 e_magic 域是 DOS 头文件签名,它的值是:0x5A4D 代表字符 MZ,它在 WinNT.h 里定义为:
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ |
下面看看 helloworld.exe 的 DOS 文件头内容:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00000000 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 MZ..........??.. 00000010 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ?.......@....... 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000030 00 00 00 00 00 00 00 00 00 00 00 00 F0 00 00 00 ............e... |
文件头)值,也就是 IMAGE_DOS_HEADER 里的 e_lfanew 值,表明 NT 文件头在 image 文件的 0x000000F0 处。
1.1 DOS stub 程序
在 DOS 文件头下面紧跟着一小段 stub 程序,从 0x00000040 - 0x0000004D 共 14 bytes,这段 dos stub 程序是这样的:00000040 0E push cs 00000041 1F pop ds 00000042 BA0E00 mov dx,0xe 00000045 B409 mov ah,0x9 00000047 CD21 int 0x21 00000049 B8014C mov ax,0x4c01 0000004C CD21 int 0x21 |
看看它是怎样运行的:
00000014 00 00 // ip 00000016 00 00 // cs 00000018 40 00 // e_lfarlc |
文件的 0x0000004e 正好这字符串的位置。
2. NT 文件头
NT 文件头是 PE 文件头的核心部分,由 IMAGE_DOS_HEADER 结构的 e_lfanew 域指出它的位置。同样 NT 文件头部分由一个结构 IMAGE_NT_HEADER 来描述,在 WinNT.h 里定义如下:
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; |
PE 文件签名:Signature
IMAGE_FILE_HEADER 文件头:FileHeader
IMAGE_OPTINAL_HEADER(32/64) 可选头:OptionalHeader
IMAGE_NT_HEADERS32 和 IMAGE_NT_HEADERS64 的匹别在于 IMAGE_OPTIONAL_HEADER 结构,分别为:IMAGE_OPTIONAL_HEADERS32 和 IMAGE_OPTIONAL_HEADERS64
在 Win32 下 IMAGE_NT_HEADERS32 是 248 bytes,在 Win64 下 IMAGE_NT_HEADERS64 是 264 bytes,因此 helloworld.exe 的
NT 文件头从 0x000000F0 - 0x000001E7 共 248 bytes
2.1 PE 签名
在 WinNT.h 文件里定义了 PE 文件的签名,它是:#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 |
![](http://www.mouseos.com/images/PE_%E7%AD%BE%E5%90%8D.png)
2.2 IMAGE_FILE_HEADER 文件头结构
PE 签名接着是 IMAGE_FILE_HEADER 结构,它在 WinNT.h 中的定义为: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; |
[align=center]域[/align] | [align=center]size[/align] | [align=center]值[/align] | [align=center]描述[/align] |
[align=center]Machine[/align] | [align=center]WORD[/align] | [align=center]IMAGE_FILE_MACHINE_xxx[/align] | [align=center]表示目标平台 processor 类型,例:IMAGE_FILE_MACHINE_I386[/align] |
[align=center]NumberOfSections[/align] | [align=center]WORD[/align] | [align=center]节数量[/align] | [align=center]表示映象中有多少个 section[/align] |
[align=center]TimeDataStamp[/align] | [align=center]DWORD[/align] | [align=center]从1970年1月1日0:00 以来的总秒数[/align] | [align=center]表示文件创建的时间[/align] |
[align=center]PointerToSymbolTable[/align] | [align=center]DWORD[/align] | [align=center]COFF 符号表偏移量[/align] | [align=center]在 image 文件中很少见,总是为 0[/align] |
[align=center]NumberOfSymbols[/align] | [align=center]DWORD[/align] | [align=center]COFF 符号表的个数[/align] | [align=center]如果存在的话,表示符号表的个数[/align] |
[align=center]SizeOfOptionalHeader[/align] | [align=center]WORD[/align] | [align=center]IMAGE_OPTIONAL_HEADER 结构大小[/align] | [align=center]该域表示 IMAGE_NT_HEADER 中的 IMAGE_OPTIONAL_HEADER 结构的大小[/align] |
[align=center]Characteristics[/align] | [align=center]WORD[/align] | [align=center]IMAGE_FILE_xxx[/align] | [align=center]表示文件属性,例如:IMAGE_FILE_DLL 属性[/align] |
#define IMAGE_FILE_MACHINE_UNKNOWN 0 #define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. #define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP #define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) |
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. #define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). #define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. #define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. #define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Agressively trim working set #define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses #define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. #define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. #define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file #define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. #define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. #define IMAGE_FILE_SYSTEM 0x1000 // System File. #define IMAGE_FILE_DLL 0x2000 // File is a DLL. #define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine #define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. |
Win64 的 0xF0
下面是 helloworld.exe 的 IMAGE_FILE_HEADER 结构,从 0x000000F4 - 0x00000107 共 20 bytes:
![](http://www.mouseos.com/images/helloworld_IMAGE_FILE_HEADER.png)
将这些值分解为:
000000F4 4C 01 // Machine 000000F8 07 00 // NumberOfSections 000000FA 6C C6 26 4C // TimeDateStamp 000000FE 00 00 00 00 // PointerToSymbolTable 00000100 00 00 00 00 // NumberOfSymbols 00000104 E0 00 // SizeOfOptionalHeader 00000106 02 01 // Characteristics |
NumberOfSections 是 0x07,说明 image 文件内含有 7 个 sections
SizeOfOptionalHeader 是 0xE0,说明接下来的 IMAGE_OPTIONAL_HEADERS32 将是 0xE0(224 bytes)
它的 Characteristics 是 0x102 = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE,说明这个 image 是 32 位可执行的映像。
2.3 IMAGE_OPTIONAL_HEADER32 结构
在 IMAGE_FILE_HEADER 结构里已经指明了 image 是 32 位,并且 IMAGE_OPTIONAL_HEADER 的大小是 224 bytes,那么这个结构就是 IMAGE_OPTIONAL_HEADER32 结构。可以根据 IMAGE_FILE_HEAER 结构的 Machine 来判断 image 是 Win32 还是 Win64 平台的。但是 Microsoft 官方推荐及认可的方法是从 IMAGE_OPTIONAL_HEADER 里的 magic 的值来判断目标平台
。
在 WinNT.h 里 IMAGE_OPTIONAL_HEADER32 的定义如下:
typedef struct _IMAGE_OPTIONAL_HEADER { // // Standard fields. // WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; // // NT additional fields. // 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; |
ImageBase
SizeOfStackReserve
SizeOfStackCommit
SizeOfHeapRerserve
SizeOfHeapCommit
这些域在 64 位结构里被定义为 ULONGLONG 类型。
从 IMAGE_OPTIONAL_HEADER32 的定义可以看出,这个结构分为 基本域 部分和 附加域 部分,它的基本域含义如下:
Offset | Size | Field | Description |
0 | 2 | Magic | The unsigned integer that identifies the state of the image file. The most common number is 0x10B, which identifies it as a normal executable file. 0x107 identifies it as a ROM image, and 0x20B identifies it as a PE32+ executable. |
2 | 1 | MajorLinkerVersion | The linker major version number. |
3 | 1 | MinorLinkerVersion | The linker minor version number. |
4 | 4 | SizeOfCode | The size of the code (text) section, or the sum of all code sections if there are multiple sections. |
8 | 4 | SizeOfInitializedData | The size of the initialized data section, or the sum of all such sections if there are multiple data sections. |
12 | 4 | SizeOfUninitializedData | The size of the uninitialized data section (BSS), or the sum of all such sections if there are multiple BSS sections. |
16 | 4 | AddressOfEntryPoint | The address of the entry point relative to the image base when the executable file is loaded into memory. For program images, this is the starting address. For device drivers, this is the address of the initialization function. An entry point is optional for DLLs. When no entry point is present, this field must be zero. |
20 | 4 | BaseOfCode | The address that is relative to the image base of the beginning-of-code section when it is loaded into memory. |
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b #define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b #define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 |
值 0x20b 说明这个 image 是 64 位的,PE 文件格式是 PE32+
PE32+ 代表的扩展的 PE 文件格式,扩展为 64 位。在 PE 文件规范中并没有 PE64 这种文件格式,Microsoft 官方的判断 image 文件是 32 位还是 64 位的方法就是通过 Magic 的值来确定。
在这些基本的域里可以获得 linker 的版本,text 节,data 节以及 bss 节的大小,
下面看一看 helloworld.exe 的 IMAGE_OPTIONAL_HEADER32 结构的基本域,从 0x00000108 - 0x0000011F
![](http://www.mouseos.com/images/helloworld_IMAGE_OPTIONAL_HEADER1.png)
00000108 0B 01 // Magic 0000010A 0A // MajorLinkerVersion 0000010B 00 // MinorLinkerVersion 0000010C 00 3C 00 00 // SizeOfCode 00000110 00 20 01 00 // SizeOfInitializeData 00000114 00 00 00 00 // SizeOfUninitializeData 00000118 0D 12 01 00 // AddressOfEntryPoint 0000011C 00 10 00 00 // BaseOfCode |
.text 节的 size 是 0x00003C00 bytes,.data 节的 size 是 0x00012000 bytes,还有一个重要的信息,代码的 RVA 入口在 0x0001120D,它是基于 ImageBase 的 RVA 值。代码的基址在 0x00001000,这个是RVA(Relative
Virtual Address)值。
下面再来看一看 IMAGE_OPTIONAL_HEADER32 结构的附加域:
Offset | Size | Field | Description |
24 | 4 | BaseOfData | The address that is relative to the image base of the beginning-of-data section when it is loaded into memory. |
28/24 | 4/8 | ImageBase | The preferred address of the first byte of image when loaded into memory; must be a multiple of 64 K. The default for DLLs is 0x10000000. The default for Windows CE EXEs is 0x00010000. The default for Windows NT, Windows 2000, Windows XP, Windows 95, Windows 98, and Windows Me is 0x00400000. |
32/32 | 4 | SectionAlignment | The alignment (in bytes) of sections when they are loaded into memory. It must be greater than or equal to FileAlignment. The default is the page size for the architecture. |
36/36 | 4 | FileAlignment | The alignment factor (in bytes) that is used to align the raw data of sections in the image file. The value should be a power of 2 between 512 and 64 K, inclusive. The default is 512. If the SectionAlignment is less than the architecture’s page size, then FileAlignment must match SectionAlignment. |
40/40 | 2 | MajorOperatingSystemVersion | The major version number of the required operating system. |
42/42 | 2 | MinorOperatingSystemVersion | The minor version number of the required operating system. |
44/44 | 2 | MajorImageVersion | The major version number of the image. |
46/46 | 2 | MinorImageVersion | The minor version number of the image. |
48/48 | 2 | MajorSubsystemVersion | The major version number of the subsystem. |
50/50 | 2 | MinorSubsystemVersion | The minor version number of the subsystem. |
52/52 | 4 | Win32VersionValue | Reserved, must be zero. |
56/56 | 4 | SizeOfImage | The size (in bytes) of the image, including all headers, as the image is loaded in memory. It must be a multiple of SectionAlignment. |
60/60 | 4 | SizeOfHeaders | The combined size of an MS?DOS stub, PE header, and section headers rounded up to a multiple of FileAlignment. |
64/64 | 4 | CheckSum | The image file checksum. The algorithm for computing the checksum is incorporated into IMAGHELP.DLL. The following are checked for validation at load time: all drivers, any DLL loaded at boot time, and any DLL that is loaded into a critical Windows process. |
68/68 | 2 | Subsystem | The subsystem that is required to run this image. For more information, see “Windows Subsystem” later in this specification. |
70/70 | 2 | DllCharacteristics | For more information, see “DLL Characteristics” later in this specification. |
72/72 | 4/8 | SizeOfStackReserve | The size of the stack to reserve. Only SizeOfStackCommit is committed; the rest is made available one page at a time until the reserve size is reached. |
76/80 | 4/8 | SizeOfStackCommit | The size of the stack to commit. |
80/88 | 4/8 | SizeOfHeapReserve | The size of the local heap space to reserve. Only SizeOfHeapCommit is committed; the rest is made available one page at a time until the reserve size is reached. |
84/96 | 4/8 | SizeOfHeapCommit | The size of the local heap space to commit. |
88/104 | 4 | LoaderFlags | Reserved, must be zero. |
92/108 | 4 | NumberOfRvaAndSizes | The number of data-directory entries in the remainder of the optional header. Each describes a location and size. |
下面是 helloworld.exe 的 IMAGE_OPTIONAL_HEADER32 剩余部分,从 0x00000120 - 0x000001E7
![](http://www.mouseos.com/images/helloworld_IMAGE_OPTIONAL_HEADER2.png)
00000120 00 10 00 00 // BaseOfData 00000124 00 00 40 00 // ImageBase 00000128 00 10 00 00 // SectionAlignment 0000012C 00 02 00 00 // FileAlignment 00000130 05 00 // MajorOperatingSystemVersion 00000132 01 00 // MinorOperatingSystemVersion 00000134 00 00 // MajorImageVersion 00000136 00 00 // MinorImageVersion 00000138 05 00 // MajorSubsystemVersion 0000013A 01 00 // MinorSubsystemVersion 0000013C 00 00 00 00 // Win32VersionVAlue 00000140 00 90 02 00 // SizeOfImage 00000144 00 04 00 00 // SizeOfHeaders 00000148 00 00 00 00 // CheckSum 0000014C 02 00 // Subsystem 0000014E 40 81 // DllCharacteristics 00000150 00 00 10 00 // SizeOfStackReserve 00000154 00 10 00 00 // SizeOfStackCommit 00000158 00 00 10 00 // SizeOfHeapReserve 0000015C 00 10 00 00 // SizeOfHeapCommit 00000160 00 00 00 00 // LoaderFlags 00000164 10 00 00 00 // NumberOfRvaAndSizes 00000168 00 00 00 00 // DataDirectory[0] 0000016C 00 00 00 00 00000170 00 80 01 00 // DataDirectory[1] 00000174 50 00 00 00 00000178 00 90 01 00 // DataDirectory[2] 0000017C 1C E7 00 00 00000180 00 00 00 00 // DataDirectory[3] 00000184 00 00 00 00 00000188 00 00 00 00 // DataDirectory[4] 0000018C 00 00 00 00 00000190 00 80 02 00 // DataDirectory[5] 00000194 40 03 00 00 00000198 20 57 01 00 // DataDirectory[6] 0000019C 1C 00 00 00 000001A0 00 00 00 00 // DataDirectory[7] 000001A4 00 00 00 00 000001A8 00 00 00 00 // DataDirectory[8] 000001AC 00 00 00 00 000001B0 00 00 00 00 // DataDirectory[9] 000001B4 00 00 00 00 000001B8 00 00 00 00 // DataDirectory[10] 000001BC 00 00 00 00 000001C0 00 00 00 00 // DataDirectory[11] 000001C4 00 00 00 00 000001C8 30 82 01 00 // DataDirectory[12] 000001CC E0 01 00 00 000001D0 00 00 00 00 // DataDirectory[13] 000001D4 00 00 00 00 000001D8 00 00 00 00 // DataDirectory[14] 000001DC 00 00 00 00 000001E0 00 00 00 00 // DataDirectory[15] 000001E4 00 00 00 00 |
上面的 SectionAlinment 域值为 0x1000 是表示映象被加载到 virtual address 以是 0x1000(4K byte)为单位的倍数,也就是加载在 virtual address 的 4K 边界上。FileAlinment 域的值为 0x200 表示执行映象从 0x200 为边界开始加载到 virtual address
上。
2.3.1 Directory 表格
在 IMAGE_OPTIONAL_HEADER32 未端是一组 IMAGE_DATA_DIRECTORY 结构的数组,在 WinNT.h 里定义为:// // Directory format. // typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 |
这 16 个 Driectory 指引出 16 不同格式的 table,这 16 个 table 分别是:
[align=center]表项[/align] | [align=center]表格[/align] |
[align=center]0[/align] | [align=center]export table[/align] |
[align=center]1[/align] | [align=center]import table[/align] |
[align=center]2[/align] | [align=center]resource table[/align] |
[align=center]3[/align] | [align=center]exception table[/align] |
[align=center]4[/align] | [align=center]certificate table[/align] |
[align=center]5[/align] | [align=center]base relocation table[/align] |
[align=center]6[/align] | [align=center]debug[/align] |
[align=center]7[/align] | [align=center]architecute[/align] |
[align=center]8[/align] | [align=center]global pointer[/align] |
[align=center]9[/align] | [align=center]TLS table[/align] |
[align=center]10[/align] | [align=center]load configuration table[/align] |
[align=center]11[/align] | [align=center]bound import[/align] |
[align=center]12[/align] | [align=center]import address table[/align] |
[align=center]13[/align] | [align=center]delay import descriptor[/align] |
[align=center]14[/align] | [align=center]CLR runtime header[/align] |
[align=center]15[/align] | [align=center]reserved, must bo zero[/align] |
在我们的实例 helloworld.exe 中使用了 5 个 Driectory,也就是使用了 5 个 Data table,它们是:
import table
resource table
base relocation table
debug table
import address table
[align=center]域[/align] | [align=center]import table[/align] | [align=center]resource table[/align] | [align=center]base relocation bale[/align] | [align=center]debug table[/align] | [align=center]import address table[/align] |
[align=center]VirtualAddress[/align] | [align=center]0x00018000[/align] | [align=center]0x00019000[/align] | [align=center]0x00028000[/align] | [align=center]0x00015720[/align] | [align=center]0x00018230[/align] |
[align=center]size[/align] | [align=center]0x50[/align] | [align=center]0xE71C[/align] | [align=center]0x340[/align] | [align=center]0x1C[/align] | [align=center]0x1E0[/align] |
3. section 表
现在来看一看 helloworld.exe 的 section 表,从 0x000001E8 - 0x000002FF,共 280 bytes这个节表结构在 WinNT.h 中定义为
// // Section header format. // #define IMAGE_SIZEOF_SHORT_NAME 8 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; #define IMAGE_SIZEOF_SECTION_HEADER 40 |
在 helloworld.exe 映象的 IMAGE_FILE_HEADER 结构的 NumberOfSections 域里已经指出 helloworld.exe 映象中包含有 7 个 sections,因此整个 section
表的大小为:280 bytes
helloworld.exe 的 section 表如下:
![](http://www.mouseos.com/images/helloworld_section%E8%A1%A8.png)
这 7 个 section 分别是:
.textbss 节
.text 节
.rdata 节
.data 节
.idata 节
.rsrc 节
.reloc 节
[align=center]域[/align] | [align=center].textbss 节[/align] | [align=center].text 节[/align] | [align=center].rdata 节[/align] | [align=center].data 节[/align] | [align=center].idata 节[/align] | [align=center].rsrc 节[/align] | [align=center].reloc 节[/align] |
VirtualSize | [align=center]0x00010000[/align] | [align=center]0x00003BDB[/align] | [align=center]0x00001CD1[/align] | [align=center]0x00000764[/align] | [align=center]0x00000AAE[/align] | [align=center]0x0000E71C[/align] | [align=center]0x00000564[/align] |
VirtualAddress | [align=center]0x00001000[/align] | [align=center]0x00011000[/align] | [align=center]0x00015000[/align] | [align=center]0x00017000[/align] | [align=center]0x00018000[/align] | [align=center]0x00019000[/align] | [align=center]0x00028000[/align] |
SizeOfRawData | [align=center]0[/align] | [align=center]0x00003C00[/align] | [align=center]0x00001E00[/align] | [align=center]0x00000200[/align] | [align=center]0x00000C00[/align] | [align=center]0x0000E800[/align] | [align=center]0x00000600[/align] |
PointerToRawData | [align=center]0[/align] | [align=center]0x00000400[/align] | [align=center]0x00004000[/align] | [align=center]0x00005E00[/align] | [align=center]0x00006000[/align] | [align=center]0x00006C00[/align] | [align=center]0x00015400[/align] |
PointerToRelocations | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] |
PointerToLinenumbers | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] |
NumberOfRelocations | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] |
NumberOfLinenumbers | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] | [align=center]0[/align] |
Characteristics | [align=center]0xE00000A0[/align] | [align=center]0x60000020[/align] | [align=center]0x40000040[/align] | [align=center]0xC0000040[/align] | [align=center]0xC0000040[/align] | [align=center]0x40000040[/align] | [align=center]0x42000040[/align] |
VirtualAddress 是一个基于 ImageBase 的 RVA 值,它指出 section 的所在,VirtualSize 指出 section 的大小,SizeOfRawData 是在 image 文件里占有的空间,它是 FileAlignment 的倍数,即:0x200 的倍数,也就是说 0x200 的边界。PointerToRawData 是
section 在 image 文件的位置,同样也是 FileAligment 即:0x200 边界上。
相关文章推荐
- windows PE Image 文件分析(5)--- .rsrc 节与 resource table
- windows PE Image 文件分析(1)
- windows PE Image 文件分析(2)--- .text 节
- windows PE Image 文件分析(3)--- .idata 节与 import table
- windows PE Image 文件分析(4)--- 导入函数的绑定
- windows PE Image 文件分析(5)--- .rsrc 节与 resource table
- windows PE Image 文件分析(6)--- .reloc 节与 base relocation table
- 代码分析windows下PE文件格式结构,并附带PE文件格式详细图解
- 结合romimage来分析WINCE下的PE文件特点
- Windows用WinDbg分析蓝屏dump文件查找原因(转)
- Windows下INF驱动安装文件内容分析
- 用非常规手段有效删除Windows怪文件正文分析错误
- PE文件和COFF文件格式分析——节信息
- Windows下INF驱动安装文件内容分析
- 分析:“新一代Windows文件系统”WinFS 夭折的几大因素
- [Windows]_[0基础]_[使用命令行工具dumpbin分析文件]
- Windows下用Python你会几种copy文件的方法以及效率分析
- PE文件结构分析(代码)
- 提取NTLDR文件,分解Osloader.exe;pe文件找e_lfanew、IMAGE_EXPORT_DIRECTORY->AddressOfFunctions
- PE文件学习系列笔记四-C++实现PE文件的分析