/*
遍历vad二叉树来遍历进程里的模块
*/
#include <ntifs.h>
typedef struct _MMADDRESS_NODE
{
ULONG64 u1;
struct _MMADDRESS_NODE* LeftChild;
struct _MMADDRESS_NODE* RightChild;
ULONG64 StartingVpn;
ULONG64 EndingVpn;
}MMADDRESS_NODE, *PMMADDRESS_NODE;
typedef struct _EX_FAST_REF
{
union
{
PVOID Object;
ULONG_PTR RefCnt : 3;
ULONG_PTR Value;
};
} EX_FAST_REF, *PEX_FAST_REF;
struct _SEGMENT
{
struct _CONTROL_AREA* ControlArea;
ULONG TotalNumberOfPtes;
ULONG SegmentFlags;
ULONG64 NumberOfCommittedPages;
ULONG64 SizeOfSegment;
union
{
struct _MMEXTEND_INFO* ExtendInfo;
void* BasedAddress;
};
ULONG64 SegmentLock;
ULONG64 u1;
ULONG64 u2;
struct _MMPTE* PrototypePte;
ULONGLONG ThePtes[0x1];
};
//控制区
struct _CONTROL_AREA
{
struct _SEGMENT* Segment;
struct _LIST_ENTRY DereferenceList;
unsigned __int64 NumberOfSectionReferences;
unsigned __int64 NumberOfPfnReferences;
unsigned __int64 NumberOfMappedViews;
unsigned __int64 NumberOfUserReferences;
ULONG u;
ULONG FlushInProgressCount;
struct _EX_FAST_REF FilePointer;
/*ULONG ControlAreaLock;
ULONG ModifiedWriteCount;
ULONG StartingFrame;
ULONG64 WaitingForDeletion;
ULONG64 u2; //0x10字节
ULONG64 LockedPages;
_LIST_ENTRY ViewList;*/
};
struct _SUBSECTION
{
struct _CONTROL_AREA* ControlArea;
struct _MMPTE* SubsectionBase;
struct _SUBSECTION* NextSubsection;
ULONG PtesInSubsection;
ULONG UnusedPtes;
struct _MM_AVL_TABLE* GlobalPerSessionHead;
ULONG u;
ULONG StartingSector;
ULONG NumberOfFullSectors;
};
typedef struct _MMVAD
{
ULONG64 u1;
struct _MMVAD* LeftChild;
struct _MMVAD* RightChild;
ULONG64 StartingVpn;
ULONG64 EndingVpn;
ULONG64 u;
ULONG64 PushLock;
ULONG64 u5;
ULONG64 u2;
struct _SUBSECTION* Subsection;
struct _MSUBSECTION* MappedSubsection;
struct _MMPTE* FirstPrototypePte;
struct _MMPTE* LastContiguousPte;
struct _LIST_ENTRY ViewLinks;
struct _EPROCESS* VadsProcess;
}MMVAD;
typedef struct tag_MM_AVL_TABLE
{
struct _MMADDRESS_NODE BalancedRoot;
ULONG64 DepthOfTree;
ULONG64 Unused;
ULONG64 NumberGenericTableElements;
void* NodeHint;
void* NodeFreeHint;
}MM_AVL_TABLE, *PMMAVL_TABLE;
long TotalNum = 0;
VOID EnumVad(MMVAD* Root)
{
POBJECT_NAME_INFORMATION Str = (POBJECT_NAME_INFORMATION)ExAllocatePool(PagedPool, 500);
ULONG RetLen = 0;//接收
//DbgBreakPoint();
//申请内存失败或者节点为null都退出
if (!Str || !Root)
return;
RtlZeroMemory(Str, 500);
//KdPrint(("-> %p\n", Root->Subsection->ControlArea->FilePointer.Value));
__try
{
if (MmIsAddressValid(Root->Subsection) &&
MmIsAddressValid(Root->Subsection->ControlArea) &&
MmIsAddressValid((PVOID)Root->Subsection->ControlArea->FilePointer.Value)
)
{
//清除低4位就是FILE_OBJECT
PFILE_OBJECT pFileObj = (PFILE_OBJECT)((Root->Subsection->ControlArea->FilePointer.Value >> 4) << 4);
if (MmIsAddressValid(pFileObj))
{
//获取模块名称
NTSTATUS Status = ObQueryNameString(pFileObj, Str, 500, &RetLen);
if (NT_SUCCESS(Status))
{
//KdPrint(("基址:%p 大小:%p ",
// Root->Subsection->ControlArea->Segment->BasedAddress,
// Root->Subsection->ControlArea->Segment->SizeOfSegment));
KdPrint(("模块:%ws\n\n", Str->Name.Buffer));
TotalNum++;
}
else
{
KdPrint(("获取模块名称失败 %08X\n", Status));
}
}
}
}
__except (1)
{
//KdPrint(("地址无效!\n"));
}
ExFreePool(Str);
__try
{
if (MmIsAddressValid(Root->LeftChild))
EnumVad(Root->LeftChild);
if (MmIsAddressValid(Root->RightChild))
EnumVad(Root->RightChild);
}
__except (1)
{
KdPrint(("异常!!"));
return;
}
}
BOOLEAN EnumProcessModule(ULONG Pid)
{
PEPROCESS Peprocess = 0;
if (NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)Pid, &Peprocess)))
{
//挂靠到目标进程
KeAttachProcess(Peprocess);
PMMAVL_TABLE Table = (PMMAVL_TABLE)((UCHAR*)Peprocess + 0x448);
KdPrint(("%p", Table->BalancedRoot.RightChild));
if (Table->BalancedRoot.LeftChild)
EnumVad((MMVAD*)Table->BalancedRoot.LeftChild);
if (Table->BalancedRoot.RightChild)
EnumVad((MMVAD*)Table->BalancedRoot.RightChild);
//解除挂靠
KeDetachProcess();
KdPrint(("总模块数量为%ld", TotalNum));
}
else
{
KdPrint(("PsLookupProcessByProcessId failed"));
return FALSE;
}
return TRUE;
}