草庐IT

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

LyShark 2023-04-15 原文

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

VAD结构的遍历效果如下:

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

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中。

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

程序运行后输出效果如下:

有关驱动开发:内核遍历进程VAD结构体的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  5. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  6. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  7. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  8. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  9. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  10. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

随机推荐