内核安全编程(一)共享内存

来源:互联网 发布:2017 天使投资数据 编辑:程序博客网 时间:2024/06/06 13:18

前面分别通过读写驱动(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%08x\n",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%08x\n",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 :%d\n",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 : %d\n",GetLastError());CloseHandle(hFile);return 0;}bRet=DeviceIoControl(hFile,IOCTL_SHARE_MEMORY,NULL,0,&pShareAddr,4,&dwRet,NULL);if(!bRet){printf("DeviceIoControl False : %d\n",GetLastError());CloseHandle(hFile);}printf("DeviceIoControl IOCTL_SHARE_MEMORY pShareAddr:0x%08x ShareData:%s\n",pShareAddr,pShareAddr);bRet=DeviceIoControl(hFile,IOCTL_BUFFERED_IO,"LL Love U",10,NULL,20,&dwRet,NULL);if(!bRet){        printf("DeviceIoControl False : %d\n",GetLastError());CloseHandle(hFile);return 0;}printf("ShareMemory:%s\n",pShareAddr);CloseHandle(hFile);}



原创粉丝点击