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 ffffe28fbb0860c0
    SessionId: 1  Cid: 11a8    Peb: 0035c000  ParentCid: 11c8
    DirBase: 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 0x668

VOID 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 * 0x1000
            pBuffer->VadInfos[pBuffer->nCnt].startVpn = (startptr | Root->Core.StartingVpn) << PAGE_SHIFT;

            // 结束页: EndVpn * 0x1000 + 0xfff
            pBuffer->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得到进程EProcess
    if (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 * 0x1000
                pBuffer->VadInfos[pBuffer->nCnt].startVpn = (startptr | Root->Core.StartingVpn) << PAGE_SHIFT;

                // 结束页: EndVpn * 0x1000 + 0xfff
                pBuffer->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);

        // 枚举VAD
        EnumProcessVad(vad.nPid, vad.pBuffer, nCount);


        // 输出VAD
        for (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;
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络工程师沦为IT行业里的“二等公民”了?

大家好&#xff0c;我是老杨。 都说网工难&#xff0c;都说网工苦&#xff0c;都说网工行业已经不行了、网工成为最底层、“二等公民”&#xff0c;已经彻底没落了…… 这些在互联网里持续不断散发出来的负能量&#xff0c;有没有让你在深夜耍手机的时候一次又一次的扎心过&a…

提升工作效率,打造精细思维——OmniOutliner 5 Pro for Mac

在当今快节奏的工作环境中&#xff0c;如何高效地组织和管理我们的思维和任务成为了关键。而OmniOutliner 5 Pro for Mac正是为此而生的一款强大工具。无论你是专业写作者、项目经理还是学生&#xff0c;OmniOutliner 5 Pro for Mac都能帮助你提升工作效率&#xff0c;打造精细…

shopify motion主题如何更换视频

有很多做跨境电商的朋友&#xff0c;为了吸引用户在网站停留更多时间&#xff0c;往往会选择将自己的网站做的天花乱坠&#xff0c;视频、GIF等各式夺目的的元素搭配在网站首页。但是后期想要更换视频的时候&#xff0c;如果没有相关经验的小白不知道如何更换视频&#xff0c;或…

处理BOP数据集,将其和COCO数据集结合

处理BOP数据集&#xff0c;将其和COCO数据集结合 BOP 取消映射关系&#xff0c;并自增80 取消文件名的images前缀 import os import json from tqdm import tqdm import argparseparser argparse.ArgumentParser() parser.add_argument(--json_path, defaultH:/Dataset/COCO…

【LeetCode:2342. 数位和相等数对的最大和 | HashMap + 模拟 】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

[黑马程序员SpringBoot2]——开发实用篇1

目录&#xff1a; 手工启动热部署自动启动热部署热部署范围配置关闭热部署功能第三方bean属性绑定松散绑定常用计量单位应用bean属性校验进制数据转换规则加载测试专用属性加载测试专用配置测试类中启动web环境发送虚拟请求匹配响应执行状态匹配响应体匹配响应体(json)匹配响应…

快速搜索多个word、excel等文件中内容

如何快速搜索多个word、excel等文件中内容 操作方法 以win11系统为介绍对象。 首先我们打开“我的电脑”-->“文件夹选项”-->“搜索”标签页,在“搜索内容”下方选择&#xff1a;"始终搜索文件名和内容&#xff08;此过程可能需要几分钟&#xff09;"。然后…

杭州-区块链前瞻性论坛邀请函​

2023密码与安全前瞻性论坛邀请函 生成合法节点或非法节点&#xff0c;测试共识协议

Bulk RNA-seq上下游分析

Bulk-RNA-seq上下游分析还是相对简单的&#xff0c;这次我以mouse为例&#xff0c;进行Bulk-RNA-seq上下游分析&#xff0c;并进行对应的图片绘制。 上游分析 1.软件准备 #安装所需软件 sudo apt install fastqc sudo apt install hisat2 sudo apt install cutadapt sudo ap…

Vue3 动态设置 ref

介绍 在一些场景&#xff0c;ref设置是未知的需要根据动态数据来决定&#xff0c;如表格中的input框需要我们主动聚焦&#xff0c;就需要给每一个input设置一个ref&#xff0c;进而进行聚焦操作。 Demo 点击下面截图中的编辑按钮&#xff0c;自动聚焦到相应的输入框中。 &…

python3-- Pillow10 ‘FreeTypeFont‘ object has no attribute ‘getsize‘报错解决

文章目录 一、问题二. 解决方法&#xff1a;1.方法12.方法2 三. 总结 一、问题 使用pillow10进行图片文字合成时获取文字大小失败 AttributeError: FreeTypeFont object has no attribute getsize二. 解决方法&#xff1a; 1.方法1 降级Pillow pip install Pillow9.5.0再去…

手把手教你搭建Maven私服

Java全能学习面试指南&#xff1a;https://javaxiaobear.cn 1. Maven私服简介 ①私服简介 Maven 私服是一种特殊的Maven远程仓库&#xff0c;它是架设在局域网内的仓库服务&#xff0c;用来代理位于外部的远程仓库&#xff08;中央仓库、其他远程公共仓库&#xff09;。 当然…

数组两种初始化方法

1.数组的静态初始化 静态初始化即在初始化数组时即规定了数组的大小以及数组中每个元素的值 有三种静态初始化的方法&#xff1a; 以初始化一个int类型的数组为例&#xff1a; 1.数组类型[] 数组名 new 数组类型[]{元素1,元素2...元素n}; int[] a new int[]{1,3,5}; 2.数…

qt library创建和使用

1、创建library 2、修改library中的代码 3、把library进行编译&#xff0c;编译后会生成相关文件 4、把编译后的文件拷贝到主程序目录下面。 5、并把library中的testlib头文件拷贝到主程序&#xff0c;并在pro文件加入&#xff08;这里在后面使用library中函数有关&#xff0…

elasticsearch 概述

初识elasticsearch 了解ES elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 例如&#xff1a; 在GitHub搜索代码 在电商网站搜索商品 ELK技术栈 elasticsearc…

会员管理系统编程教学编程工具下载

会员管理系统编程教学编程工具下载 给大家分享一款中文编程工具&#xff0c;零基础轻松学编程&#xff0c;不需英语基础&#xff0c;编程工具可下载。 这款工具不但可以连接部分硬件&#xff0c;而且可以开发大型的软件&#xff0c;象如图这个实例就是用这个工具开发的。 它的…

Guitar Pro2024吉他软件好不好用?

吉他&#xff0c;这把魔幻的弹奏利器&#xff0c;既需要技术&#xff0c;又需要技巧。 是的&#xff0c;它不会自己跳入你的手中&#xff0c;除非你敲对了密码&#xff1a;练习&#xff01; 今天就来看看&#xff0c;大家是不是已经找到了快速掌握吉他的门道呢&#xff1f; …

Spring Cloud学习(九)【Elasticsearch 分布式搜索引擎01】

文章目录 初识 elasticsearch了解 ES倒排索引ES 的一些概念安装es、kibana安装elasticsearch部署kibana 分词器安装IK分词器ik分词器-拓展词库 索引库操作mapping 映射属性索引库的 CRUD 文档操作添加文档查看、删除文档修改文档Dynamic Mapping RestClient 操作索引库什么是Re…

Android手机投屏神器scrcpy

scrcpy 下装/安装 scrcpy 用于电脑控制 Android 设备的命令行工具 官方下载地址&#xff1a;https://github.com/Genymobile/scrcpy/releases 非官方下载地址 https://download.csdn.net/download/weixin_43335288/88505202 下载后直接解压&#xff08;免安装&#xff09; 连…

JSON.toJSONString/JSONObject.toJSONString将实体类对象转换成JSON字符串时,多出了params字符串[记录贴]

我这里是给与了实体类一些固定的默认值&#xff0c;转换莫名其妙多出了params参数&#xff0c;回头深挖一下 **光看代码了 被偷了后方&#xff0c;忘记继承了还 ** 将实体类转换成JSON格式&#xff0c;三种写法都是一样的&#xff0c;内核都是阿里巴巴的 System.out.println(…