1

我目前正试图围绕一些 Windows 后备列表进行思考,并且我看到一些让我感到困惑的内存地址。

由于sergmat原始问题),从我发布的另一个问题中生成了一些代码:

lkd> !lookaside iopsmallirplookasidelist 
Lookaside "" @ 82d5ffc0 "Irps"
....
lkd> dt _SINGLE_LIST_ENTRY 82d5ffc0 
nt!_SINGLE_LIST_ENTRY
+0x000 Next             : 0x86737e30 _SINGLE_LIST_ENTRY
....
lkd> !pool 0x86737e30 
Pool page 86737e30 region is Nonpaged pool
*86737e28 size:   a0 previous size:   48  (Allocated) *Irp 
    Pooltag Irp  : Io, IRP packets  

从上面的 WinDBG 输出中可以看出,在地址 0x82d5ffc0 处有一个单链表。此输出是在 32 位 Windows 7 系统上生成的。

但是,这就是我感到困惑的地方,在 Windows 7 64 位系统上执行相同的操作时,这是输出(地址明显不同):

lkd> !lookaside iopsmallirplookasidelist
Lookaside "" @ fffff80002a14800 "Irps"
....
lkd> dt _SINGLE_LIST_ENTRY fffff80002a14800 
ntdll!_SINGLE_LIST_ENTRY
    +0x000 Next 0x00000000'01bf0003
....
!pool 0x0000000001bf0003
Pool page 000000001bf0003 region is unknown    
...

看起来 的Next0x0000000001bf0003不是有效的虚拟地址,我还尝试对其执行虚拟到物理的转换,但失败了。

看起来这个值是页面的某种偏移量,但我不完全确定应该如何计算地址。

列表标题中还有其他数据,这是一个_SLIST_HEADER结构,位于_SINGLE_LIST_ENTRY. 它包含以下数据:

Alignment: 0x1bf0003
Region: 0xfffffa8001df5b01

在初始标头之后是一系列三个联合,并且由于这是一个 64 位系统,我认为Header16应该使用联合,其中包含以下内容:

Depth: 0x3
Sequence: 0x1bf
HeaderType: 0x1
Init: 0x0
Reserved: 0x0
NextEntry: 0xfffffa8001df5b0

Header16.NextEntry元素确实包含一个有效的虚拟地址,所以我不确定这是否是下一个列表元素的实际值,或者其他什么。

因此,如果有人可以帮助澄清如何_SINGLE_LIST_ENTRY.Next在 64 位系统上计算元素,我将不胜感激。

谢谢

4

1 回答 1

1

SLIST_HEADER 记录在 WDK 中:

typedef union DECLSPEC_ALIGN(16) _SLIST_HEADER {
    struct {  // original struct
        ULONGLONG Alignment;
        ULONGLONG Region;
    } DUMMYSTRUCTNAME;
    struct {  // 8-byte header
        ULONGLONG Depth:16;
        ULONGLONG Sequence:9;
        ULONGLONG NextEntry:39;
        ULONGLONG HeaderType:1; // 0: 8-byte; 1: 16-byte
        ULONGLONG Init:1;       // 0: uninitialized; 1: initialized
        ULONGLONG Reserved:59;
        ULONGLONG Region:3;
    } Header8;
    struct {  // ia64 16-byte header
        ULONGLONG Depth:16;
        ULONGLONG Sequence:48;
        ULONGLONG HeaderType:1; // 0: 8-byte; 1: 16-byte
        ULONGLONG Init:1;       // 0: uninitialized; 1: initialized
        ULONGLONG Reserved:2;
        ULONGLONG NextEntry:60; // last 4 bits are always 0's
    } Header16;
    struct {  // x64 16-byte header
        ULONGLONG Depth:16;
        ULONGLONG Sequence:48;
        ULONGLONG HeaderType:1; // 0: 8-byte; 1: 16-byte
        ULONGLONG Reserved:3;
        ULONGLONG NextEntry:60; // last 4 bits are always 0's
    } HeaderX64;
} SLIST_HEADER, *PSLIST_HEADER;

所以你想要HeaderX64。此外,结构中的 NextEntry 地址只有 60 位,根据注释,最后四位始终为零。所以,这是我系统中的一个例子(稍微清理一下):

1: kd> dt nt!_SLIST_HEADER 0xfffff80001862800 HeaderX64.
   +0x000 HeaderX64  : 
      +0x000 Depth      : (0x2)
      +0x000 Sequence   : (0x58)
      +0x008 HeaderType : 0x1
      +0x008 Reserved   : 0x0
      +0x008 NextEntry  : (0xfffffa80038556b)

在末尾添加一个归零的半字节:

1: kd> !pool 0xfffffa80038556b0 2
Pool page fffffa80038556b0 region is Nonpaged pool
*fffffa80038556a0 size:  130 previous size:   80  (Allocated) *Irp 
        Pooltag Irp  : Io, IRP packets
于 2013-12-04T19:46:28.127 回答