看流星社区

 找回密码
 注册账号
查看: 1808|回复: 0

【驱动笔记14】初步认识MDL

[复制链接]

该用户从未签到

发表于 2017-6-1 17:25:43 | 显示全部楼层 |阅读模式
前段时间在群里有人问起什么是MDL,当时三言两语也不知道解释清楚了没,今天闲着无事,索性记录下来吧,就当是做个笔记,以后忘了也好查阅。

我们知道,系统中一些重要的表项如SSDT是只读的,如果我们强行对其进行修改就会造成BSOD的严重后果。当然这种保护方式很容易被绕过,我们曾经介绍了通过修改cr0来禁用WP(WriteProtect,写保护)位的方法,现在再介绍一种不需要使用汇编的方法,就是MDL。

MDL的全称是Memory DescriptorList,即内存描述符表。我们可以通过MDL描述一块内存区域,在MDL中包含了该内存区域的起始地址、拥有者进程、字节数量、标记等信息,如下所示:
typedef struct _MDL
{
struct_MDL *Next;
CSHORTSize;
CSHORTMdlFlags;
struct_EPROCESS *Process;
PVOIDMappedSystemVa;
PVOIDStartVa;
ULONGByteCount;
ULONG ByteOffset;
} MDL, *PMDL;

我们先来看一段在SSDT HOOK中常见的代码,如下所示:
PMDL MDSystemCall;
PVOID *MappedSCT;

MDSystemCall = MmCreateMdl(NULL,KeServiceDescriptorTable.ServiceTableBase,KeServiceDescriptorTable.NumberOfServices*4);
if(!MDSystemCall)
{
returnSTATUS_UNSUCCESSFUL;
}
MmBuildMdlForNonPagedPool(MDSystemCall);
MDSystemCall->MdlFlags |=MDL_MAPPED_TO_SYSTEM_VA;
MappedSCT = MmMapLockedPages(MDSystemCall, KernelMode);
HookOn( ZwTerminateProcess, New_ZwTerminateProcess);

其中KeServiceDescriptorTable描述的是SSDT,其中ServiceTableBase标明了SSDT的起始地址,因此我们通过MmCreateMdl函数创建一个MDL,它刚好把SSDT这块内存包含在内,有人可能会问,它的长度为啥是“KeServiceDescriptorTable.NumberOfServices*4”字节呢?很简单,因为指针的长度是4个字节。

后面的代码首先从不分页的内存池中BuildMDL,然后添加一个MDL_MAPPED_TO_SYSTEM_VA标记以便允许写入该内存区域;然后我们将这块内存锁起来,现在可以就开始HOOKSSDT了,直到关闭HOOK后才将其释放。从这里就可以看出,这种方式明显没有修改cr0的方法好,呵呵呵呵。

不过这种方法的应用范围比较广,控制精度也较好,精确地指定了要修改哪一块内存的标记,两者方法算是各有千秋吧,谁喜欢用哪一种都可以
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-19 18:40

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表