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

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

VAD结构的遍历效果如下:

VAD是Windows操作系统中用于管理进程虚拟地址空间的数据结构之一,全称为Virtual Address Descriptor,即虚拟地址描述符。VAD是一个基于AVL自平衡二叉树的数据结构,它用于维护一段连续的虚拟地址空间。每个VAD节点都描述了一段连续的虚拟地址空间,并包含了该空间的属性信息,如该空间是否可读、可写、可执行等等。

在Windows操作系统中,每个进程都有自己的虚拟地址空间,用于存储该进程的代码、数据和堆栈等信息。这个虚拟地址空间被分为许多段,每个段都由一个或多个VAD节点表示。这些VAD节点构成了一个树形结构,树的根节点表示整个虚拟地址空间,而每个节点表示一段连续的虚拟地址空间。

每个VAD节点都是由一个MMVAD结构体来表示,MMVAD结构体中包含了该节点的各种属性信息,如虚拟地址的起始地址、结束地址、访问权限、保护属性等等。此外,MMVAD结构体还包含了指向下一个和上一个VAD节点的指针,以及指向该节点子节点的指针。这些指针使得VAD节点可以组成一个树形结构,并且可以方便地进行遍历和访问。

总之,VAD结构是Windows操作系统中管理进程虚拟地址空间的重要数据结构之一,它通过构建一个树形结构来管理进程的虚拟地址空间,并提供了丰富的属性信息,使得操作系统可以对虚拟地址空间进行有效的管理和保护。

那么这个VAD结构体在哪里呢?

每一个进程都有自己单独的VAD结构树,这个结构通常在EPROCESS结构里面里面,在内核调试模式下使用dt _EPROCESS可得到如下信息。

EPROCESS 结构体是用于表示操作系统中的一个进程的数据结构,其中包含了许多与该进程相关的信息,包括了该进程的虚拟地址空间描述符树(VAD 结构树)。

在内核调试模式下,使用 dt _EPROCESS 命令可以显示出该结构体的定义和各个字段的信息。其中与 VAD 结构树相关的字段为 VadRootVadHint

  • VadRoot 字段:表示该进程的虚拟地址空间描述符树的根节点,类型为 PMMVAD_SHORT。
  • VadHint 字段:表示该进程上一次访问的虚拟地址空间描述符节点,类型为 PMMVAD.

VadRoot 字段指向一个 MM_AVL_TABLE 结构体,该结构体包含了一个平衡二叉树,用于存储该进程的虚拟地址空间描述符节点。每个节点都包含了一个虚拟地址空间的起始地址、结束地址,以及一些其他描述符信息,如该区域是否是可读、可写、可执行等。

VadHint 字段则指向该进程最近访问的虚拟地址空间描述符节点,这个字段可以被用来优化访问虚拟地址空间描述符树的性能。

lyshark.com 1: kd> dt _EPROCESS
ntdll!_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结构是如何被添加的?

通常情况下系统调用VirtualAllocate等申请一段堆内存时,则会在VAD树上增加一个结点_MMVAD结构体,需要说明的是栈并不受VAD的管理。由系统直接分配空间,并把地址记录在了TEB中。

在 Windows 操作系统中,申请堆内存时,系统调用 VirtualAllocHeapAlloc 等函数会向操作系统请求一段连续的虚拟地址空间,然后内核会分配一些物理内存页并映射到该虚拟地址空间上,从而完成了内存的分配和管理。

在这个过程中,内核会在当前进程的 VAD 树中创建一个新的 MMVAD 结构体,用于描述这个新分配的虚拟地址空间的起始地址、大小、保护属性等信息。同时,内核会将这个 MMVAD 结构体插入到当前进程的 VAD 树中,并通过平衡二叉树的方式来维护这个树的结构,使得树的查询和插入操作都能够以 O(log n) 的时间复杂度完成。

但需要注意的是,栈并不受 VAD 树的管理,因为栈空间的分配和管理是由系统直接实现的。每个线程都拥有自己的 TEB(Thread Environment Block)结构体,其中包含了该线程的栈空间的起始地址、大小等信息。系统在创建线程时,会为该线程分配一段物理内存页,并映射到该线程的栈空间中,然后将栈空间的起始地址记录在该线程的 TEB 中。因此,栈空间的分配和管理是由系统直接实现的,不需要通过 VAD 树来管理。

