2

我正在尝试逐字节读取其内存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 alignment10000 base of code这两者似乎都包含我需要避免崩溃和访问冲突的正确值。

是什么原因造成的,为什么它只发生在 ntdll 中?

4

1 回答 1

2

如您的转储中所示,加载的图像中有间隙。文件头在 0x77df0000 处加载,然后 .text 部分在 0x77e00000 处加载 64k 字节。这是您在帖子中提到的 64k 部分对齐的结果。我不知道是否有任何不寻常的部分对齐的原因,除了他们想要一些缓冲区或其他元素分配有 64k 对齐的明显原因。这可能与VirtualAlloc 具有 64k 粒度这一事实有关。

您可以使用 VirtualQuery 来确定哪些页面是有效的。每次您的“for 循环”前进到一个新页面时,然后调用 VirtualQuery。如果State值为 MEM_COMMIT 并且该AllocationProtect值设置了 PAGE_EXECUTE_READ、PAGE_EXECUTE_READWRITE、PAGE_READONLY 或 PAGE_READWRITE 位之一,并且AllocatonProtect值没有设置 PAGE_GUARD 位,那么您知道该页面存在并且是可读的。如果不是,那么您可以使用该RegionSize值跳过该页面,以及它后面具有相同状态的每个页面。

您还可以解析 0x77df0000 处的 PECOFF 标头以找出这些部分的加载位置,但这要复杂一些。

于 2015-06-13T19:27:09.783 回答