VAD概念
简介
VAD其实没有过于复杂,由于本人总是忘记,遂写个记录方便以后查询.
内存分为物理内存和虚拟内存;操作系统和进程共享物理内存,进程独享虚拟内存;物理内存可以通过CR3
寄存器在进程之间互相隔离,确保进程之间互不侵犯;2位下,每个进程独享4GB
内存,怎么知道哪些内存已经使用过,windwos
采用virtual address descripot
自平衡二叉树来管理虚拟内存,低端的内存地址放在根节点左子树,高端内存地址放根节点右子树,大致的结构如下:每当进程调用virtualAlloc
分配虚拟内存时,操作系统会先遍历这个树,看看还有哪些地方的虚拟内存还未使用
64位环境下查找VAD
在EPROCESS
结构中保存着VadRoot
根节点
1 2 3 4 5 6 7 8 9 10 11 12 13
| kd> dt _EPROCESS nt!_EPROCESS +0x000 Pcb : _KPROCESS +0x160 ProcessLock : _EX_PUSH_LOCK +0x168 CreateTime : _LARGE_INTEGER [...] +0x448 VadRoot : _MM_AVL_TABLE +0x488 AlpcContext : _ALPC_PROCESS_CONTEXT +0x4a8 TimerResolutionLink : _LIST_ENTRY +0x4b8 RequestedTimerResolution : Uint4B +0x4bc ActiveThreadsHighWatermark : Uint4B +0x4c0 SmallestTimerResolution : Uint4B +0x4c8 TimerResolutionStackRecord : Ptr64 _PO_DIAG_STACK_RECORD
|
64位VAD
结构如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 1: kd> dt _MMVAD nt!_MMVAD +0x000 u1 : <unnamed-tag> +0x008 LeftChild : Ptr64 _MMVAD +0x010 RightChild : Ptr64 _MMVAD +0x018 StartingVpn : Uint8B +0x020 EndingVpn : Uint8B +0x028 u : <unnamed-tag> +0x030 PushLock : _EX_PUSH_LOCK +0x038 u5 : <unnamed-tag> +0x040 u2 : <unnamed-tag> +0x048 Subsection : Ptr64 _SUBSECTION +0x048 MappedSubsection : Ptr64 _MSUBSECTION +0x050 FirstPrototypePte : Ptr64 _MMPTE +0x058 LastContiguousPte : Ptr64 _MMPTE +0x060 ViewLinks : _LIST_ENTRY +0x070 VadsProcess : Ptr64 _EPROCESS
|
!process 0 0
查看EPROCESS
地址
1 2 3 4 5 6 7
| 1: kd> !process 0 0 **** NT ACTIVE PROCESS DUMP **** [...] PROCESS fffffa8004ae1b30 SessionId: 1 Cid: 0c60 Peb: 7fffffd3000 ParentCid: 062c DirBase: 4716c000 ObjectTable: fffff8a0027e1bf0 HandleCount: 70. Image: calc.exe
|
查看VAD
管理各块内存属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 1: kd> !vad fffffa8004ae1b30+0x440 VAD level start end commit c3504c4102210000: Unable to get nt!_FILE_OBJECT.FileName.Buffer [...] fffffa8004971d90 ( 9) 190 199 10 Private READWRITE fffffa800492d140 ( 7) 1a0 1af 16 Private READWRITE fffffa800461f0c0 ( 8) 1b0 1cc 29 Private READWRITE fffffa8004b54250 ( 9) 1d0 1ec 29 Private READWRITE fffffa8004865950 ( 4) 1f0 26f 9 Private READWRITE fffffa80041a4870 ( 8) 270 2a8 57 Private READWRITE fffffa8004568f70 ( 7) 2b0 2e8 57 Private READWRITE fffffa80041a5140 ( 6) 2f0 2f9 10 Private READWRITE fffffa80038a0b60 ( 8) 300 312 19 Private READWRITE fffffa8004b65580 ( 9) 320 329 10 Private READWRITE fffffa800455ded0 ( 7) 330 42f 105 Private READWRITE fffffa8004b50750 ( 8) 430 52f 46 Private READWRITE fffffa80044bc350 ( 5) 530 6b7 0 Mapped READONLY Pagefile-backed section fffffa8004436bd0 ( 8) 6c0 840 0 Mapped READONLY Pagefile-backed section
|
接下来就可以递归遍历二叉树得到VAD树了
当内存使用完毕,调用VirtualFree
,将内存从VAD
卸下,后续再次遍历时才能继续使用!正常情况下,如果要卸载dll,可以调用windwos
提供的freeLibrary
接口(释放后再使用,躲避检测),里面有关键的函数:ZwUnmapViewOfSection
,可以直接把dll对应的内存从VAD中删除,ZwUnmapViewOfSection
是傀儡执行恶意的代码的关键函数(一般傀儡进程或者直接注入的shellcode都是Private
(调用VirtualAlloc
)权限,并且具有EXECUTE
属性,可以使用此方法检测傀儡进程)