xp下用户措施空间分派(4):加载主措施
副标题#e#
这个是主措施,它的模块信息:
名称 | 基址 | 巨细 | 进口点 |
f:\embed\etools\Debug\bin\bash.exe | 00400000 | 0006f000 | 0045bb30 |
对应的内存块:
这些块的范例都是MEM_IMAGE,且分派时的掩护符号都是PAGE_EXECUTE_WRITECOPY,MSDN这样表明这 个符号位:
Enables execute, read, and write access to the committed region of image file code pages. The pages are shared read-on-write and copy-on-write.
这几个内存块的分派基址 都是一样的,揣摩windows是为整个文件申请了一块大的空间,然后将文件内里的section别离写入到不 同的区域内里去。
用下面的呼吁行将所有的信息dump出来。
dumpbin /all bash.exe
#p#副标题#e#
再把它们和内存里的数据举办较量。
1.1 文件头
先看从原始文件中dump出来的文件头:
FILE HEADER VALUES
14C machine (x86)
5 number of sections
4A910052 time date stamp Sun Aug 23 16:39:46 2009
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
102 characteristics
Executable
32 bit word machine
一共有5个section,可是上 面有6个块,怎么就对应不上呢,想来0x0040 0000这个块应该是文件头信息:
0x00400000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 MZ..............
0x00400010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 [email protected]
0x00400020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00400030 00 00 00 00 00 00 00 00 00 00 00 00 e0 00 00 00 ................
0x00400040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 ........!..L.!Th
0x00400050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f is program canno
0x00400060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 t be run in DOS
0x00400070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 mode....$.......
0x00400080 b0 80 2d 3c f4 e1 43 6f f4 e1 43 6f f4 e1 43 6f .€-<..Co..Co..Co
0x00400090 49 ae d5 6f f9 e1 43 6f ea b3 d6 6f ff e1 43 6f I..o..Co...o..Co
0x004000A0 ea b3 c7 6f f3 e1 43 6f ea b3 d0 6f f0 e1 43 6f ...o..Co...o..Co
0x004000B0 f4 e1 42 6f 5f e1 43 6f d3 27 38 6f f3 e1 43 6f ..Bo_.Co.'8o..Co
0x004000C0 ea b3 c0 6f 88 e1 43 6f ea b3 d2 6f f5 e1 43 6f ...o..Co...o..Co
0x004000D0 52 69 63 68 f4 e1 43 6f 00 00 00 00 00 00 00 00 Rich..Co........
0x004000E0 50 45 00 00 4c 01 05 00 49 a8 94 4a 00 00 00 00 PE..L...I..J....
0x004000F0 00 00 00 00 e0 00 02 01 0b 01 09 00 00 be 05 00 ................
0x00400100 00 e2 00 00 00 00 00 00 30 bb 05 00 00 10 00 00 ........0.......
0x00400110 00 d0 05 00 00 00 40 00 00 10 00 00 00 02 00 00 [email protected]
0x00400120 05 00 00 00 00 00 00 00 05 00 00 00 00 00 00 00 ................
0x00400130 00 f0 06 00 00 04 00 00 60 40 07 00 03 00 40 81 ........`@[email protected]
0x00400140 00 00 10 00 00 10 00 00 00 00 10 00 00 10 00 00 ................
0x00400150 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 ................
这些内存数据和原始文件头内里的数据是完全沟通的。
在c运行库里提 供了一个叫__ImageBase的全局变量,存放这个变量的地点就在0x0040 0000,下面给出这个布局体成员 的一些值:
e_magic | 0x5a4d | unsigned short |
e_cblp | 0x0090 | unsigned short |
e_cp | 0x0003 | unsigned short |
e_crlc | 0x0000 | unsigned short |
e_cparhdr | 0x0004 | unsigned short |
e_minalloc | 0x0000 | unsigned short |
e_maxalloc | 0xffff | unsigned short |
e_ss | 0x0000 | unsigned short |
e_sp | 0x00b8 | unsigned short |
e_csum | 0x0000 | unsigned short |
e_ip | 0x0000 | unsigned short |
e_cs | 0x0000 | unsigned short |
e_lfarlc | 0x0040 | unsigned short |
e_ovno | 0x0000 | unsigned short |
e_res | 0x0040001c "" | unsigned short [4] |
e_oemid | 0x0000 | unsigned short |
e_oeminfo | 0x0000 | unsigned short |
e_res2 | 0x00400028 "" | unsigned short [10] |
e_lfanew | 0x000000e0 | long |
留意系统对这个区域的掩护:
这个区域将是只读的。
#p#分页标题#e#
按照PE文件的划定,在0x3c这个偏移量的位置(也就是 __ImageBase.e_lfanew这个成员)指明白IMAGE_FILE_HEAD的偏移量。我们直接用一个IMAGE_FILE_HEAD 指针指向这个位置,就可以看到IMAGE_FILE_HEAD的值了:
Machine | 0x014c | unsigned short |
NumberOfSections | 0x0005 | unsigned short |
TimeDateStamp | 0x4a94cfc5 | unsigned long |
PointerToSymbolTable | 0x00000000 | unsigned long |
NumberOfSymbols | 0x00000000 | unsigned long |
SizeOfOptionalHeader | 0x00e0 | unsigned short |
Characteristics | 0x0102 | unsigned short |
再凭据这个布局体获得的SizeOfOptionalHeader,我们将得以遍历所有的section head。
紧接着 IMAGE_FILE_HEAD之后的是一个叫IMAGE_OPTIONAL_HEAD的布局体,我们直接用一个指针指向这个位置并 获得实际的值:
把它和从文件内里DUMP出来的数据较量,可以发明它们是一致的:
OPTIONAL HEADER VALUES
10B magic # (PE32)
9.00 linker version
5BE00 size of code
E200 size of initialized data
0 size of uninitialized data
5BB60 entry point (0045BB60) _mainCRTStartup
1000 base of code
5D000 base of data
400000 image base (00400000 to 0046EFFF)
1000 section alignment
200 file alignment
5.00 operating system version
0.00 image version
5.00 subsystem version
0 Win32 version
6F000 size of image
400 size of headers
6F1FE checksum
3 subsystem (Windows CUI)
8140 DLL characteristics
Dynamic base
NX compatible
Terminal Server Aware
100000 size of stack reserve
1000 size of stack commit
100000 size of heap reserve
1000 size of heap commit
0 loader flags
10 number of directories
0 [ 0] RVA [size] of Export Directory
63354 [ 78] RVA [size] of Import Directory
68000 [ 2B4] RVA [size] of Resource Directory
0 [ 0] RVA [size] of Exception Directory
0 [ 0] RVA [size] of Certificates Directory
69000 [ 5844] RVA [size] of Base Relocation Directory
5D2E0 [ 1C] RVA [size] of Debug Directory
0 [ 0] RVA [size] of Architecture Directory
0 [ 0] RVA [size] of Global Pointer Directory
0 [ 0] RVA [size] of Thread Storage Directory
62EE0 [ 40] RVA [size] of Load Configuration Directory
0 [ 0] RVA [size] of Bound Import Directory
5D000 [ 2C0] RVA [size] of Import Address Table Directory
0 [ 0] RVA [size] of Delay Import Directory
0 [ 0] RVA [size] of COM Descriptor Directory
0 [ 0] RVA [size] of Reserved Directory
1.2 代码段
先看看从bash.exe内里dump出来的信息:
#p#分页标题#e#
SECTION HEADER #1
.text name
5BC4E virtual size
1000 virtual address (00401000 to 0045CC4D)
5BE00 size of raw data
400 file pointer to raw data (00000400 to 0005C1FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
Execute Read
它请求的地 址是0x0040 1000,看看在内存里的section head:
下面是windows为这个段分派的内存块:
显然windows是满意文件的请求了。
再较量dump出来的代码段的原始数据和内存里的数据:
0x00401000 55 8b ec 81 ec d4 00 00 00 53 56 57 8d bd 2c ff U........SVW..,.
0x00401010 ff ff b9 35 00 00 00 b8 cc cc cc cc f3 ab 8b 45 ...5...........E
0x00401020 14 83 e0 01 89 45 f8 8b 45 08 0f be 08 83 f9 3d .....E..E......=
可以发明它们的内容是一致的。
在vs2008内里可以看到这段代码反汇编的功效:
int
binary_test (op, arg1, arg2, flags)
char *op, *arg1, *arg2;
int flags;
{
00401000 55 push ebp
00401001 8B EC mov ebp,esp
00401003 81 EC D4 00 00 00 sub esp,0D4h
00401009 53 push ebx
0040100A 56 push esi
0040100B 57 push edi
0040100C 8D BD 2C FF FF FF lea edi,[ebp-0D4h]
00401012 B9 35 00 00 00 mov ecx,35h
00401017 B8 CC CC CC CC mov eax,0CCCCCCCCh
0040101C F3 AB rep stos dword ptr es:[edi]
int patmatch;
………………
由此可见windows应该是把这个段的 内容原封不动地读进来了,执行时PC指针将指向这块内存的数据。
1.3 只读数据段
这是exe内里的第二个段,看看它的section head:
.rdata name
6FD0 virtual size
5D000 virtual address (0045D000 to 00463FCF)
7000 size of raw data
5C200 file pointer to raw data (0005C200 to 000631FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
Read Only
再看内存内里 的section head:
同样,满意了文件的要求。
这个只读数据段的绝大部门数据与文件中读出的一致,可是对付导入 表之类的数据,在加载到内存之后将由windows动态变动。
1.4 数据段
先看看从文件中dump出来的section head:
SECTION HEADER #3
.data name
352C virtual size
64000 virtual address (00464000 to 0046752B)
1400 size of raw data
63200 file pointer to raw data (00063200 to 000645FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C0000040 flags
Initialized Data
Read Write
再看看内存内里的section head:
从这里可以看到,实际上这个段的内存是分为两部门的,第一个部门用于存放Relocation table,第 二个部门才是措施里的全局变量。因为第二个部门是答允在措施中修改的,因此它的掩护符号配置成了 PAGE_READWRITE。
随便在措施内里找个全局变量,看一下地点,简直是落在这个范畴的,呵呵。前几 天还使劲在想怎么取得数据段的首地点,得来全不费时光!用VirtualQuery足矣!
1.5 .rsrc
先看看从bash.exe内里dump出来的section head:
SECTION HEADER #4
.rsrc name
2B4 virtual size
68000 virtual address (00468000 to 004682B3)
400 size of raw data
64600 file pointer to raw data (00064600 to 000649FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
Read Only
再看看内存内里的section head:
这一块的内容和从文件中读取的内容完全一致。
1.6 .reloc
先看看从文件中dump出来的头:
#p#分页标题#e#
SECTION HEADER #5
.reloc name
58D0 virtual size
69000 virtual address (00469000 to 0046E8CF)
5A00 size of raw data
64A00 file pointer to raw data (00064A00 to 0006A3FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
42000040 flags
Initialized Data
Discardable
Read Only
再看看内存内里的section head:
较量发明它在内存中的数据和从文件中读取出来的原始数据是一致的。Reloc的进程暂且不管,再看 看其它的对象。