lyshark.com 0: kd> dt _MMVAD
nt!_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中可看到。

如上在EPROCESS结构中可以找到VAD结构的相对偏移+0x658以及进程VAD计数偏移+0x668,我们首先通过!process 0 0指令得到当前所有进程的EPROCESS结构,并选中进程。

lyshark.com 0: kd> !process 0 0
PROCESS ffffe28fbb0860c0SessionId: 1  Cid: 11a8    Peb: 0035c000  ParentCid: 11c8DirBase: 309f3002  ObjectTable: ffffac87ba3da580  HandleCount: 145.Image: x64.exe

此处的ffffe28fbb0860c0正是我们所需要的EPROCESS结构。

当需要得到该进程的VAD结构时,只需要使用!vad ffffe28fbb0860c0 + 0x658来显示该进程的VAD树。

至于获取VAD有多少条,则可以直接使用!vad ffffe28fbb0860c0 + 0x668来获取到。

既然手动可以遍历出来,那么自动化也并不难,首先定义头文件vad.h同样这是微软定义,如果想要的到最新的,自己下载WinDBG调试内核输入命令。

#pragma once
#include <ntifs.h>typedef struct _MM_GRAPHICS_VAD_FLAGS        // 15 elements, 0x4 bytes (sizeof) 
{/*0x000*/     ULONG32      Lock : 1;                   // 0 BitPosition                   /*0x000*/     ULONG32      LockContended : 1;          // 1 BitPosition                   /*0x000*/     ULONG32      DeleteInProgress : 1;       // 2 BitPosition                   /*0x000*/     ULONG32      NoChange : 1;               // 3 BitPosition                   /*0x000*/     ULONG32      VadType : 3;                // 4 BitPosition                   /*0x000*/     ULONG32      Protection : 5;             // 7 BitPosition                   /*0x000*/     ULONG32      PreferredNode : 6;          // 12 BitPosition                  /*0x000*/     ULONG32      PageSize : 2;               // 18 BitPosition                  /*0x000*/     ULONG32      PrivateMemoryAlwaysSet : 1; // 20 BitPosition                  /*0x000*/     ULONG32      WriteWatch : 1;             // 21 BitPosition                  /*0x000*/     ULONG32      FixedLargePageSize : 1;     // 22 BitPosition                  /*0x000*/     ULONG32      ZeroFillPagesOptional : 1;  // 23 BitPosition                  /*0x000*/     ULONG32      GraphicsAlwaysSet : 1;      // 24 BitPosition                  /*0x000*/     ULONG32      GraphicsUseCoherentBus : 1; // 25 BitPosition                  /*0x000*/     ULONG32      GraphicsPageProtection : 3; // 26 BitPosition                  
}MM_GRAPHICS_VAD_FLAGS, *PMM_GRAPHICS_VAD_FLAGS;
typedef struct _MM_PRIVATE_VAD_FLAGS         // 15 elements, 0x4 bytes (sizeof) 
{/*0x000*/     ULONG32      Lock : 1;                   // 0 BitPosition                   /*0x000*/     ULONG32      LockContended : 1;          // 1 BitPosition                   /*0x000*/     ULONG32      DeleteInProgress : 1;       // 2 BitPosition                   /*0x000*/     ULONG32      NoChange : 1;               // 3 BitPosition                   /*0x000*/     ULONG32      VadType : 3;                // 4 BitPosition                   /*0x000*/     ULONG32      Protection : 5;             // 7 BitPosition                   /*0x000*/     ULONG32      PreferredNode : 6;          // 12 BitPosition                  /*0x000*/     ULONG32      PageSize : 2;               // 18 BitPosition                  /*0x000*/     ULONG32      PrivateMemoryAlwaysSet : 1; // 20 BitPosition                  /*0x000*/     ULONG32      WriteWatch : 1;             // 21 BitPosition                  /*0x000*/     ULONG32      FixedLargePageSize : 1;     // 22 BitPosition                  /*0x000*/     ULONG32      ZeroFillPagesOptional : 1;  // 23 BitPosition                  /*0x000*/     ULONG32      Graphics : 1;               // 24 BitPosition                  /*0x000*/     ULONG32      Enclave : 1;                // 25 BitPosition                  /*0x000*/     ULONG32      ShadowStack : 1;            // 26 BitPosition                  
}MM_PRIVATE_VAD_FLAGS, *PMM_PRIVATE_VAD_FLAGS;typedef struct _MMVAD_FLAGS            // 9 elements, 0x4 bytes (sizeof) 
{/*0x000*/     ULONG32      Lock : 1;             // 0 BitPosition                  /*0x000*/     ULONG32      LockContended : 1;    // 1 BitPosition                  /*0x000*/     ULONG32      DeleteInProgress : 1; // 2 BitPosition                  /*0x000*/     ULONG32      NoChange : 1;         // 3 BitPosition                  /*0x000*/     ULONG32      VadType : 3;          // 4 BitPosition                  /*0x000*/     ULONG32      Protection : 5;       // 7 BitPosition                  /*0x000*/     ULONG32      PreferredNode : 6;    // 12 BitPosition                 /*0x000*/     ULONG32      PageSize : 2;         // 18 BitPosition                 /*0x000*/     ULONG32      PrivateMemory : 1;    // 20 BitPosition                 
}MMVAD_FLAGS, *PMMVAD_FLAGS;typedef struct _MM_SHARED_VAD_FLAGS            // 11 elements, 0x4 bytes (sizeof) 
{/*0x000*/     ULONG32      Lock : 1;                     // 0 BitPosition                   /*0x000*/     ULONG32      LockContended : 1;            // 1 BitPosition                   /*0x000*/     ULONG32      DeleteInProgress : 1;         // 2 BitPosition                   /*0x000*/     ULONG32      NoChange : 1;                 // 3 BitPosition                   /*0x000*/     ULONG32      VadType : 3;                  // 4 BitPosition                   /*0x000*/     ULONG32      Protection : 5;               // 7 BitPosition                   /*0x000*/     ULONG32      PreferredNode : 6;            // 12 BitPosition                  /*0x000*/     ULONG32      PageSize : 2;                 // 18 BitPosition                  /*0x000*/     ULONG32      PrivateMemoryAlwaysClear : 1; // 20 BitPosition                  /*0x000*/     ULONG32      PrivateFixup : 1;             // 21 BitPosition                  /*0x000*/     ULONG32      HotPatchAllowed : 1;          // 22 BitPosition                  
}MM_SHARED_VAD_FLAGS, *PMM_SHARED_VAD_FLAGS;typedef struct _MMVAD_FLAGS2             // 7 elements, 0x4 bytes (sizeof) 
{/*0x000*/     ULONG32      FileOffset : 24;        // 0 BitPosition                  /*0x000*/     ULONG32      Large : 1;              // 24 BitPosition                 /*0x000*/     ULONG32      TrimBehind : 1;         // 25 BitPosition                 /*0x000*/     ULONG32      Inherit : 1;            // 26 BitPosition                 /*0x000*/     ULONG32      NoValidationNeeded : 1; // 27 BitPosition                 /*0x000*/     ULONG32      PrivateDemandZero : 1;  // 28 BitPosition                 /*0x000*/     ULONG32      Spare : 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_FLAGS  VadFlags;MM_GRAPHICS_VAD_FLAGS GraphicsVadFlags;MM_SHARED_VAD_FLAGS   SharedVadFlags;}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*/     UINT64       CommittedSize;/*0x008*/     ULONG32      ReferenceCount;/*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*/     UINT64       NumberOfSectionReferences;/*0x020*/     UINT64       NumberOfPfnReferences;/*0x028*/     UINT64       NumberOfMappedViews;/*0x030*/     UINT64       NumberOfUserReferences;/*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*/     UINT32       BeingDeleted : 1;                     // 0 BitPosition                   /*0x000*/     UINT32       BeingCreated : 1;                     // 1 BitPosition                   /*0x000*/     UINT32       BeingPurged : 1;                      // 2 BitPosition                   /*0x000*/     UINT32       NoModifiedWriting : 1;                // 3 BitPosition                   /*0x000*/     UINT32       FailAllIo : 1;                        // 4 BitPosition                   /*0x000*/     UINT32       Image : 1;                            // 5 BitPosition                   /*0x000*/     UINT32       Based : 1;                            // 6 BitPosition                   /*0x000*/     UINT32       File : 1;                             // 7 BitPosition                   /*0x000*/     UINT32       AttemptingDelete : 1;                 // 8 BitPosition                   /*0x000*/     UINT32       PrefetchCreated : 1;                  // 9 BitPosition                   /*0x000*/     UINT32       PhysicalMemory : 1;                   // 10 BitPosition                  /*0x000*/     UINT32       ImageControlAreaOnRemovableMedia : 1; // 11 BitPosition                  /*0x000*/     UINT32       Reserve : 1;                          // 12 BitPosition                  /*0x000*/     UINT32       Commit : 1;                           // 13 BitPosition                  /*0x000*/     UINT32       NoChange : 1;                         // 14 BitPosition                  /*0x000*/     UINT32       WasPurged : 1;                        // 15 BitPosition                  /*0x000*/     UINT32       UserReference : 1;                    // 16 BitPosition                  /*0x000*/     UINT32       GlobalMemory : 1;                     // 17 BitPosition                  /*0x000*/     UINT32       DeleteOnClose : 1;                    // 18 BitPosition                  /*0x000*/     UINT32       FilePointerNull : 1;                  // 19 BitPosition                  /*0x000*/     ULONG32      PreferredNode : 6;                    // 20 BitPosition                  /*0x000*/     UINT32       GlobalOnlyPerSession : 1;             // 26 BitPosition                  /*0x000*/     UINT32       UserWritable : 1;                     // 27 BitPosition                  /*0x000*/     UINT32       SystemVaAllocated : 1;                // 28 BitPosition                  /*0x000*/     UINT32       PreferredFsCompressionBoundary : 1;   // 29 BitPosition                  /*0x000*/     UINT32       UsingFileExtents : 1;                 // 30 BitPosition                  /*0x000*/     UINT32       PageSize64K : 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*/     UINT64       StartingVpn;/*0x020*/     UINT64       EndingVpn;/*0x028*/     union {PCONTROL_AREA   ControlArea;PVOID   FileObject;}u1;                   // 4 elements, 0x8 bytes (sizeof)  /*0x030*/     UINT64       SizeOfSection;/*0x038*/     union {ULONG32 LongFlags;MMSECTION_FLAGS Flags;}u;                    // 2 elements, 0x4 bytes (sizeof)  struct                                       // 3 elements, 0x4 bytes (sizeof)  {/*0x03C*/         ULONG32      InitialPageProtection : 12; // 0 BitPosition                   /*0x03C*/         ULONG32      SessionId : 19;             // 12 BitPosition                  /*0x03C*/         ULONG32      NoValidationNeeded : 1;     // 31 BitPosition                  };
}SECTION, *PSECTION;

