DriverEntry.c
#include <ntddk.h>
#define DEVICE_NAME L"\\Device\\MyDDKDevice1"
#define SYMBOLIC_LINK_NAME L"\\??\\MyDDKDevice1"
//#define DEVICE_EX_SIZE 200
//读设备
#define READ_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_READ_ACCESS)
//写设备
#define WRITE_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x831,METHOD_BUFFERED,FILE_WRITE_ACCESS)
//获取内核分配的非分页内存在用户空间中的虚拟地址
#define GET_PTR_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x832,METHOD_BUFFERED,FILE_READ_ACCESS)
//取消内核分配的非分页内存映射到用户空间
#define UNMAP_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x833,METHOD_BUFFERED,FILE_READ_ACCESS)
typedef struct
{
PVOID kva;
PMDL pMdl;
}DeviceExtension;
VOID KeSleep(LONG msec)
{
LARGE_INTEGER interval;
interval.QuadPart = -10000; // 100ns units, -10000 means 10ms
interval.QuadPart *= msec;
KeDelayExecutionThread(KernelMode, FALSE, &interval);
}
VOID DriverUnload(__in struct _DRIVER_OBJECT* DriverObject)
{
DeviceExtension* pdx;
UNICODE_STRING symbolLinkName;
DbgPrint("DriverUnload\n");
pdx = DriverObject->DeviceObject->DeviceExtension;
if (pdx->kva != NULL && pdx->pMdl != NULL)
{
IoFreeMdl(pdx->pMdl);
ExFreePool(pdx->kva);
}
if (DriverObject->DeviceObject)
IoDeleteDevice(DriverObject->DeviceObject);
RtlInitUnicodeString(&symbolLinkName, SYMBOLIC_LINK_NAME);
IoDeleteSymbolicLink(&symbolLinkName);
}
NTSTATUS OnCreateDevice(__in struct _DEVICE_OBJECT* DeviceObject, __inout struct _IRP* Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("OnCreateDevice\n");
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS OnReadDevice(__in struct _DEVICE_OBJECT* DeviceObject, __inout struct _IRP* Irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stack;
ULONG wantRead;
char* pData = "This data is from kernel.";
int len = strlen(pData) + 1;
DbgPrint("OnReadDevice\n");
stack = IoGetCurrentIrpStackLocation(Irp);
wantRead = stack->Parameters.Read.Length;//用户想要读取的字节数
DbgPrint("App wants to read %d bytes\n", wantRead);
// 完成IRP
//设置IRP完成状态
Irp->IoStatus.Status = status;
//设置IRP操作了多少字节
Irp->IoStatus.Information = len;
DbgPrint("readBuf address:%p\n", Irp->AssociatedIrp.SystemBuffer);
memcpy(Irp->AssociatedIrp.SystemBuffer, pData, len);
//KeSleep(5000);
//处理IRP
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//IoMarkIrpPending(Irp);
//status = STATUS_PENDING;
return status;
}
NTSTATUS OnWriteDevice(__in struct _DEVICE_OBJECT* DeviceObject, __inout struct _IRP* Irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stack;
ULONG len;//App写到内核的数据量
DbgPrint("OnWriteDevice\n");
stack = IoGetCurrentIrpStackLocation(Irp);
len = stack->Parameters.Write.Length;//App写到内核的数据量
DbgPrint("writeBuf address:%p\n", Irp->AssociatedIrp.SystemBuffer);
DbgPrint("Kernel recved %d bytes from App.The content is:%s\n", len, Irp->AssociatedIrp.SystemBuffer);
// 完成IRP
//设置IRP完成状态
Irp->IoStatus.Status = status;
//设置IRP操作了多少字节
Irp->IoStatus.Information = 13;
//RtlZeroMemory(DeviceObject->DeviceExtension, DEVICE_EX_SIZE);
//memcpy(DeviceObject->DeviceExtension, Irp->AssociatedIrp.SystemBuffer, len);
//处理IRP
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS OnCloseDevice(__in struct _DEVICE_OBJECT* DeviceObject, __inout struct _IRP* Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("OnCloseDevice\n");
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS OnCleanupDevice(__in struct _DEVICE_OBJECT* DeviceObject, __inout struct _IRP* Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("OnCleanupDevice\n");
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS OnDeviceIoControl(__in struct _DEVICE_OBJECT* DeviceObject, __inout struct _IRP* Irp)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG_PTR Informaiton = 0;
PVOID InputData = NULL;
ULONG InputDataLength = 0;
PVOID OutputData = NULL;
ULONG OutputDataLength = 0;
ULONG IoControlCode = 0;
char* pData = NULL;
int len = 0;
DeviceExtension* pdx = NULL;
PVOID uva = NULL;
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp); //Irp堆栈
IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
pdx = DeviceObject->DeviceExtension;
DbgPrint("OnDeviceIoControl\n");
switch (IoControlCode)
{
case WRITE_CTL_CODE:
InputData = Irp->AssociatedIrp.SystemBuffer;
InputDataLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
DbgPrint("App write to kernel by DeviceIoControl %d bytes,the content is:%s\n", InputDataLength, InputData);
Irp->IoStatus.Information = InputDataLength;
break;
case READ_CTL_CODE:
OutputData = Irp->AssociatedIrp.SystemBuffer;
OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
DbgPrint("App wants to read %d bytes from kernel by DeviceIoControl\n", OutputDataLength);
pData = "Ring0 --> Ring3";
len = strlen(pData) + 1;
memcpy(OutputData, pData, len);
Irp->IoStatus.Information = len;
break;
case GET_PTR_CTL_CODE:
// 将内核空间映射到用户空间
OutputData = Irp->AssociatedIrp.SystemBuffer;
__try
{
uva = MmMapLockedPagesSpecifyCache(pdx->pMdl,
UserMode, MmCached, NULL, FALSE, NormalPagePriority);
*((ULONGLONG*)OutputData) = (ULONGLONG)uva;
DbgPrint("MmMapLockedPagesSpecifyCache Success\n");
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
*((ULONGLONG*)OutputData) = (ULONGLONG)NULL;
DbgPrint("MmMapLockedPagesSpecifyCache Fail\n");
}
Irp->IoStatus.Information = sizeof(ULONGLONG);
break;
case UNMAP_CTL_CODE:
InputData = Irp->AssociatedIrp.SystemBuffer;
__try
{
uva = *((ULONGLONG*)InputData);
MmUnmapLockedPages(uva, pdx->pMdl);
DbgPrint("MmUnmapLockedPages Success\n");
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("MmUnmapLockedPages Fail\n");
}
Irp->IoStatus.Information = 0;
break;
}
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT* DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
DEVICE_OBJECT* pdo;
UNICODE_STRING devicename, symbolLinkName;
DeviceExtension* pdx;
RtlInitUnicodeString(&devicename, DEVICE_NAME);
RtlInitUnicodeString(&symbolLinkName, SYMBOLIC_LINK_NAME);
DbgPrint("DriverEntry\n");
status = IoCreateDevice(DriverObject, sizeof(DeviceExtension),
&devicename, FILE_DEVICE_UNKNOWN, 0, TRUE, &pdo);
if (!NT_SUCCESS(status))
{
DbgPrint("Create Device Object Failed:%x\n", status);
return status;
}
pdo->Flags |= DO_BUFFERED_IO;
status = IoCreateSymbolicLink(&symbolLinkName, &devicename);
if (!NT_SUCCESS(status))
{
DbgPrint("Create SymbolicLink Name Failed:%x\n", status);
IoDeleteDevice(pdo);
return status;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = OnCreateDevice;
DriverObject->MajorFunction[IRP_MJ_READ] = OnReadDevice;
DriverObject->MajorFunction[IRP_MJ_WRITE] = OnWriteDevice;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = OnCloseDevice;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = OnCleanupDevice;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OnDeviceIoControl;
DriverObject->DriverUnload = DriverUnload;
pdx = pdo->DeviceExtension;
__try
{
//分配内核空间
size_t sz = 1024 * PAGE_SIZE * 16;//64MB
pdx->kva = ExAllocatePool(NonPagedPool, sz);
if (pdx->kva != NULL)
{
RtlZeroMemory(pdx->kva, sz);//必须清零才能映射到用户空间
//创建MDL
pdx->pMdl = IoAllocateMdl(pdx->kva, sz, FALSE, FALSE, NULL);
if (pdx->pMdl != NULL)
{
MmBuildMdlForNonPagedPool(pdx->pMdl);
DbgPrint("ExAllocatePool Success\n");
}
else
{
ExFreePool(pdx->kva);
pdx->kva = NULL;
DbgPrint("ExAllocatePool Failed\n");
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
pdx->kva = NULL;
pdx->pMdl = NULL;
DbgPrint("ExAllocatePool Failed\n");
}
return status;
}
用户进程A:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#define CALC_RUN_TIME(start,finish) ((double)((finish)-(start))/CLOCKS_PER_SEC)
#define DEVICE_NAME "\\\\.\\MyDDKDevice1"
//读设备
#define READ_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_READ_ACCESS)
//写设备
#define WRITE_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x831,METHOD_BUFFERED,FILE_WRITE_ACCESS)
//获取内核分配的非分页内存在用户空间中的虚拟地址
#define GET_PTR_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x832,METHOD_BUFFERED,FILE_READ_ACCESS)
//取消内核分配的非分页内存映射到用户空间
#define UNMAP_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x833,METHOD_BUFFERED,FILE_READ_ACCESS)
DWORD ReadMyDevice(HANDLE hDevice, char* buf, int len)
{
DWORD dwRead = 0;
DeviceIoControl(hDevice, READ_CTL_CODE, NULL, 0, buf, len, &dwRead, NULL);
return dwRead;
}
void* GetKVAMappedToUVA(HANDLE hDevice)
{
DWORD dwRead = 0;
unsigned long long uva;
DeviceIoControl(hDevice, GET_PTR_CTL_CODE, NULL, 0, &uva, sizeof(unsigned long long),
&dwRead, NULL);
return (void*)uva;
}
DWORD WriteMyDevice(HANDLE hDevice, char* buf, int len)
{
DWORD dwWrite = 0;
DeviceIoControl(hDevice, WRITE_CTL_CODE, buf, len, NULL, 0, &dwWrite, NULL);
return dwWrite;
}
void main()
{
HANDLE hDevice = CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_DEVICE, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("打开设备失败\n");
system("pause");
return;
}
void* uva = GetKVAMappedToUVA(hDevice);
if (uva != NULL)
{
int len = 64 * 1024 * 1024;
memset((void*)uva, 0, len);
memset((void*)uva, 'A', len - 1);
printf("写成功\n");
}
CloseHandle(hDevice);
printf("写完成\n");
system("pause");
}
用户进程B:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#define CALC_RUN_TIME(start,finish) ((double)((finish)-(start))/CLOCKS_PER_SEC)
#define DEVICE_NAME "\\\\.\\MyDDKDevice1"
//读设备
#define READ_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x830,METHOD_BUFFERED,FILE_READ_ACCESS)
//写设备
#define WRITE_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x831,METHOD_BUFFERED,FILE_WRITE_ACCESS)
//获取内核分配的非分页内存在用户空间中的虚拟地址
#define GET_PTR_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x832,METHOD_BUFFERED,FILE_READ_ACCESS)
//取消内核分配的非分页内存映射到用户空间
#define UNMAP_CTL_CODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x833,METHOD_BUFFERED,FILE_READ_ACCESS)
DWORD ReadMyDevice(HANDLE hDevice, char* buf, int len)
{
DWORD dwRead = 0;
DeviceIoControl(hDevice, READ_CTL_CODE, NULL, 0, buf, len, &dwRead, NULL);
return dwRead;
}
void* GetKVAMappedToUVA(HANDLE hDevice)
{
DWORD dwRead = 0;
unsigned long long uva;
DeviceIoControl(hDevice, GET_PTR_CTL_CODE, NULL, 0, &uva, sizeof(unsigned long long),
&dwRead, NULL);
return (void*)uva;
}
DWORD WriteMyDevice(HANDLE hDevice, char* buf, int len)
{
DWORD dwWrite = 0;
DeviceIoControl(hDevice, WRITE_CTL_CODE, buf, len, NULL, 0, &dwWrite, NULL);
return dwWrite;
}
void main()
{
HANDLE hDevice = CreateFileA(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_DEVICE, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("打开设备失败\n");
system("pause");
return;
}
void* uva = GetKVAMappedToUVA(hDevice);
if (uva != NULL)
{
char* p = (char*)uva;
int br = 1;
}
CloseHandle(hDevice);
system("pause");
}