1

我目前正试图围绕一些Windows旁视列表进行封装,并且我看到一些内存地址让我感到困惑。Windows x64(侵入)单链表

从另一个问题我贴出来,一些代码所产生,这要归功于sergmatoriginal question):

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  
... 

这样看来, 0x0000000001bf0003Next值不是一个有效的虚拟地址,我也尝试在其上执行虚拟到物理的转换,失败。

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

列表标题中有其他数据,_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元素确实包含有效的虚拟地址,所以我不确定这是否是下一个列表元素的实际值,或其他。

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

感谢

回答

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