驱动开发:内核遍历进程VAD结构体

在上一篇文章《驱动开发:内核中实现Dump进程转储》中我们实现了ARK工具的转存功能,本篇文章继续以内存为出发点介绍VAD结构,该结构的全程是Virtual Address Descriptor虚拟地址描述符,VAD是一个AVL平衡二叉树,树的每一个节点代表一段虚拟地址空间 。程序中的代码段,数据段,堆段都会各种占用一个或多个VAD节点,由一个MMVAD结构完整描述 。
VAD结构的遍历效果如下:

驱动开发:内核遍历进程VAD结构体

文章插图
那么这个结构在哪?每一个进程都有自己单独的VAD结构树,这个结构通常在EPROCESS结构里面里面,在内核调试模式下使用dt _EPROCESS可得到如下信息 。
lyshark.com 1: kd> dt _EPROCESSntdll!_EPROCESS+0x500 Vm: _MMSUPPORT_FULL+0x640 MmProcessLinks: _LIST_ENTRY+0x650 ModifiedPageCount : Uint4B+0x654 ExitStatus: Int4B+0x658 VadRoot: _RTL_AVL_TREE+0x660 VadHint: Ptr64 Void+0x668 VadCount: Uint8B+0x670 VadPhysicalPages : Uint8B+0x678 VadPhysicalPagesLimit : Uint8B可以看到在本系统中VAD的偏移是+0x658紧跟其后的还有vadCount的计数等 。
【驱动开发:内核遍历进程VAD结构体】
驱动开发:内核遍历进程VAD结构体

文章插图
VAD结构是如何被添加的?通常情况下系统调用VirtualAllocate等申请一段堆内存时,则会在VAD树上增加一个结点_MMVAD结构体,需要说明的是栈并不受VAD的管理 。由系统直接分配空间,并把地址记录在了TEB中 。
lyshark.com 0: kd> dt _MMVADnt!_MMVAD+0x000 Core: _MMVAD_SHORT+0x040 u2: <anonymous-tag>+0x048 Subsection: Ptr64 _SUBSECTION+0x050 FirstPrototypePte : Ptr64 _MMPTE+0x058 LastContiguousPte : Ptr64 _MMPTE+0x060 ViewLinks: _LIST_ENTRY+0x070 VadsProcess: Ptr64 _EPROCESS+0x078 u4: <anonymous-tag>+0x080 FileObject: Ptr64 _FILE_OBJECT结构体MMVAD则是每一个VAD内存块的属性,这个内存结构定义在WinDBG中可看到 。
驱动开发:内核遍历进程VAD结构体

文章插图
如上在EPROCESS结构中可以找到VAD结构的相对偏移+0x658以及进程VAD计数偏移+0x668,我们首先通过!process 0 0指令得到当前所有进程的EPROCESS结构,并选中进程 。
lyshark.com 0: kd> !process 0 0PROCESS ffffe28fbb0860c0SessionId: 1Cid: 11a8Peb: 0035c000ParentCid: 11c8DirBase: 309f3002ObjectTable: ffffac87ba3da580HandleCount: 145.Image: x64.exe此处的ffffe28fbb0860c0正是我们所需要的EPROCESS结构 。
驱动开发:内核遍历进程VAD结构体

文章插图
当需要得到该进程的VAD结构时,只需要使用!vad ffffe28fbb0860c0 + 0x658来显示该进程的VAD树 。
驱动开发:内核遍历进程VAD结构体

文章插图
至于获取VAD有多少条,则可以直接使用!vad ffffe28fbb0860c0 + 0x668来获取到 。
驱动开发:内核遍历进程VAD结构体

文章插图
既然手动可以遍历出来,那么自动化也并不难,首先定义头文件vad.h同样这是微软定义,如果想要的到最新的,自己下载WinDBG调试内核输入命令 。
#pragma once#include <ntifs.h>typedef struct _MM_GRAPHICS_VAD_FLAGS// 15 elements, 0x4 bytes (sizeof){ /*0x000*/ULONG32Lock : 1;// 0 BitPosition /*0x000*/ULONG32LockContended : 1;// 1 BitPosition /*0x000*/ULONG32DeleteInProgress : 1;// 2 BitPosition /*0x000*/ULONG32NoChange : 1;// 3 BitPosition /*0x000*/ULONG32VadType : 3;// 4 BitPosition /*0x000*/ULONG32Protection : 5;// 7 BitPosition /*0x000*/ULONG32PreferredNode : 6;// 12 BitPosition /*0x000*/ULONG32PageSize : 2;// 18 BitPosition /*0x000*/ULONG32PrivateMemoryAlwaysSet : 1; // 20 BitPosition /*0x000*/ULONG32WriteWatch : 1;// 21 BitPosition /*0x000*/ULONG32FixedLargePageSize : 1;// 22 BitPosition /*0x000*/ULONG32ZeroFillPagesOptional : 1;// 23 BitPosition /*0x000*/ULONG32GraphicsAlwaysSet : 1;// 24 BitPosition /*0x000*/ULONG32GraphicsUseCoherentBus : 1; // 25 BitPosition /*0x000*/ULONG32GraphicsPageProtection : 3; // 26 BitPosition}MM_GRAPHICS_VAD_FLAGS, *PMM_GRAPHICS_VAD_FLAGS;typedef struct _MM_PRIVATE_VAD_FLAGS// 15 elements, 0x4 bytes (sizeof){ /*0x000*/ULONG32Lock : 1;// 0 BitPosition /*0x000*/ULONG32LockContended : 1;// 1 BitPosition /*0x000*/ULONG32DeleteInProgress : 1;// 2 BitPosition /*0x000*/ULONG32NoChange : 1;// 3 BitPosition /*0x000*/ULONG32VadType : 3;// 4 BitPosition /*0x000*/ULONG32Protection : 5;// 7 BitPosition /*0x000*/ULONG32PreferredNode : 6;// 12 BitPosition /*0x000*/ULONG32PageSize : 2;// 18 BitPosition /*0x000*/ULONG32PrivateMemoryAlwaysSet : 1; // 20 BitPosition /*0x000*/ULONG32WriteWatch : 1;// 21 BitPosition /*0x000*/ULONG32FixedLargePageSize : 1;// 22 BitPosition /*0x000*/ULONG32ZeroFillPagesOptional : 1;// 23 BitPosition /*0x000*/ULONG32Graphics : 1;// 24 BitPosition /*0x000*/ULONG32Enclave : 1;// 25 BitPosition /*0x000*/ULONG32ShadowStack : 1;// 26 BitPosition}MM_PRIVATE_VAD_FLAGS, *PMM_PRIVATE_VAD_FLAGS;typedef struct _MMVAD_FLAGS// 9 elements, 0x4 bytes (sizeof){ /*0x000*/ULONG32Lock : 1;// 0 BitPosition /*0x000*/ULONG32LockContended : 1;// 1 BitPosition /*0x000*/ULONG32DeleteInProgress : 1; // 2 BitPosition /*0x000*/ULONG32NoChange : 1;// 3 BitPosition /*0x000*/ULONG32VadType : 3;// 4 BitPosition /*0x000*/ULONG32Protection : 5;// 7 BitPosition /*0x000*/ULONG32PreferredNode : 6;// 12 BitPosition /*0x000*/ULONG32PageSize : 2;// 18 BitPosition /*0x000*/ULONG32PrivateMemory : 1;// 20 BitPosition}MMVAD_FLAGS, *PMMVAD_FLAGS;typedef struct _MM_SHARED_VAD_FLAGS// 11 elements, 0x4 bytes (sizeof){ /*0x000*/ULONG32Lock : 1;// 0 BitPosition /*0x000*/ULONG32LockContended : 1;// 1 BitPosition /*0x000*/ULONG32DeleteInProgress : 1;// 2 BitPosition /*0x000*/ULONG32NoChange : 1;// 3 BitPosition /*0x000*/ULONG32VadType : 3;// 4 BitPosition /*0x000*/ULONG32Protection : 5;// 7 BitPosition /*0x000*/ULONG32PreferredNode : 6;// 12 BitPosition /*0x000*/ULONG32PageSize : 2;// 18 BitPosition /*0x000*/ULONG32PrivateMemoryAlwaysClear : 1; // 20 BitPosition /*0x000*/ULONG32PrivateFixup : 1;// 21 BitPosition /*0x000*/ULONG32HotPatchAllowed : 1;// 22 BitPosition}MM_SHARED_VAD_FLAGS, *PMM_SHARED_VAD_FLAGS;typedef struct _MMVAD_FLAGS2// 7 elements, 0x4 bytes (sizeof){ /*0x000*/ULONG32FileOffset : 24;// 0 BitPosition /*0x000*/ULONG32Large : 1;// 24 BitPosition /*0x000*/ULONG32TrimBehind : 1;// 25 BitPosition /*0x000*/ULONG32Inherit : 1;// 26 BitPosition /*0x000*/ULONG32NoValidationNeeded : 1; // 27 BitPosition /*0x000*/ULONG32PrivateDemandZero : 1;// 28 BitPosition /*0x000*/ULONG32Spare : 3;// 29 BitPosition}MMVAD_FLAGS2, *PMMVAD_FLAGS2;typedef struct _MMVAD_SHORT{ RTL_BALANCED_NODE VadNode; UINT32 StartingVpn;/*0x18*/ UINT32 EndingVpn;/*0x01C*/ UCHAR StartingVpnHigh; UCHAR EndingVpnHigh; UCHAR CommitChargeHigh; UCHAR SpareNT64VadUChar; INT32 ReferenceCount; EX_PUSH_LOCK PushLock;/*0x028*/ struct {union{ULONG_PTR flag;MM_PRIVATE_VAD_FLAGS PrivateVadFlags;/*0x030*/MMVAD_FLAGSVadFlags;MM_GRAPHICS_VAD_FLAGS GraphicsVadFlags;MM_SHARED_VAD_FLAGSSharedVadFlags;}Flags; }u1; PVOID EventList;/*0x038*/}MMVAD_SHORT, *PMMVAD_SHORT;typedef struct _MMADDRESS_NODE{ ULONG64 u1; struct _MMADDRESS_NODE* LeftChild; struct _MMADDRESS_NODE* RightChild; ULONG64 StartingVpn; ULONG64 EndingVpn;}MMADDRESS_NODE, *PMMADDRESS_NODE;typedef struct _MMEXTEND_INFO// 2 elements, 0x10 bytes (sizeof){ /*0x000*/UINT64CommittedSize; /*0x008*/ULONG32ReferenceCount; /*0x00C*/UINT8_PADDING0_[0x4];}MMEXTEND_INFO, *PMMEXTEND_INFO;struct _SEGMENT{ struct _CONTROL_AREA* ControlArea; ULONG TotalNumberOfPtes; ULONG SegmentFlags; ULONG64 NumberOfCommittedPages; ULONG64 SizeOfSegment; union {struct _MMEXTEND_INFO* ExtendInfo;void* BasedAddress; }u; ULONG64 SegmentLock; ULONG64 u1; ULONG64 u2; PVOID* PrototypePte; ULONGLONG ThePtes[0x1];};typedef struct _EX_FAST_REF{ union {PVOID Object;ULONG_PTR RefCnt : 3;ULONG_PTR Value; };} EX_FAST_REF, *PEX_FAST_REF;typedef struct _CONTROL_AREA// 17 elements, 0x80 bytes (sizeof){ /*0x000*/struct _SEGMENT* Segment; union// 2 elements, 0x10 bytes (sizeof) {/*0x008*/struct _LIST_ENTRY ListHead;// 2 elements, 0x10 bytes (sizeof)/*0x008*/VOID*AweContext; }; /*0x018*/UINT64NumberOfSectionReferences; /*0x020*/UINT64NumberOfPfnReferences; /*0x028*/UINT64NumberOfMappedViews; /*0x030*/UINT64NumberOfUserReferences; /*0x038*/ULONG32 u;// 2 elements, 0x4 bytes (sizeof) /*0x03C*/ULONG32 u1;// 2 elements, 0x4 bytes (sizeof) /*0x040*/struct _EX_FAST_REF FilePointer;// 3 elements, 0x8 bytes (sizeof) // 4 elements, 0x8 bytes (sizeof)}CONTROL_AREA, *PCONTROL_AREA;typedef struct _SUBSECTION_{ struct _CONTROL_AREA* ControlArea;}SUBSECTION, *PSUBSECTION;typedef struct _MMVAD{ MMVAD_SHORT Core; union/*0x040*/ {UINT32 LongFlags2;//现在用不到省略MMVAD_FLAGS2 VadFlags2; }u2; PSUBSECTION Subsection;/*0x048*/ PVOID FirstPrototypePte;/*0x050*/ PVOID LastContiguousPte;/*0x058*/ LIST_ENTRY ViewLinks;/*0x060*/ PEPROCESS VadsProcess;/*0x070*/ PVOID u4;/*0x078*/ PVOID FileObject;/*0x080*/}MMVAD, *PMMVAD;typedef struct _RTL_AVL_TREE// 1 elements, 0x8 bytes (sizeof){ /*0x000*/struct _RTL_BALANCED_NODE* Root;}RTL_AVL_TREE, *PRTL_AVL_TREE;typedef struct _VAD_INFO_{ ULONG_PTR pVad; ULONG_PTR startVpn; ULONG_PTR endVpn; ULONG_PTR pFileObject; ULONG_PTR flags;}VAD_INFO, *PVAD_INFO;typedef struct _ALL_VADS_{ ULONG nCnt; VAD_INFO VadInfos[1];}ALL_VADS, *PALL_VADS;typedef struct _MMSECTION_FLAGS// 27 elements, 0x4 bytes (sizeof){ /*0x000*/UINT32BeingDeleted : 1;// 0 BitPosition /*0x000*/UINT32BeingCreated : 1;// 1 BitPosition /*0x000*/UINT32BeingPurged : 1;// 2 BitPosition /*0x000*/UINT32NoModifiedWriting : 1;// 3 BitPosition /*0x000*/UINT32FailAllIo : 1;// 4 BitPosition /*0x000*/UINT32Image : 1;// 5 BitPosition /*0x000*/UINT32Based : 1;// 6 BitPosition /*0x000*/UINT32File : 1;// 7 BitPosition /*0x000*/UINT32AttemptingDelete : 1;// 8 BitPosition /*0x000*/UINT32PrefetchCreated : 1;// 9 BitPosition /*0x000*/UINT32PhysicalMemory : 1;// 10 BitPosition /*0x000*/UINT32ImageControlAreaOnRemovableMedia : 1; // 11 BitPosition /*0x000*/UINT32Reserve : 1;// 12 BitPosition /*0x000*/UINT32Commit : 1;// 13 BitPosition /*0x000*/UINT32NoChange : 1;// 14 BitPosition /*0x000*/UINT32WasPurged : 1;// 15 BitPosition /*0x000*/UINT32UserReference : 1;// 16 BitPosition /*0x000*/UINT32GlobalMemory : 1;// 17 BitPosition /*0x000*/UINT32DeleteOnClose : 1;// 18 BitPosition /*0x000*/UINT32FilePointerNull : 1;// 19 BitPosition /*0x000*/ULONG32PreferredNode : 6;// 20 BitPosition /*0x000*/UINT32GlobalOnlyPerSession : 1;// 26 BitPosition /*0x000*/UINT32UserWritable : 1;// 27 BitPosition /*0x000*/UINT32SystemVaAllocated : 1;// 28 BitPosition /*0x000*/UINT32PreferredFsCompressionBoundary : 1;// 29 BitPosition /*0x000*/UINT32UsingFileExtents : 1;// 30 BitPosition /*0x000*/UINT32PageSize64K : 1;// 31 BitPosition}MMSECTION_FLAGS, *PMMSECTION_FLAGS;typedef struct _SECTION// 9 elements, 0x40 bytes (sizeof){ /*0x000*/struct _RTL_BALANCED_NODE SectionNode;// 6 elements, 0x18 bytes (sizeof) /*0x018*/UINT64StartingVpn; /*0x020*/UINT64EndingVpn; /*0x028*/union {PCONTROL_AREAControlArea;PVOIDFileObject; }u1;// 4 elements, 0x8 bytes (sizeof) /*0x030*/UINT64SizeOfSection; /*0x038*/union {ULONG32 LongFlags;MMSECTION_FLAGS Flags; }u;// 2 elements, 0x4 bytes (sizeof) struct// 3 elements, 0x4 bytes (sizeof) {/*0x03C*/ULONG32InitialPageProtection : 12; // 0 BitPosition/*0x03C*/ULONG32SessionId : 19;// 12 BitPosition/*0x03C*/ULONG32NoValidationNeeded : 1;// 31 BitPosition };}SECTION, *PSECTION;

经验总结扩展阅读