我正在尝试逐字节读取我的可执行文件中加载的ntdll.dll
内存。
可执行文件在我的x64 windows 7计算机上编译为x32可执行文件。
我编写了一个名为FindPattern
的函数,它接收一个特定的字节数组,并在ntdll.dll模块中查找这个字节数组。
我已经在其他模块上检查了这个功能,我确信它能正常工作。
现在当我在我的ntdll模块上使用这个函数时,它会在读取内存ntdll + 0x1000时崩溃。
我在windbg上检查了这个,而windbg也不能读取内存:
0:000> db ntdll + FF0 L20
77df0ff0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
77df1000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
我不知道为什么会发生这种情况,但它包含0x9000字节
0:000> db ntdll + FFF0 L20
77dffff0 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
77e00000 8b 44 24 04 cc c2 04 00-cc 90 c3 90 cc c3 90 90 .D$.............
它没有发生在我检查的任何其他DLL ..问题可以使用ReadProcessMemory
绕过,但我想了解是什么导致它。
运行!dh命令结果:
0:000> !dh ntdll
File Type: DLL
FILE HEADER VALUES
14C machine (i386)
5 number of sections
55636317 time date stamp Mon May 25 20:59:51 2015
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
2102 characteristics
Executable
32 bit word machine
DLL
OPTIONAL HEADER VALUES
10B magic #
9.00 linker version
D6400 size of code
67400 size of initialized data
0 size of uninitialized data
0 address of entry point
10000 base of code
----- new -----
77df0000 image base
10000 section alignment
200 file alignment
3 subsystem (Windows CUI)
6.01 operating system version
6.01 image version
6.01 subsystem version
180000 size of image
400 size of headers
14C3B3 checksum
00040000 size of stack reserve
00001000 size of stack commit
00100000 size of heap reserve
00001000 size of heap commit
140 DLL characteristics
Dynamic base
NX compatible
10218 [ F6D2] address [size] of Export Directory
0 [ 0] address [size] of Import Directory
110000 [ 5A028] address [size] of Resource Directory
0 [ 0] address [size] of Exception Directory
13C600 [ 3A18] address [size] of Security Directory
170000 [ 4D30] address [size] of Base Relocation Directory
E60F4 [ 38] address [size] of Debug Directory
0 [ 0] address [size] of Description Directory
0 [ 0] address [size] of Special Directory
0 [ 0] address [size] of Thread Storage Directory
71C80 [ 40] address [size] of Load Configuration Directory
0 [ 0] address [size] of Bound Import Directory
0 [ 0] address [size] of Import Address Table Directory
0 [ 0] address [size] of Delay Import Directory
0 [ 0] address [size] of COR20 Header Directory
0 [ 0] address [size] of Reserved Directory
SECTION HEADER #1
.text name
D6153 virtual size
10000 virtual address
D6200 size of raw data
400 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
(no align specified)
Execute Read
Debug Directories(2)
Type Size Address Pointer
cv 23 e6130 d6530 Format: RSDS, guid, 2, wntdll.pdb
( 10) 4 e612c d652c
SECTION HEADER #2
RT name
1C9 virtual size
F0000 virtual address
200 size of raw data
D6600 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
(no align specified)
Execute Read
SECTION HEADER #3
.data name
82A8 virtual size
100000 virtual address
6E00 size of raw data
D6800 file pointer to raw data
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
(no align specified)
Read Write
SECTION HEADER #4
.rsrc name
5A028 virtual size
110000 virtual address
5A200 size of raw data
DD600 file pointer to raw data
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
(no align specified)
Read Only
SECTION HEADER #5
.reloc name
4D30 virtual size
170000 virtual address
4E00 size of raw data
137800 file pointer to raw data
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
(no align specified)
Read Only
为什么这个10000 section alignment
和10000 base of code
似乎都包含了我需要避免崩溃和访问冲突的正确值。
是什么导致了它,为什么它只发生在ntdll?
答案 0 :(得分:2)
如您的转储中所示,加载的图片中存在间隙。文件头加载到0x77df0000,然后.text段在0x77e00000之后加载64k字节。这是您在帖子中记下的64k部分对齐的结果。我不知道是否有任何不寻常的部分对齐的原因,除了他们想要一些缓冲区或其他元素分配64k对齐的明显原因。它可能与VirtualAlloc has 64k granularity这一事实有某种关系。
您可以使用VirtualQuery确定哪些页面有效。每次你的" for循环"进入新页面然后调用VirtualQuery。如果State
值为MEM_COMMIT且AllocationProtect
值具有PAGE_EXECUTE_READ,PAGE_EXECUTE_READWRITE,PAGE_READONLY或PAGE_READWRITE位集之一且AllocatonProtect
值未设置PAGE_GUARD位,那么您知道该页面存在且可读。如果没有,那么您可以使用RegionSize
值跳过该页面,以及其后面具有相同状态的每个页面。
您还可以解析0x77df0000处的PECOFF标头以找出加载部分的位置,但这有点复杂。