创建共享内存

c++

Posted by YiMiTuMi on February 15, 2022

创建共享内存

当应用层和驱动层通信的时候,可以通过共享内存的方式来实现。即在驱动层分配一块内存,并为这段内存指定一个应用层指针和内核层指针,来进行写入和读取数据。

程序

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);   //释放内存

蓝色妖姬 – 相守