当前位置: 首页 > news >正文

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;
}

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

相关文章:

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

在上一篇文章《内核中实现Dump进程转储》中我们实现了ARK工具的转存功能&#xff0c;本篇文章继续以内存为出发点介绍VAD结构&#xff0c;该结构的全程是Virtual Address Descriptor即虚拟地址描述符&#xff0c;VAD是一个AVL自平衡二叉树&#xff0c;树的每一个节点代表一段虚…...

基于世界杯算法优化概率神经网络PNN的分类预测 - 附代码

基于世界杯算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于世界杯算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于世界杯优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…...

NPM 与 XUI 共存!Nginx Proxy Manager 搭配 X-UI 实现 Vless+WS+TLS 教程!

之前分享过搭建可以与宝塔共存的一个 “魔法” 服务器状态监控应用 ——xui&#xff0c;支持 VmessWSTLS。 最近 Docker 视频出的比较多&#xff0c;前阵子又出现了宝塔国内版存在隐私泄露的问题&#xff0c;很多小伙伴其实都不用宝塔了&#xff0c;那么&#xff0c;在我们现在…...

【网络奇遇记】那年我与计算机网络的浅相知

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. 计算机网络的定义1.1 计算机早期的一个最简单的定义1.2 现阶段计算机网络的一个较好的定义 二. …...

LeetCode26.删除有序数组中的重复项(双指针法)

LeetCode26.删除有序数组中的重复项 1.问题描述2.解题思路3.代码 1.问题描述 给你一个 非严格递增排列 的数组 nums &#xff0c;请你** 原地** 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然…...

原型网络Prototypical Network的python代码逐行解释,新手小白也可学会!!-----系列8

文章目录 前言一、原始代码二、对每一行代码的解释&#xff1a;总结 前言 这是该系列原型网络的最后一段代码及其详细解释&#xff0c;感谢各位的阅读&#xff01; 一、原始代码 if __name__ __main__:##载入数据labels_trainData, labels_testData load_data() # labels_…...

黑马点评回顾 redis实现共享session

文章目录 传统session缺点整体访问流程代码实现生成验证码登录 问题具体思路 传统session缺点 传统单体项目一般是把session存入tomcat&#xff0c;但是每个tomcat中都有一份属于自己的session,假设用户第一次访问第一台tomcat&#xff0c;并且把自己的信息存放到第一台服务器…...

Redis篇---第八篇

系列文章目录 文章目录 系列文章目录前言一、说说 Redis 哈希槽的概念?二、Redis 常见性能问题和解决方案有哪些?三、假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以某个固定的已知的前缀开头的,如果将它们全部找出来?前言 前些天发现了一个巨牛的人工智能学习网站…...

Unity使用Visual Studio Code 调试

Unity 使用Visual Studio Code 调试C# PackageManager安装Visual Studio EditorVisual Studio Code安装Unity 插件修改Unity配置调试 PackageManager安装Visual Studio Editor 打开 Window->PackageManger卸载 Visual Studio Code Editor &#xff0c;这个已经被官方废弃安…...

【Linux】进程替换|exec系列函数

文章目录 一、看一看单进程版的进程替换二、进程替换的原理三、多进程版——验证各种程序替换接口exec系列函数execlexeclpexecvexecvp tipsexecleexecve 四、总结 一、看一看单进程版的进程替换 #include<stdio.h> #include<unistd.h> #include<stdlib.h>i…...

Java编程技巧:将图片导出成pdf文件

目录 一、pom依赖二、代码三、测试链接 一、pom依赖 <!-- pdf插件 start --> <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.3</version> </dependency> <dependency…...

二项分布和泊松分布

一、二项分布 1.1 n重伯努利试验 若是二项分布&#xff0c;则必是n重伯努利试验概型。即&#xff1a;每次试验只有两种结果 与 &#xff0c;且在每次试验中A发生的概率相等&#xff0c;即P(A)p&#xff0c;将这种试验独立重复n次&#xff0c;则称这种试验为n重伯努利试验&#…...

【飞控调试】DJIF450机架+Pixhawk6c mini+v1.13.3固件+好盈Platinium 40A电调无人机调试

1 背景 由于使用了一种新的航电设备组合&#xff0c;在调试无人机起飞的时候遇到了之前没有遇到的问题。之前用的飞控&#xff08;Pixhawk 6c&#xff09;和电调&#xff08;Hobbywing X-Rotor 40A&#xff09;&#xff0c;在QGC里按默认参数配置来基本就能平稳飞行&#xff0…...

Android studio配置Flutter开发环境报错问题解决

博主前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住也分享一下给大家 &#x1f449;点击跳转到教程 报错问题截图 报错原因已经给出&#xff1a; You need Java 11 or higher to build your app with this version of G…...

2023.11.18 -自用hadoop高可用环境搭建命令

启动hadoop高可用环境 # 1.先恢复快照到高可用环境 # 2.三台服务器启动zookeeper服务 [rootnode1 ~]# zkServer.sh start [rootnode2 ~]# zkServer.sh start [rootnode3 ~]# zkServer.sh start 查看服务状态: [rootnode]# zkServer.sh status 关闭zk服务的命令是: [rootnode]# …...

【Linux】常用系统工作命令

一、Linux文档目录结构 在Linux系统中&#xff0c;目录、字符设备、套接字、硬盘、光驱、打印机等都被抽象成文件形式&#xff0c;“Linux系统中一切都是文件”。Linux系统中的一切文件都是从"根"目录&#xff08;/&#xff09;开始的&#xff0c;并按照文件系统层次…...

深入理解网络协议:通信世界的基石

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在当今数字化时代&#xff0c;网络协议是连接世…...

PL/SQL编程

一、Oracle常用函数 concat&#xff1a;用于连接两个字符串。 CONCAT(Oraok, .com) -- Result: Oraok.com ceil&#xff1a;小数点向上取整。 secect ceil(7.3) from dual --Result: 8 dual表是oracle系统为计算设计的一张临时表 select sysdate as 系统日期 from dual…...

Prompt提示词——什么是CRISPE框架?QCIPSPE框架?

框架介绍 【CRISPE】框架 是由 Matt Nigh 提出并发布的提示词书写框架&#xff0c;共由五部分组成。 这个框架&#xff08;CRISPE&#xff09;主要包括五个部分&#xff0c;用于指导用户向ChatGPT提问。首先&#xff0c;通过设定ChatGPT的角色&#xff08;Capacity and Role&…...

Nginx的核心配置文件

Nginx的核心配置文件 学习Nginx首先需要对它的核心配置文件有一定的认识&#xff0c;这个文件位于Nginx的安装目录/usr/local/nginx/conf目录下&#xff0c;名字为nginx.conf 详细配置&#xff0c;可以参考resources目录下的<<nginx配置中文详解.conf>> Nginx的核…...

Java,集合框架,关于Collection接口(子接口List和Set)

目录 数组储存多个数据方面的特点&#xff1a; Java集合框架体系&#xff1a;&#xff08;Java.util包下&#xff09; Collection接口中的方法测试&#xff1a; 迭代器&#xff08;Iterator&#xff09;的作用&#xff1a;用来遍历集合元素。 增强for循环&#xff08;即for…...

已安装的nginx追加ssl模块

Nginx开启SSL模块1 切换到源码包&#xff1a; cd /usr/local/src/nginx-1.11.3 2 查看nginx原有的模块 /usr/local/nginx/sbin/nginx -V 在configure arguments:后面显示的原有的configure参数如下&#xff1a; –prefix/usr/local/nginx --with-http_stub_status_module …...

大语言模型|人工智能领域中备受关注的技术

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️其他领域】 文章目录 前言关于大语言模型大语言模型是什么&#xff1f;大语言模型有什么用?文案写作知识库回答文本分类代码生成 AWS 如何通过 LLM 提供帮助&#xff1f;Amazon BedrockAmazon SageM…...

Docker之DockerFile解析

DockerFile解析 是什么 Dockerfile是用来构建Docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚本。 概述 官网 https://docs.docker.com/engine/reference/builder/ 构建三步骤 编写Dockerfile文件 docker build命令构建镜像 docker run依镜像运…...

NSSCTF第13页(2)

[HNCTF 2022 Week1]Challenge__rce 提示?hint 访问看到了源码 <?php error_reporting(0); if (isset($_GET[hint])) { highlight_file(__FILE__); } if (isset($_POST[rce])) { $rce $_POST[rce]; if (strlen($rce) < 120) { if (is_string($rce…...

基于吉萨金字塔建造算法优化概率神经网络PNN的分类预测 - 附代码

基于吉萨金字塔建造算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于吉萨金字塔建造算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于吉萨金字塔建造优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&a…...

Git详解及 github使用

1.1 关于版本控制 开始之前先看一个没有版本控制的例子 1.1.1 本地版本控制 本地版本控制系统 许多人习惯用复制整个项目目录的方式来保存不同的版本&#xff0c;或许还会改名加上备份时间以示区别。这么做唯一的 好处就是简单&#xff0c;但是特别容易犯错。有时候会混淆所在…...

iOS源码-工程目录讲解

1、 工程目录 1.1、xib 主要的界面渲染控制&#xff0c;ios开发常用的界面&#xff0c;可以在这里快速开发出来 1.2、base 基本的类&#xff0c;子类继承base类&#xff0c;就具备父类的方法&#xff0c;无需在重写 1.3、util 基础的类一些&#xff0c;处理时间等 1.4、…...

ESP32 Arduino实战协议篇-搭建独立的 Web 服务器

在此项目中,您将创建一个带有 ESP32 的独立 Web 服务器,该服务器使用 Arduino IDE 编程环境控制输出(两个 LED)。Web 服务器是移动响应的,可以使用本地网络上的任何浏览器设备进行访问。我们将向您展示如何创建 Web 服务器以及代码如何逐步工作。 项目概况 在直接进入项目…...

多维时序 | MATLAB实现PSO-BiLSTM-Attention粒子群优化双向长短期记忆神经网络融合注意力机制的多变量时间序列预测

多维时序 | MATLAB实现PSO-BiLSTM-Attention粒子群优化双向长短期记忆神经网络融合注意力机制的多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-BiLSTM-Attention粒子群优化双向长短期记忆神经网络融合注意力机制的多变量时间序列预测预测效果基本介绍模型描述程序设计参考…...

【开源】基于Vue.js的在线课程教学系统的设计和实现

项目编号&#xff1a; S 014 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S014&#xff0c;文末获取源码。} 项目编号&#xff1a;S014&#xff0c;文末获取源码。 目录 一、摘要1.1 系统介绍1.2 项目录屏 二、研究内容2.1 课程类型管理模块2.2 课程管理模块2…...

CentOS 安装etcd集群 —— 筑梦之路

环境说明 192.168.1.11 192.168.1.12 192.168.1.13 yum在线安装 yum install etcd -y #etcd01 cat > /etc/etcd/etcd.conf <<EOF ETCD_NAMEetcd01 ETCD_LISTEN_PEER_URLS"http://0.0.0.0:2380" ETCD_LISTEN_CLIENT_URLS"http://0.0.0.0:2379&quo…...

mysql 实现去重

个人网站 首发于公众号小肖学数据分析 1、试题描述 数据表user_test如下&#xff0c;请你查询所有投递用户user_id并且进行去重展示&#xff0c;查询结果和返回顺序如下 查询结果和返回顺序如下所示 解题思路&#xff1a; (1) 对user_id列直接去重&#xff1a; &#xff…...

类模板成员函数类外实现

#include<iostream> #include<string> using namespace std;//类模板成员函数类外实现 template<class T1,class T2> class Person { public:Person(T1 name,T2 age); // { // this->m_namename; // this->m_ageage; // }void showPerson(); // { /…...

多svn仓库一键更新脚本分享

之前分享过多git仓库一键更新脚本&#xff0c;本期就分享下svn仓库的一键更新脚本 1、首先需要设置svn为可执行命令行 打开SVN安装程序&#xff0c;选择modify&#xff0c;然后点击 command client tools&#xff0c;安装命令行工具 2、update脚本 echo 开始更新SVN目录&…...

C语言程序设计(入门)

考虑到期末临近&#xff0c;大一的学生该考c语言程序设计了吧&#xff0c;整一小篇给爱摆烂的小萌新复习一下降低挂科的风险 1. 1.1 main 函数 int main() {// 程序的入口&#xff0c;执行从这里开始return 0; // 表示程序正常结束 }1.2 语句和分号 C语言中的语句以分号结束…...

短视频账号矩阵系统源码

短视频账号矩阵系统源码搭建步骤包括以下几个方面&#xff1a; 1. 确定账号类型和目标受众&#xff1a;确定要运营的短视频账号类型&#xff0c;如搞笑、美食、美妆等&#xff0c;并明确目标受众和定位。 2. 准备账号资料&#xff1a;准备相关资质和资料&#xff0c;如营业执照…...

基于SSM的在线投稿系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…...

PWM实验

PWM相关概念 PWM:脉冲宽度调制定时器 脉冲&#xff1a;方波信号&#xff0c;高低电平变化产生方波 周期&#xff1a;高低电平变化所需要时间 频率&#xff1a;1s钟可以产生方波个数 占空比&#xff1a;在一个方波内&#xff0c;高电平占用的百分比 宽度调制&#xff1a;占…...

Python武器库开发-flask篇之session与cookie(二十六)

flask篇之session与cookie(二十六) 在 Flask 中&#xff0c;可以使用 session 来在不同请求之间存储和传递数据。Session 在客户端和服务器端之间交换&#xff0c;但是数据存储在服务器端。 Session 与 Cookie 的区别 session 和 cookie 都可以用来在不同请求之间存储和传递…...

深度学习YOLO安检管制物品识别与检测 - python opencv 计算机竞赛

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络4 Yolov55 模型训练6 实现效果7 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习YOLO安检管制误判识别与检测 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&…...

vite+react+typescript 遇到的问题

1.找不到模块“vite”。你的意思是要将 “moduleResolution” 选项设置为 “node”&#xff0c;还是要将别名添加到 “paths” 选项中 tsconfig.json 中 compilerOptions:{“moduleResolution”: node} 2.未知的编译器选项“allowImportingTsExtensions” 该选项用于控制是否…...

数据结构及八种常用数据结构简介

data-structure 数据结构是一种存在某种关系的元素的集合。“数据” 是指元素&#xff1b;“结构” 是指元素之间存在的关系&#xff0c;分为 “逻辑结构” 和 “物理结构&#xff08;又称存储结构&#xff09;”。 常用的数据结构有 数组&#xff08;array&#xff09;、栈&…...

阿里云配置ssl(Apache)

阿里云申请证书&#xff0c;有个专门的免费的申请方式与普通证书是平级的功能&#xff1b; 访问服务器&#xff0c;判断apache是不是开启ssl功能&#xff0c;如果没有安装就安装它 [rootcentos ~]# rpm -qa | grep mod_ssl //什么没显示说明没装 yum install mod_ssl openssl …...

阿里云linux升级新版本npm、nodejs

在阿里云服务器上编译部署NextJS工程发现 alibaba linux默认yum install npm安装的版本太低, 使用以下方式升级node、npm新版本。 1、卸载现有版本 yum remove nodejs npm -y2、安装新版本 sudo yum install https://rpm.nodesource.com/pub_21.x/nodistro/repo/nodesource-…...

如何在el-tree懒加载并且包含下级的情况下进行数据回显-02

上一篇文章如何在el-tree懒加载并且包含下级的情况下进行数据回显-01对于el-tree懒加载&#xff0c;包含下级的情况下&#xff0c;对于回显提出两种方案&#xff0c;第一种方案有一些难题无法解决&#xff0c;我们重点来说说第二种方案。 第二种方案是使用这个变量对其是否全选…...

Pytorch 网络冻结的三种方法区别:detach、requires_grad、with_no_grad

1、requires_grad requires_gradTrue # 要求计算梯度&#xff1b; requires_gradFalse # 不要求计算梯度&#xff1b;在pytorch中&#xff0c;tensor有一个 requires_grad参数&#xff0c;如果设置为True&#xff0c;那么它会追踪对于该张量的所有操作。在完成计算时可以通过调…...

如何定位el-tree中的树节点当父元素滚动时如何定位子元素

使用到的方法 Element 接口的 scrollIntoView() 方法会滚动元素的父容器&#xff0c;使被调用 scrollIntoView() 的元素对用户可见。 参数 alignToTop可选 一个布尔值&#xff1a; 如果为 true&#xff0c;元素的顶端将和其所在滚动区的可视区域的顶端对齐。相应的 scrollIntoV…...

【WiFI问题自助】解决WiFi能连上但是没有网的问题

WiFi能连上但是没有网的问题 背景&#xff1a;wifi能连上&#xff0c;但是没有网 解决 遇事不决&#xff0c;先重启啊&#xff01;怎么重启&#xff1f;拔掉电源再插上&#xff01;拔掉网线再插上&#xff01; 直接ok了。 思考记录 今天WiFi又上不了网了&#xff0c;昨天报…...

论文阅读:JINA EMBEDDINGS: A Novel Set of High-Performance Sentence Embedding Models

Abstract JINA EMBEDINGS构成了一组高性能的句子嵌入模型&#xff0c;擅长将文本输入转换为数字表示&#xff0c;捕捉文本的语义。这些模型在密集检索和语义文本相似性等应用中表现出色。文章详细介绍了JINA EMBEDINGS的开发&#xff0c;从创建高质量的成对&#xff08;pairwi…...