0x00 代码
桌面程序
#include <windows.h>
#include <stdio.h>
#define IOCTL_Device_Read_Write CTL_CODE(FILE_DEVICE_UNKNOWN, 0x999, METHOD_BUFFERED , FILE_READ_DATA | FILE_WRITE_DATA)
int main(int argc, char* grav[])
{
char readBuffer[300] = { 0 };
const char writeBuffer[] = "Console WriteFile";
size_t writeBufferLength = strlen(writeBuffer) + 1;
char deviceIoControlWrite[] = "Console DeviceIoControl";
size_t deviceIoControlWriterLength = strlen(deviceIoControlWrite) + 1;
char deviceIoControlRead[300] = { 0 };
DWORD BytesReturned = 0;
DWORD readNumber = 0;
DWORD writerNumber = 0;
printf("CreateFile\n");
system("pause");
HANDLE handle = CreateFile(L"\\\\.\\DataInteraction",GENERIC_READ| GENERIC_WRITE,0,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);
if(handle == INVALID_HANDLE_VALUE)
{
printf("INVALID_HANDLE_VALUE\n");
return 0;
}
printf("ReadFile\n");
system("pause");
if (ReadFile(handle, readBuffer, 100, &readNumber, NULL))
{
printf("ReadFile:: %s %d\n", readBuffer, readNumber);
}
else
{
printf("ReadFile failed\n");
}
printf("WriteFile\n");
system("pause");
if (WriteFile(handle, writeBuffer, writeBufferLength, &writerNumber, NULL))
{
printf("WriteFile success\n");
}
else
{
printf("WriteFile failed\n");
}
printf("DeviceIoControl\n");
system("pause");
if (DeviceIoControl(handle, IOCTL_Device_Read_Write, deviceIoControlWrite, deviceIoControlWriterLength, deviceIoControlRead, 300, &BytesReturned, NULL))
{
printf("DeviceIoControl Read: %s BytesReturned: %d\n", deviceIoControlRead, BytesReturned);
}else
{
printf("DeviceIoControl failed\n");
}
CloseHandle(handle);
system("pause");
return 0;
}
驱动
#include <wdm.h>
#define IOCTL_Device_Read_Write CTL_CODE(FILE_DEVICE_UNKNOWN, 0x999, METHOD_BUFFERED , FILE_READ_DATA | FILE_WRITE_DATA)
//驱动卸载
VOID DriverUnload(PDRIVER_OBJECT DriverObjec)
{
DbgPrint("DriverUnload");
if (DriverObjec->DeviceObject)
{
DbgPrint("DriverUnload->IoDeleteDevice");
IoDeleteDevice(DriverObjec->DeviceObject);
UNICODE_STRING SysmbolicLinkNmae = { 0 };
RtlInitUnicodeString(&SysmbolicLinkNmae, L"\\??\\DataInteraction");
IoDeleteSymbolicLink(&SysmbolicLinkNmae);
}
DbgPrint("DriverUnload success");
}
NTSTATUS MyDispatchCreate(PDEVICE_OBJECT DeviceObjct,PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("MyDispatchCreate");
Irp->IoStatus.Information = 0; //返回给R3的附加信息
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp,IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
NTSTATUS MyDispatchCleanUp(PDEVICE_OBJECT DeviceObjct,PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("MyDispatchCleanUp");
Irp->IoStatus.Information = 0; //返回给R3的附加信息
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp,IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
NTSTATUS MyDispatchClose(PDEVICE_OBJECT DeviceObjct, PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("MyDispatchClose");
Irp->IoStatus.Information = 0; //返回给R3的附加信息
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp, IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
NTSTATUS MyDispatchRead(PDEVICE_OBJECT DeviceObjct, PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
const char str[] = "Device MyDispatchRead";
size_t strLen = strlen(str) + 1;
DbgPrint("MyDispatchRead");
PIO_STACK_LOCATION IrpSp= IoGetCurrentIrpStackLocation(Irp); //获取堆信息
//BOOL ReadFile(HANDLE hFile,LPVOID lpBuffer,DWORD nNumberOfBytesToRead,LPDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped);
//IrpSp->Parameters.Read.Length == nNumberOfBytesToRead
if (IrpSp->Parameters.Read.Length < strLen)
{
Irp->IoStatus.Information = 0; //返回给R3的附加信息 -> lpNumberOfBytesRead
DbgPrint("MyDispatchRead failed");
}
else
{
//IrIrp->AssociatedIrp.SystemBuffer == lpBuffer
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, str, strLen);
//返回给R3的附加信息 -> lpNumberOfBytesRead
//修改此值会影响实际传输的数据. 修改为2,则实际只拷贝2字节
//Irp->IoStatus.Information = strLen;
Irp->IoStatus.Information = 10; //返回给R3的附加信息
DbgPrint("MyDispatchRead success");
}
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp, IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
NTSTATUS MyDispatchWrite(PDEVICE_OBJECT DeviceObjct, PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("MyDispatchWrite");
//BOOL WriteFile(HANDLE hFile,LPCVOID lpBuffer,DWORD nNumberOfBytesToWrite,LPDWORD lpNumberOfBytesWritten,LPOVERLAPPED lpOverlapped);
char str[256] = {0};
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); //获取堆信息
//IrpSp->Parameters.Read.Length == nNumberOfBytesToRead
if (IrpSp->Parameters.Write.Length > 256)
{
Irp->IoStatus.Information = 0; //返回给R3的附加信息 -> lpNumberOfBytesRead
DbgPrint("MyDispatchWrite failed");
}
else
{
//IrIrp->AssociatedIrp.SystemBuffer == lpBuffer
RtlCopyMemory(str, Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Write.Length);
DbgPrint("Device Write: %s",str);
Irp->IoStatus.Information = IrpSp->Parameters.Write.Length; //返回给R3的附加信息 -> lpNumberOfBytesRead
DbgPrint("MyDispatchWrite success");
}
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp, IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
NTSTATUS MyDispatchControl(PDEVICE_OBJECT DeviceObjct, PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
const char str[] = "Device MyDispatchControl";
size_t strLen = strlen(str) + 1;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); //获取堆信息
DbgPrint("MyDispatchControl");
DbgPrint("MyDispatchControl->IOCTL_Device_Read_Write:%d", IOCTL_Device_Read_Write);
DbgPrint("MyDispatchControl->IrpSp->Parameters.DeviceIoControl.IoControlCode:%d", IrpSp->Parameters.DeviceIoControl.IoControlCode);
//IrpSp->Parameters.DeviceIoControl.IoControlCode -> 用户层传入的指定代码
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_Device_Read_Write:
DbgPrint("MyDispatchControl->switch->IOCTL_Device_Read_Write");
DbgPrint("Device MyDispatchControl->Write: %s InputLenght:%d OutputLenght:%d",
(char*)Irp->AssociatedIrp.SystemBuffer,
IrpSp->Parameters.DeviceIoControl.InputBufferLength,
IrpSp->Parameters.DeviceIoControl.OutputBufferLength);
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < strLen)
{
Irp->IoStatus.Information = 0; //返回给R3的附加信息
DbgPrint("Device MyDispatchControl->Read failed");
}
else
{
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, str, strLen);
//Irp->IoStatus.Information = strLen; //返回给R3的附加信息
Irp->IoStatus.Information = 10; //返回给R3的附加信息
DbgPrint("Device MyDispatchControl->Read success");
}
break;
default:
DbgPrint("MyDispatchControl::switch->default");
break;
}
Irp->IoStatus.Status = status; //irp完成状态
IofCompleteRequest(Irp, IO_NO_INCREMENT); //当驱动程序完成给定IRP的所有处理时调用,代表IRP处理完成
return status;
}
//驱动入口
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
DbgPrint("DriverEntry");
//驱动卸载
DriverObject->DriverUnload = DriverUnload;
//创建设备
PDEVICE_OBJECT DeviceObjet = NULL;
UNICODE_STRING DeviceName = { 0 };
RtlInitUnicodeString(&DeviceName,L"\\Device\\DataInteraction");
status = IoCreateDevice(DriverObject,400,&DeviceName,FILE_DEVICE_UNKNOWN,0,TRUE,&DeviceObjet);
if (!NT_SUCCESS(status))
{
DbgPrint("DriverEntry->IoCreateDevice failed");
return status;
}
DeviceObjet->Flags |= DO_BUFFERED_IO; //未设置此标志,Irp->AssociatedIrp.SystemBuffer为NULL,注意是|= 不要直接=,会消除其它标志位
//创建符号链接
UNICODE_STRING SysmbolicLinkNmae = { 0 };
RtlInitUnicodeString(&SysmbolicLinkNmae, L"\\??\\DataInteraction");
status = IoCreateSymbolicLink(&SysmbolicLinkNmae,&DeviceName);
if (!NT_SUCCESS(status))
{
DbgPrint("DriverEntry->IoCreateSymbolicLink failed");
IoDeleteDevice(DeviceObjet);
return status;
}
//设备回调
//https:docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nc-wdm-driver_dispatch
DriverObject->MajorFunction[IRP_MJ_CREATE] = MyDispatchCreate; //CreateFile
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MyDispatchCleanUp; //CloseHandle
DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyDispatchClose; //CloseHandle
DriverObject->MajorFunction[IRP_MJ_READ] = MyDispatchRead; //ReadFile
DriverObject->MajorFunction[IRP_MJ_WRITE] = MyDispatchWrite; //WriteFile
//https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/defining-i-o-control-codes
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MyDispatchControl; //CustomCode
DbgPrint("DriverEntry Success");
return status;
}
0x01 汇总
1 回调
DriverObject->MajorFunction定义了IRP回调,通过索引定位不同的回调函数
2 IRP
PIO_STACK_LOCATION IrpSp= IoGetCurrentIrpStackLocation(Irp)获取I/O堆栈中与IRP相关联的条目
在不同回调中, 可以使用IrpSp不同的成员来明确操作.具体使用见文档:
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nc-wdm-driver_dispatch
2 创建(CreateFile)
调用 DriverObject->MajorFunction[IRP_MJ_CREATE]
3 读取(ReadFile)
调用 DriverObject->MajorFunction[IRP_MJ_ READ]
4 写入(WriteFile)
调用 DriverObject->MajorFunction[IRP_MJ_ WRITE]
5 自定义(DeviceIoControl)
调用 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]
IrpSp->Parameters.DeviceIoControl.IoControlCode为DeviceIoControl的第二个参数
6 关闭(CloseHandle)
先调用 DriverObject->MajorFunction[IRP_MJ_CLEANUP]
在调用 DriverObject->MajorFunction[IRP_MJ_CLOSE]
7设备缓冲区
IoCreateDevice第二个参数指定缓冲区大小
同时修改DeviceObjet->Flags,使其或上DO_BUFFERED_IO,如果未设置此标志则Irp->AssociatedIrp.SystemBuffer为NULL,注意是|= 不要直接=,否则会消除其它标志位
0x02文档
驱动派遣回调: 点击IRP查看详细的IPR和IrpSp参数说明
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nc-wdm-driver_dispatch
定义I/O控制代码: 自定义控制代码,回调详情看上述文档中的IRP_MJ_DEVICE_CONTROL
https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/defining-i-o-control-codes
https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol