创建共享内存
当应用层和驱动层通信的时候,可以通过共享内存的方式来实现。即在驱动层分配一块内存,并为这段内存指定一个应用层指针和内核层指针,来进行写入和读取数据。
程序
BOOLEAN CreatMappingAddress(PVOID* pMappingAddSys_Out, PVOID* pShareUserAdd_Out, SIZE_T iNumberOfBytes, PMDL* pShareMM_MDL_Out, ULONG ulTag)
{
//一块共享内存
PVOID pMappingAddSys = NULL;
PVOID pShareUserAdd = NULL;
pMappingAddSys = ExAllocatePoolWithTag(NonPagedPool, iNumberOfBytes, ulTag);
if (pMappingAddSys == NULL)
{
DbgPrint("ExAllocatePoolWithTag Fail!\n");
return FALSE;
}
RtlZeroMemory(pMappingAddSys, iNumberOfBytes);
PMDL pShareMM_MDL = IoAllocateMdl(pMappingAddSys, iNumberOfBytes, FALSE, FALSE, NULL); //映射到MDL表中
if (pShareMM_MDL == NULL)
{
DbgPrint("IoAllocateMdl Fail!\n");
ExFreePool(pMappingAddSys);
return FALSE;
}
MmBuildMdlForNonPagedPool(pShareMM_MDL); //初始化当前页面
try
{
MmProbeAndLockPages(pShareMM_MDL, KernelMode, IoWriteAccess); //在内存中锁定,并且指明对它的改写权力
}
except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint((" Exception during MmProbeAndLockPages"));
IoFreeMdl(pShareMM_MDL);
ExFreePool(pMappingAddSys);
return FALSE;
}
pShareUserAdd = MmMapLockedPagesSpecifyCache(pShareMM_MDL, UserMode, MmCached, NULL, FALSE, NormalPagePriority); //为当前物理页映射一个R3的指针
if (pShareUserAdd == NULL)
{
DbgPrint("MmMapLockedPagesSpecifyCache Fail!\n");
IoFreeMdl(pShareMM_MDL);
ExFreePool(pMappingAddSys);
return FALSE;
}
DbgPrint("pShareMM_SYS的地址为: 0x%p\n", (PUCHAR)pMappingAddSys);
DbgPrint("pShareMM_User的地址为: 0x%p\n", (PUCHAR)pShareUserAdd);
*pMappingAddSys_Out = pMappingAddSys;
*pShareUserAdd_Out = pShareUserAdd;
*pShareMM_MDL_Out = pShareMM_MDL;
return TRUE;
}
例
在这个例子里向 pMappingAddSys 写入数据后,将pShareUserAdd这个指针发送到用户层,在用户层就可以读取数据了。
BOOLEAN Test()
{
//创建一个共享内存用于保存数据让R3读取
PVOID pShareUserAdd = NULL;
PVOID pMappingAddSys = NULL;
if (!CreatMappingAddress(&pMappingAddSys, &pShareUserAdd, 1024, (ULONG)"TempAddress"))
{
DbgPrint("CreatMappingAddress Fail!\n");
return FALSE;
}
DbgPrint("pMappingAddSys = 0x%p \n", pMappingAddSys);
if (pMappingAddSys != NULL)
{
DbgPrint("pMappingAddSys != NULL \n");
//向pMappingAddSys写入数据
RtlZeroMemory(pMappingAddSys, 1024);
memcpy(pMappingAddSys, "12345678", sizeof("12345678"));
DbgPrint("pMappingAddSys = 0x%p, pMappingAddSysValue = %s \n", pMappingAddSys, (PCHAR)pMappingAddSys);
}
DbgPrint("End GetDriverModule\n");
return TRUE;
}
可以通过winDbg看一下 pShareUserAdd 和 pMappingAddSys的值:
pShareMM_SYS的地址为: 0x86AB1008 //R0
pShareMM_User的地址为: 0x005A0008 //R3
通过结果可以看出 pShareMM_SYS 为 0环的指针,地址位于高2G,pShareMM_User 为 3环的指针,地址位于低2G。
用完后要记得释放内存:
IoFreeMdl(pShareMM_MDL); //释放MDL
ExFreePool(pMappingAddSys); //释放内存