MDL(Memory Descriptor List),指内存描述符表,它包含了该内存区域的起始地址、拥有者进程、字节数量以及标志。MDL结构定义在ntddk.h中,具体结构如下:
Typedef struct _MDL{
Struct _MDL *Next;
CSHORT Size;
CSHORT MdlFlags;
Struct _EPROCESS *Process;
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
为了修改内存标志,需要声明一个结构,该结构用于强制转换由Windows内核导出的KeServiceDescriptorTable变量的类型。该结构如下:
typedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; //Used only in checked build unsigned int NumberOfServices; unsigned char *ParamTableBase; } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; |
《Rootkits》书中给的源码如下所示,尽管去能够在windows XP下编译过,并且能够执行,但其中的有些函数已经过时,已有新的函数替代了。下面分别描述:
g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4); if(!g_pmdlSystemCall) return STATUS_UNSUCCESSFUL; MmBuildMdlForNonPagedPool(g_pmdlSystemCall); // Change the flags of the MDL g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); |
MmCreateMdl函数的定义如下
PMDL |
新的函数为
PMDL |
IoAllocateMdl的作用是分配一个MDL结构,也就是将系统的一段内存空间映射到另外一个地方,然后修改这部分内存的保护属性,并修改其内容,以达到修改受保护内存的目的。第一参数为MDL内存的起始地址,第二个参数为MDL的长度。
由于IoAllocateMdl创建的MDL都是指向非分页的虚拟内存的buffer中的,所以需要MmBuildMdlForNonPagedPool函数来在物理内存上更新这个MDL。
MmMapLocakedPages函数的定义如下
PVOID |
新的函数为MmMapLockedPagesSpecifyCache,它的定义为
PVOID |
它的作用是用来锁定内存中的MDL页,允许用户修改其属性。
所以使用新函数后修改的代码如下:
//g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, //KeServiceDescriptorTable.NumberOfServices*4); g_pmdlSystemCall = IoAllocateMdl(KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4,FALSE, FALSE, NULL ); if(!g_pmdlSystemCall) return STATUS_UNSUCCESSFUL; MmBuildMdlForNonPagedPool(g_pmdlSystemCall); // Change the flags of the MDL // MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); MappedSystemCallTable = MmMapLockedPagesSpecifyCache(g_pmdlSystemCall, KernelMode, MmWriteCombined, NULL, FALSE, 0); MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); |