/* hook1 is basic driver with unload support, logs every action too DebugView enjoy your first lesson */ /* this inelegant extern here is because of microsoft of course :) we all want to code c99, however, microsoft compiler does not support it so, we're forced to use c++ and that's why we need this here because we still want c headers and c format of functions etc. it is still better to use c++ and use only features that we want than to use microsft supported old ansi-c and be without these features */ extern "C" { #include #include "debug.h" #define DEVICE_NAME L"\\Device\\hook1" #define DOS_DEVICE_NAME L"\\DosDevices\\hook1" NTSTATUS hook1_create(PDEVICE_OBJECT DeviceObject,PIRP Irp); NTSTATUS hook1_close(PDEVICE_OBJECT DeviceObject,PIRP Irp); NTSTATUS hook1_device_control(PDEVICE_OBJECT DeviceObject,PIRP Irp); VOID hook1_unload(PDRIVER_OBJECT DriverObject); NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath); } //extern "C" /* dos device name is global variable because we use it in unload too, we can always make another RtlInitUnicodeString if we don't like global vars */ UNICODE_STRING dos_dev_name; /* create function is called everytime CreateFile is called on our device */ NTSTATUS hook1_create(PDEVICE_OBJECT DeviceObject,PIRP Irp) { DbgMsg("hook1.cpp: hook1_create(DeviceObject:0x%.8X,Irp:0x%.8X)",DeviceObject,Irp); NTSTATUS status=STATUS_SUCCESS; Irp->IoStatus.Status=status; IoCompleteRequest(Irp,IO_NO_INCREMENT); DbgMsg("hook1.cpp: hook1_create(-):0x%.8X)",status); return status; } /* close function is called everytime CloseHandle is called on our device close is associated with IRP_MJ_CLOSE and it is NOT executed in the context of the CloseHandle caller, if we want to make some cleanup in that context we rather associate cleanup function with IRP_MJ_CLEANUP */ NTSTATUS hook1_close(PDEVICE_OBJECT DeviceObject,PIRP Irp) { DbgMsg("hook1.cpp: hook1_close(DeviceObject:0x%.8X,Irp:0x%.8X)",DeviceObject,Irp); NTSTATUS status=STATUS_SUCCESS; Irp->IoStatus.Status=status; IoCompleteRequest(Irp,IO_NO_INCREMENT); DbgMsg("hook1.cpp: hook1_close(-):0x%.8X)",status); return status; } /* device control function is called everytime DeviceIoControl is called on our device, it is common way how user mode app communicate with driver */ NTSTATUS hook1_device_control(PDEVICE_OBJECT DeviceObject,PIRP Irp) { DbgMsg("hook1.cpp: hook1_device_control(DeviceObject:0x%.8X,Irp:0x%.8X)",DeviceObject,Irp); NTSTATUS status=STATUS_SUCCESS; Irp->IoStatus.Status=status; IoCompleteRequest(Irp,IO_NO_INCREMENT); DbgMsg("hook1.cpp: hook1_device_control(-):0x%.8X)",status); return status; } /* unload is called when driver is being unloaded, if we do not implement unload function them our driver can't be unloaded dynamically */ VOID hook1_unload(PDRIVER_OBJECT DriverObject) { DbgMsg("hook1.cpp: hook1_unload(DriverObject:0x%.8X)",DriverObject); //cleanup everything our driver created - delete symlink and device IoDeleteSymbolicLink(&dos_dev_name); IoDeleteDevice(DriverObject->DeviceObject); DbgMsg("hook1.cpp: hook1_unload(-)"); } /* DriverEntry is common driver entry point */ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) { DbgMsg("hook1.cpp: DriverEntry(DriverObject:0x%.8X,RegistryPath:0x%.8X)",DriverObject,RegistryPath); UNICODE_STRING dev_name; RtlInitUnicodeString(&dev_name,DEVICE_NAME); RtlInitUnicodeString(&dos_dev_name,DOS_DEVICE_NAME); /* if we want our driver to be accessible we need to create device for it, one driver can have more devices */ PDEVICE_OBJECT dev_obj; NTSTATUS status=IoCreateDevice(DriverObject,0,&dev_name,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&dev_obj); if (NT_SUCCESS(status)) { /* for some selected major functions we set handlers */ DriverObject->MajorFunction[IRP_MJ_CREATE] = hook1_create; DriverObject->MajorFunction[IRP_MJ_CLOSE] = hook1_close; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = hook1_device_control; DriverObject->DriverUnload = hook1_unload; /* this selects the method of IO, we use buffered IO as it is comfortable and effective for smaller packets */ dev_obj->Flags|=DO_BUFFERED_IO; /* if we want user mode application to communicate our driver we need to make a dos device link */ status=IoCreateSymbolicLink(&dos_dev_name,&dev_name); if (!NT_SUCCESS(status)) { DbgMsg("hook1.cpp: DriverEntry.IoCreateSymbolicLink failed with status 0x%.8X",status); IoDeleteDevice(DriverObject->DeviceObject); } } else DbgMsg("hook1.cpp: DriverEntry.IoCreateDevice failed with status 0x%.8X",status); DbgMsg("hook1.cpp: DriverEntry(-):0x%.8X",status); return status; }