当前位置 博文首页 > KOOKNUT的博客:浅谈MDL(叁)--实例测试(Windows内核学习笔记)
在我之前写SSDTHook时候,用到过MDL的相关知识,是对内核层的虚拟地址进行MDL映射,然后修改,实现SSDTHook。
原文链接:
https://blog.csdn.net/qq_42253797/article/details/104352520
接下来看一下MDL的实现过程:
首先调用MmCreateMdl函数,对KeServiceDescriptorTable->ServiceTableBase所在地址,以系统服务函数的长度为界限,进行创建MDL。我们看到Windbg中的参数,StartVA是进行过页面对齐的大小:0x84883000,源虚拟地址为:0x8488343c,这个数据在下图有所体现。ByteOffset的值为0x43c,这印证了我们之前说过的,StartVA+ByteOffset为源虚拟地址。
接下来构建一个非分页内存MmBuildMdlForNonPagedPool,免于被置换处物理内存,修改MDL属性,截至目前,所得到的MappedSystemVa都是不算数的。
接下来使用MmMapLockedPages映射非分页内存页面,返回映射之后的地址,返回值和MappedSystemVa都指向映射之后的虚拟地址。
对原本ServiceTable服务函数表的地址进行查看,和现在映射出来的地址里面的值是相同的。
0: kd> dd 0x8488343c
8488343c 84a7efbf 848c6855 84a0ed47 8482a897
8488344c 84a80895 84903112 84af10d7 84af1120
8488345c 84a03563 84b0a9d4 84b0bc2d 849f9d3b
8488346c 84a8aed3 84ae3da3 84a36cc7 84a068ab
8488347c 8499c9e3 84ad5c88 849ed28c 84a2fcbc
8488348c 84a7c191 849dd300 84a7b59e 849fadb2
8488349c 84a8c95a 849fd435 84a8c73a 84a84e92
848834ac 84a0f2cf 84ad0a25 84a8225f 84a8cb8c
0: kd> dd 0xaebac43c
aebac43c 84a7efbf 848c6855 84a0ed47 8482a897
aebac44c 84a80895 84903112 84af10d7 84af1120
aebac45c 84a03563 84b0a9d4 84b0bc2d 849f9d3b
aebac46c 84a8aed3 84ae3da3 84a36cc7 84a068ab
aebac47c 8499c9e3 84ad5c88 849ed28c 84a2fcbc
aebac48c 84a7c191 849dd300 84a7b59e 849fadb2
aebac49c 84a8c95a 849fd435 84a8c73a 84a84e92
aebac4ac 84a0f2cf 84ad0a25 84a8225f 84a8cb8c
看一下我们的挂钩函数偏移111h的地址是啥
//因为Windbg指令后面的数字是显示多少个数据,16机制数,所以我输入112h,因为数组下标为111h的数据,应该是第112h个
0: kd> dd 0xaebac43c l 112
aebac43c 84a7efbf 848c6855 84a0ed47 8482a897
aebac44c 84a80895 84903112 84af10d7 84af1120
aebac45c 84a03563 84b0a9d4 84b0bc2d 849f9d3b
...................................
aebac86c 84a5c673 84a01e50 849fe00d 84846308
aebac87c 849dd16b 84a68007
//进行验证果然
0: kd> u 84a68007
nt!NtReadFile:
84a68007 6a4c push 4Ch
84a68009 68f8a38584 push offset nt! ?? ::FNODOBFM::`string'+0x2258 (8485a3f8)
84a6800e e82dc2e1ff call nt!_SEH_prolog4 (84884240)
84a68013 33f6 xor esi,esi
84a68015 8975dc mov dword ptr [ebp-24h],esi
84a68018 8975d0 mov dword ptr [ebp-30h],esi
84a6801b 8975ac mov dword ptr [ebp-54h],esi
84a6801e 8975b0 mov dword ptr [ebp-50h],esi
执行挂钩,修改MDL虚拟地址中的值之后,用源SSDT表的起始地址验证,发现发生了改变:
0: kd> dd 8488343c l 112
8488343c 84a7efbf 848c6855 84a0ed47 8482a897
8488344c 84a80895 84903112 84af10d7 84af1120
...................
8488386c 84a5c673 84a01e50 849fe00d 84846308
8488387c 849dd16b 9e1bc100
0: kd> u 9e1bc100
SSDTHook!FakeNtReadFile [z:\ring0层代码\[3]钩子集合\ssdthook\ssdthook\ssdthook.c @ 126]:
9e1bc100 55 push ebp
9e1bc101 8bec mov ebp,esp
9e1bc103 6afe push 0FFFFFFFEh
9e1bc105 6820d31b9e push offset SSDTHook!__safe_se_handler_table+0x1a0 (9e1bd320)
9e1bc10a 6880c51b9e push offset SSDTHook!_except_handler4 (9e1bc580)
9e1bc10f 64a100000000 mov eax,dword ptr fs:[00000000h]
9e1bc115 50 push eax
9e1bc116 81c4d4fdffff add esp,0FFFFFDD4h
证明,MDL确实修改的物理页面的东西,并且两个不同的内核虚拟地址映射到了同一个物理内存地址上。
第二种,是Ring3的地址,在Ring0中进行映射,这里的MDL->Process就不会再是0x00000000了。我们也之前有这个例子,在内存修改器中:
https://blog.csdn.net/qq_42253797/article/details/105399092
来看一下调试信息:
这是自己写的两个Ring3层的代码,简单的测试一下数据拷贝,但是通过Ring0实现拷贝。
Windbg查看进程EPROCESS:
PROCESS 89b1b250 SessionId: 1 Cid: 0f44 Peb: 7ffd4000 ParentCid: 09c4
DirBase: be9b45a0 ObjectTable: a891fd60 HandleCount: 6.
Image: SourceProcess.exe
PROCESS 8967d030 SessionId: 1 Cid: 0f74 Peb: 7ffdb000 ParentCid: 09c4
DirBase: be9b4640 ObjectTable: a88d0438 HandleCount: 6.
Image: TargetProcess.exe
驱动代码中传的参数数据:
MmInitializeMdl代码执行完毕之后,看到被初始化的部分
MmProbeAndLockPages之后:
MmMapLockedPagesSpecifyCache之后:得到映射地址
映射之后的返回地址,就用这个地址进行拷贝
2: kd> db 0xabd3aca0
abd3aca0 48 00 65 00 6c 00 6c 00-6f 00 57 00 6f 00 72 00 H.e.l.l.o.W.o.r.
abd3acb0 6c 00 64 00 00 00 00 00-00 00 00 00 00 00 00 00 l.d.............
//拷贝之后的Ring3虚拟地址
2: kd> db 0x000a9430
000a9430 48 00 65 00 6c 00 6c 00-6f 00 57 00 6f 00 72 00 H.e.l.l.o.W.o.r.
000a9440 6c 00 64 00 00 00 00 00-00 00 00 00 00 00 00 00 l.d.............
先对MDL的总结告一段落,之后学习过程中,如果有什么新的发现,会再回来补充以及修正。
“It takes courage to believe.”