Windows x64(Intrusive)单链表

时间:2013-11-15 14:34:29

标签: windows linked-list reverse-engineering windbg intrusive-containers

我目前正试图围绕一些Windows旁边列表,我看到一些令我困惑的内存地址。

根据我发布的另一个问题,由于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    
...

Next的{​​{1}}值似乎不是有效的虚拟地址,我也尝试对其执行虚拟到物理转换,但失败了。

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

列表标题中有其他数据,0x0000000001bf0003结构,位于_SLIST_HEADER之前。它包含以下数据:

_SINGLE_LIST_ENTRY

在初始头是一系列三个联合之后,由于这是一个64位系统,我相信应该使用Alignment: 0x1bf0003 Region: 0xfffffa8001df5b01 联合,其中包含:{/ p>

Header16

Depth: 0x3 Sequence: 0x1bf HeaderType: 0x1 Init: 0x0 Reserved: 0x0 NextEntry: 0xfffffa8001df5b0 元素确实包含一个有效的虚拟地址,因此我不确定这是否是下一个列表元素的实际值,或其他内容。

因此,如果有人可以帮助澄清如何在64位系统上计算Header16.NextEntry元素,我将非常感激。

谢谢

1 个答案:

答案 0 :(得分:1)

WDK中记录了SLIST_HEADER:

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