`
wodamazi
  • 浏览: 1417510 次
文章分类
社区版块
存档分类
最新评论

读书笔记_windows下的混合钩子(HOOK)_part 4_使用MDL修改内存保护机制

 
阅读更多

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
MmCreateMdl(
INPMDL
MemoryDescriptorListOPTIONAL,
INPVOID
Base,
INSIZE_T
Length
);

新的函数为

PMDL
IoAllocateMdl(
__in_optPVOID
VirtualAddress,
__inULONG
Length,
__inBOOLEAN
SecondaryBuffer,
__inBOOLEAN
ChargeQuota,
__inout_optPIRP
IrpOPTIONAL
);

IoAllocateMdl的作用是分配一个MDL结构,也就是将系统的一段内存空间映射到另外一个地方,然后修改这部分内存的保护属性,并修改其内容,以达到修改受保护内存的目的。第一参数为MDL内存的起始地址,第二个参数为MDL的长度。

由于IoAllocateMdl创建的MDL都是指向非分页的虚拟内存的buffer中的,所以需要MmBuildMdlForNonPagedPool函数来在物理内存上更新这个MDL。

MmMapLocakedPages函数的定义如下

PVOID
MmMapLockedPages(
INPMDL
MemoryDescriptorList,
INKPROCESSOR_MODE
AccessMode
);

新的函数为MmMapLockedPagesSpecifyCache,它的定义为

PVOID
MmMapLockedPagesSpecifyCache(
__inPMDLX
MemoryDescriptorList,
__inKPROCESSOR_MODE
AccessMode,
__inMEMORY_CACHING_TYPE
CacheType,
__in_optPVOID
BaseAddress,
__inULONG
BugCheckOnFailure,
__inMM_PAGE_PRIORITY
Priority
);

它的作用是用来锁定内存中的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);

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics