概述
前面分别通过读写驱动(IRP)和IO控制(ControlCOde)两种方法来实现ring3和ring0的通信,今天学习共享内存通信方法
共享内存实现有两种方式:
1.应用程序分配内存,提供给驱动程序,由驱动程序映射并锁定该内存。
2.驱动程序分配内存,然后映射到应用程序地址范围内。
这里主要学习按书上的第二种方法的实现。
步骤:
1.驱动程序分配出一块内核空间。
2.使用MDL描述这篇内存并锁定内存,映射的用户空间。
3.将映射到用户空间的地址交给应用程序,然后由应用程序操作该地址内存空间。
代码如下:
1.首先添加一个IO_CODE用来处理共享内存的分配:
#define IOCTL_SHARE_MEMORY
CTL_CODE(FILE_DEVICE_UNKNOWN,0x893,METHOD_BUFFERED,FILE_ANY_ACCESS)
2.处理该共享内存的case分支如下:(前面的代码可参考之前的博客)
case IOCTL_SHARE_MEMORY:
pOutBuf=Irp->AssociatedIrp.SystemBuffer;
//pUseBuf=Irp->UserBuffer;这里获取用户空间地址(即IOControl函数的输入buf在ring3的地址)
//KdPrint(("IOCTL_SHARE_MEMOEY SysbBuf:0x%08x UserBuf:0x%08xn",pOutBuf,pUseBuf));
pSysAddr=DeviceObject->DeviceExtension;//将DeviceExtension做为要共享的内存
pMDL=IoAllocateMdl(pSysAddr,10,FALSE,FALSE,NULL);//分配MDL描述内核空间
if(NULL==pMDL)
{
KdPrint(("IOCTL_SHARE_MEMORY False!n"));
status=STATUS_UNSUCCESSFUL;
break;
}
MmBuildMdlForNonPagedPool(pMDL);//锁定该内核空间
*(ULONG *)pOutBuf=(ULONG)MmMapLockedPagesSpecifyCache(
pMDL,
UserMode,
MmNonCached,
NULL,
FALSE,
NormalPagePriority
);//映射内存
if(NULL==*(ULONG *)pOutBuf)
{
KdPrint(("IOCTL_SHARE_MEMORY False MmMapLocked...n"));
status=STATUS_UNSUCCESSFUL;
IoFreeMdl(pMDL);
break;
}
KdPrint(("IOCTL_SHARE_MEMOEY SysbBuf:0x%08x UserBuf:0x%08xn",pSysAddr,*(DWORD *)pOutBuf));
break;
有一些需要学习的:
1.ring3在调用DeviceIoControl时的输入参数:
BOOL WINAPI DeviceIoControl(
_In_ HANDLE hDevice,
_In_ DWORD dwIoControlCode,
_In_opt_ LPVOID lpInBuffer,
_In_ DWORD nInBufferSize,
_Out_opt_ LPVOID lpOutBuffer,
_In_ DWORD nOutBufferSize,
_Out_opt_ LPDWORD lpBytesReturned,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
lpOutBuffer在ring3层的地址在传递到ring0后保存在Irp->UserBuffer中。而IRP->AssociatedIrp.SystemBuffer实际是该参数在ring0的映射,当处理完Irp时就会将这块内存的数据拷贝到Irp->UserBuffer中。
2.*(DWORD *)pOutBuf=(DWORD)MmMapLockedPagesSpecifyCache
这句代码是将MmMapLockedPagesSpecifyCache返回的地址写入pOutBuf指向的内存空间,即“指针的指针”
换句话说,即poutBuf作为输出的指针,其内存中保存的是一个地址,这个地址指向了我们的共享内存。
(DWORD *)pOutBuf说明我们的pOutBuf指向的是一个DWORD类型的指针,然后再在前面加上"*",说明这个DWORD也是一个地址,而这个DWORD指向的地址就是共享内存的地址,即后面的赋值语句。
还可以通过一段程序来验证:
#include "stdafx.h"
#include "windows.h"
int _tmain(int argc, _TCHAR* argv[])
{
int a=8;
PVOID p=&a;
DWORD x=0x00123456;
*(DWORD *)p=x;
}
3.测试代码及结果如下:
首先通过IOCTL_BUFFERED_IO写入Hello World到扩展空间,然后发送IOCTL_SHARE_MEMORY将扩展空间作为共享内存并map到ring3,这样在ring0写入的"LL LOVE U"数据也相当于在ring3写入了数据。
#include "windows.h"
#include "winioctl.h"
#include "stdio.h"
#define IOCTL_BUFFERED_IO CTL_CODE(FILE_DEVICE_UNKNOWN,0x890,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_SHARE_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN,0x893,METHOD_BUFFERED,FILE_ANY_ACCESS)
int main()
{
HANDLE hFile=CreateFileA("\\.\DriverCtr0",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
printf("CreateFile Flase :%dn",GetLastError());
return 0;
}
BYTE * pShareAddr;
DWORD dwRet=0;
int bRet=0;
bRet=DeviceIoControl(hFile,IOCTL_BUFFERED_IO,"Hello World",10,NULL,20,&dwRet,NULL);
if(!bRet)
{
printf("DeviceIoControl False : %dn",GetLastError());
CloseHandle(hFile);
return 0;
}
bRet=DeviceIoControl(hFile,IOCTL_SHARE_MEMORY,NULL,0,&pShareAddr,4,&dwRet,NULL);
if(!bRet)
{
printf("DeviceIoControl False : %dn",GetLastError());
CloseHandle(hFile);
}
printf("DeviceIoControl IOCTL_SHARE_MEMORY pShareAddr:0x%08x ShareData:%sn",pShareAddr,pShareAddr);
bRet=DeviceIoControl(hFile,IOCTL_BUFFERED_IO,"LL Love U",10,NULL,20,&dwRet,NULL);
if(!bRet)
{
printf("DeviceIoControl False : %dn",GetLastError());
CloseHandle(hFile);
return 0;
}
printf("ShareMemory:%sn",pShareAddr);
CloseHandle(hFile);
}
最后
以上就是正直毛豆为你收集整理的内核安全编程(一)共享内存的全部内容,希望文章能够帮你解决内核安全编程(一)共享内存所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复