引入vad.h头文件,并写入如下代码,此处的eprocess_offset_VadRoot以及eprocess_offset_VadCount 则是上方得出的相对于EPROCESS结构的偏移值,每个系统都不一样,版本不同偏移值会不同。

#include "vad.h"
#include <ntifs.h>// 定义VAD相对于EProcess头部偏移值
#define eprocess_offset_VadRoot 0x658
#define eprocess_offset_VadCount 0x668VOID EnumVad(PMMVAD Root, PALL_VADS pBuffer, ULONG nCnt)
{if (!Root || !pBuffer || !nCnt){return;}__try{if (nCnt > pBuffer->nCnt){// 得到起始页与结束页ULONG64 endptr = (ULONG64)Root->Core.EndingVpnHigh;endptr = endptr << 32;ULONG64 startptr = (ULONG64)Root->Core.StartingVpnHigh;startptr = startptr << 32;// 得到根节点pBuffer->VadInfos[pBuffer->nCnt].pVad = (ULONG_PTR)Root;// 起始页: startingVpn * 0x1000pBuffer->VadInfos[pBuffer->nCnt].startVpn = (startptr | Root->Core.StartingVpn) << PAGE_SHIFT;// 结束页: EndVpn * 0x1000 + 0xfffpBuffer->VadInfos[pBuffer->nCnt].endVpn = ((endptr | Root->Core.EndingVpn) << PAGE_SHIFT) + 0xfff;// VAD标志 928 = Mapped    1049088 = Private   ....pBuffer->VadInfos[pBuffer->nCnt].flags = Root->Core.u1.Flags.flag;// 验证节点可读性if (MmIsAddressValid(Root->Subsection) && MmIsAddressValid(Root->Subsection->ControlArea)){if (MmIsAddressValid((PVOID)((Root->Subsection->ControlArea->FilePointer.Value >> 4) << 4))){pBuffer->VadInfos[pBuffer->nCnt].pFileObject = ((Root->Subsection->ControlArea->FilePointer.Value >> 4) << 4);}}pBuffer->nCnt++;}if (MmIsAddressValid(Root->Core.VadNode.Left)){// 递归枚举左子树EnumVad((PMMVAD)Root->Core.VadNode.Left, pBuffer, nCnt);}if (MmIsAddressValid(Root->Core.VadNode.Right)){// 递归枚举右子树EnumVad((PMMVAD)Root->Core.VadNode.Right, pBuffer, nCnt);}}__except (1){}
}BOOLEAN EnumProcessVad(ULONG Pid, PALL_VADS pBuffer, ULONG nCnt)
{PEPROCESS Peprocess = 0;PRTL_AVL_TREE Table = NULL;PMMVAD Root = NULL;// 通过进程PID得到进程EProcessif (NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)Pid, &Peprocess))){// 与偏移相加得到VAD头节点Table = (PRTL_AVL_TREE)((UCHAR*)Peprocess + eprocess_offset_VadRoot);if (!MmIsAddressValid(Table) || !eprocess_offset_VadRoot){return FALSE;}__try{// 取出头节点Root = (PMMVAD)Table->Root;if (nCnt > pBuffer->nCnt){// 得到起始页与结束页ULONG64 endptr = (ULONG64)Root->Core.EndingVpnHigh;endptr = endptr << 32;ULONG64 startptr = (ULONG64)Root->Core.StartingVpnHigh;startptr = startptr << 32;pBuffer->VadInfos[pBuffer->nCnt].pVad = (ULONG_PTR)Root;// 起始页: startingVpn * 0x1000pBuffer->VadInfos[pBuffer->nCnt].startVpn = (startptr | Root->Core.StartingVpn) << PAGE_SHIFT;// 结束页: EndVpn * 0x1000 + 0xfffpBuffer->VadInfos[pBuffer->nCnt].endVpn = (endptr | Root->Core.EndingVpn) << PAGE_SHIFT;pBuffer->VadInfos[pBuffer->nCnt].flags = Root->Core.u1.Flags.flag;if (MmIsAddressValid(Root->Subsection) && MmIsAddressValid(Root->Subsection->ControlArea)){if (MmIsAddressValid((PVOID)((Root->Subsection->ControlArea->FilePointer.Value >> 4) << 4))){pBuffer->VadInfos[pBuffer->nCnt].pFileObject = ((Root->Subsection->ControlArea->FilePointer.Value >> 4) << 4);}}pBuffer->nCnt++;}// 枚举左子树if (Table->Root->Left){EnumVad((MMVAD*)Table->Root->Left, pBuffer, nCnt);}// 枚举右子树if (Table->Root->Right){EnumVad((MMVAD*)Table->Root->Right, pBuffer, nCnt);}}__finally{ObDereferenceObject(Peprocess);}}else{return FALSE;}return TRUE;
}VOID UnDriver(PDRIVER_OBJECT driver)
{DbgPrint(("Uninstall Driver Is OK \n"));
}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{DbgPrint(("hello lyshark \n"));typedef struct{ULONG nPid;ULONG nSize;PALL_VADS pBuffer;}VADProcess;__try{VADProcess vad = { 0 };vad.nPid = 4520;// 默认有1000个线程vad.nSize = sizeof(VAD_INFO) * 0x5000 + sizeof(ULONG);// 分配临时空间vad.pBuffer = (PALL_VADS)ExAllocatePool(PagedPool, vad.nSize);// 根据传入长度得到枚举数量ULONG nCount = (vad.nSize - sizeof(ULONG)) / sizeof(VAD_INFO);// 枚举VADEnumProcessVad(vad.nPid, vad.pBuffer, nCount);// 输出VADfor (size_t i = 0; i < vad.pBuffer->nCnt; i++){DbgPrint("StartVPN = %p | ", vad.pBuffer->VadInfos[i].startVpn);DbgPrint("EndVPN = %p | ", vad.pBuffer->VadInfos[i].endVpn);DbgPrint("PVAD = %p | ", vad.pBuffer->VadInfos[i].pVad);DbgPrint("Flags = %d | ", vad.pBuffer->VadInfos[i].flags);DbgPrint("pFileObject = %p \n", vad.pBuffer->VadInfos[i].pFileObject);}}__except (1){}Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;
}

程序运行后输出效果如下图所示;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/153872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot中动态api如何设置

1.不需要编写controller 等mvc层&#xff0c;通过接口动态生成api。 这个问题&#xff0c;其实很好解决&#xff0c;以前编写接口&#xff0c;是要写controller&#xff0c;需要有 RestController RequestMapping("/test1") public class xxxController{ ApiOperat…

敏捷DevOps专家王立杰:端到端DevOps持续交付的5P法则 | IDCF

今天有一个流行的英文缩写词用来刻画这个风云变幻的时代&#xff1a;VUCA&#xff08;乌卡时代&#xff09;。四个英文字母分别表示动荡性&#xff08;Volatility&#xff09;、不确定性&#xff08;Uncertainty&#xff09;、复杂性&#xff08;Complexity&#xff09;和模糊性…

C编译流程

1.预处理 hello.c 经过预处理得到 hello.i gcc -E hello.c -o hello.i -E的含义&#xff1a;说明这是一个预处理操作 生成预处理文件(.i) 预处理阶段做了什么事&#xff1a; 1.1 头文件展开 我们发现 原先只有几行的hello.c变成了上千行的hello.i 实际上 预处理完成的是 将头…

Unity中Shader反射环境

文章目录 前言一、制作反射环境的两种办法法1&#xff1a;属性面板接收一个 Cubemap 作为反射环境法2&#xff1a;把环境烘焙成一张Cubemap 二、在Unity中实现把环境烘焙成一张Cubemap1、先创建一个反射探针&#xff08;可以直接创建&#xff0c;也可以空物体增加组件&#xff…

【Linux】:进程间通信和日志模拟

进程间通信 一.基本概念二.简单的通信-管道(匿名管道)1.建立通信信道2.通信接口 三.命名管道三.模拟命名管道通信&#xff08;加上日志&#xff09;1.完整代码2.基本使用 一.基本概念 是什么 两个或多个进程实现数据层面的交互。 因为进程独立性的存在&#xff0c;导致进程间…

广度优先算法(BFS)

广度优先算法&#xff08;Breadth-First Search&#xff09;是在图和树领域的搜索方法&#xff0c;其核心思想是从一个起始点开始&#xff0c;访问其所有的临近节点&#xff0c;然后再按照相同的方式访问这些临近节点的节点&#xff0c;这种访问方式类似涟漪泛起&#xff0c;一…

HINSTANCE是什么?

HINSTANCE 就是 HMODULE&#xff1a;

队列OJ--循环队列

目录 题目链接&#xff1a;622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09;​​​​​ 题解&#xff1a; ​编辑 代码实现&#xff1a; 完整代码&#xff1a; 题目链接&#xff1a;622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09;​​​​​ 题解&#x…

jenkins传参给robotframework

在做自动化的时候&#xff0c;需要使用jenkins传参给rf&#xff0c;rf根据传来的变量运行&#xff0c;在将变量传递给py脚本文件。特此记录。 一、配置jenkins 构建的命令使用如下格式即可&#xff08;注意空格&#xff09;&#xff1a; cd D:\xxx\test call pybot --variabl…

砖家测评:腾讯云标准型S5服务器和s6性能差异和租用价格

腾讯云服务器CVM标准型S5和S6有什么区别&#xff1f;都是标准型云服务器&#xff0c;标准型S5是次新一代云服务器规格&#xff0c;标准型S6是最新一代的云服务器&#xff0c;S6实例的CPU处理器主频性能要高于S5实例&#xff0c;同CPU内存配置下的标准型S6实例要比S5实例性能更好…

视频剪辑技巧:批量剪辑新篇章,AI智剪来领航

随着数字媒体的飞速发展&#xff0c;视频剪辑已经成为一项重要的工作。在繁忙的工作中&#xff0c;如何高效、准确地完成批量剪辑是一项具有挑战性的任务。近年来&#xff0c;AI智剪的出现为视频剪辑工作带来了新的解决方案&#xff0c;引领着批量剪辑的新篇章。在AI智剪的帮助…

为了摆脱 Android ,亚马逊开发基于Linux的操作系统

导读亚马逊一直在开发一种新的操作系统 —— 内部代号为 “Vega”&#xff0c;以便在 Fire TV、智能显示器和其他联网设备上取代 Android 系统。 亚马逊一直在开发一种新的操作系统 —— 内部代号为 “Vega”&#xff0c;以便在 Fire TV、智能显示器和其他联网设备上取代 Andr…

终于有人把数据资产入表知识地图总结出来了,轻松看懂

在当前数字化的浪潮下&#xff0c;数据已经成为劳动、土地、知识、技术以后的第五大生产要素&#xff0c;“数据就是资源”已成为共识。如今数据资产“入表”已成定局&#xff0c;数据资产化迫在眉睫。 2023年8月21日&#xff0c;财政部正式印发《企业数据资源相关会计处理暂行…

什么样的企业可以使用免费版的CRM?

市面上大部分的免费CRM不需要付费即可使用&#xff0c;但是对于使用人数和功能进行了部分限制。下面我们就来说说&#xff0c;免费CRM的适用对象是谁&#xff1f; 1、初创/小微企业 这种小微企业没有太多的资金&#xff0c;也没有复杂的客户管理需求&#xff0c;仅仅需要一款…

生产环境_移动目标轨迹压缩应用和算法处理-Douglas-Peucker轨迹压缩算法

场景&#xff1a; 我目前设计到的场景是&#xff1a;以路面上行驶的汽车为例&#xff0c;即在地图应用中&#xff0c;对GPS轨迹数据进行压缩&#xff0c;减少数据传输和存储开销&#xff0c;因为轨迹点太频繁了&#xff0c;占用空间太大&#xff0c;运行节点太慢了&#xff0c…

姿态估计 手势动作实时识别项目(基于mediapipe、keras进行实现)

姿态估计 手势动作实时识别项目(基于mediapipe、keras进行实现) 0、功能展示1、项目原理介绍2、数据集采集脚本3、将采集到的动作数据集利用mediapipe库检测手部关键点信息,转换成数据信息保存到本地4、训练一个效果一般的随机森林分类器5、使用Kreas训练一个效果好点的全连…

提高软件测试覆盖率的5个重点

软件测试覆盖率是软件测试中的一个重要指标&#xff0c;它有利于保障软件质量、提高软件可靠性和可维护性。软件测试覆盖率能够发现并修复代码缺陷&#xff0c;确保代码的正确性&#xff0c;提高软件的稳定性&#xff0c;降低成本和风险。 因此进一步提高软件测试覆盖率对于软件…

Oauth2认证及Spring Security Oauth2授权码模式

Oauth2认证 Oauth2简介 简介 第三方认证技术方案最主要是解决认证协议的通用标准问题&#xff0c;因为要实现跨系统认证&#xff0c;各系统之间要遵循一定的接口协议。 OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时&#xff0c;任何第三方都可以使…

ICCV 23丨3D-VisTA:用于 3D 视觉和文本对齐的预训练Transformer

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/abs/2308.04352 开源代码&#xff1a;http://3d-vista.github.io 摘要&#xff1a; 3D视觉语言标定&#xff08;3D-VL&#xff09;是一个新兴领域&#xff0c;旨在将…

centos7安装mysql8

打开Mysql下载页面 https://downloads.mysql.com/archives/community/ 选择版本号&#xff1a; centos选择Red Hat版本&#xff0c;复制地址 复制地址后&#xff0c;链接ssh&#xff0c;添加储存库 yum install 粘贴地址&#xff1b; yum install https://downloads.mysql…