Windows编写driver
1. 编译
Pspeek.cpp
#include <ntddk.h> #define DANIEL_LIST_PROCESS 0x8001 PDRIVER_OBJECT daniel_DriverObject; PDEVICE_OBJECT daniel_DeviceObject; NTSTATUS daniel_DispatchCreate( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION stackLocation; PIO_SECURITY_CONTEXT securityContext; stackLocation = IoGetCurrentIrpStackLocation(Irp); securityContext = stackLocation->Parameters.Create.SecurityContext; DbgPrint("###############\n"); DbgPrint("Daniel PsPeek daniel_DispatchCreate\n"); DbgPrint("###############\n"); Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } NTSTATUS KphDispatchDeviceControl( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) { NTSTATUS status; PIO_STACK_LOCATION stackLocation; PVOID originalInput; ULONG inputLength; ULONG ioControlCode; KPROCESSOR_MODE accessMode; UCHAR capturedInput[16 * sizeof(ULONG_PTR)]; PVOID capturedInputPointer; stackLocation = IoGetCurrentIrpStackLocation(Irp); originalInput = stackLocation->Parameters.DeviceIoControl.Type3InputBuffer; inputLength = stackLocation->Parameters.DeviceIoControl.InputBufferLength; ioControlCode = stackLocation->Parameters.DeviceIoControl.IoControlCode; accessMode = Irp->RequestorMode; // Probe and capture the input buffer. if (accessMode != KernelMode) { __try { ProbeForRead(originalInput, inputLength, sizeof(UCHAR)); memcpy(capturedInput, originalInput, inputLength); } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); goto ControlEnd; } } else { memcpy(capturedInput, originalInput, inputLength); } capturedInputPointer = capturedInput; // avoid casting below switch (ioControlCode) { case DANIEL_LIST_PROCESS: { status = STATUS_SUCCESS; } break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } ControlEnd: Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } VOID daniel_DriverUnload( __in PDRIVER_OBJECT DriverObject ) { PAGED_CODE(); IoDeleteDevice(daniel_DeviceObject); } extern "C" NTSTATUS DriverEntry( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath) { NTSTATUS status; UNICODE_STRING deviceName; PDEVICE_OBJECT deviceObject; PAGED_CODE(); DbgPrint("###############\n"); DbgPrint("Daniel PsPeek DriverEntry\n"); DbgPrint("Current Pid: %d\n", PsGetCurrentProcessId()); DbgPrint("###############\n"); daniel_DriverObject = DriverObject; // Create the device. RtlInitUnicodeString(&deviceName, L"\\Device\\DanielPsPeekDriver"); status = IoCreateDevice( DriverObject, 0, &deviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject ); if (!NT_SUCCESS(status)) return status; daniel_DeviceObject = deviceObject; // Set up I/O. DriverObject->MajorFunction[IRP_MJ_CREATE] = daniel_DispatchCreate; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KphDispatchDeviceControl; DriverObject->DriverUnload = daniel_DriverUnload; deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; return status; }
sources
TARGETNAME=Pspeek TARGETPATH=obj TARGETTYPE=DRIVER SOURCES=Pspeek.cpp
mk.bat
set setenv_script=D:\WinDDK\7600.16385.1\bin\setenv.bat set ddk_path=D:\WinDDK\7600.16385.1\ set config=chk set platform=x86 set os=WXP %setenv_script% %ddk_path% %config% %platform% %os% && H: && cd %cd% && build
2. 加载
ld.bat
sc stop Pspeek sc delete Pspeek copy /y "F:\pspeek.sys" "C:\WINDOWS\system32\pspeek.sys" sc create Pspeek binPath= "C:\WINDOWS\system32\pspeek.sys" type= kernel start= auto error= ignore DisplayName= "Daniel Process Peek Driver" sc start Pspeek
在Windows 7下,需要使用"管理员权限"才能执行上述脚本。
3. 枚举进程列表
void GatherProcessListByEPROCESS() { HANDLE pid = PsGetCurrentProcessId(); DbgPrint("Current Pid: %d\n", pid); PEPROCESS eprocess; PsLookupProcessByProcessId(pid, &eprocess); DbgPrint("_EPROCESS: 0x%08x\n", eprocess); _LIST_ENTRY active_process_node = {0,0}; memcpy(&active_process_node, (CHAR*)eprocess + 0x88, 8); DbgPrint("Active Process List Node: [0x%08x, 0x%08x]\n", active_process_node.Blink, active_process_node.Flink); DbgPrint("VirtualSize: 0x%08x \n", *(ULONG*)((CHAR*)eprocess + 0xb0)); }
上面代码与WinDbg的验证一致,因此Windows下获取内核相关的数据与Linux并无太大差别。
void PProcess(char* eprocess) { DbgPrint("%16s: 0x%08x\n", "_EPROCESS", eprocess); DbgPrint("%16s: %s\n", "ImageName", eprocess + 0x174); DbgPrint("\n"); } void GatherProcessListByEPROCESS() { HANDLE pid = PsGetCurrentProcessId(); DbgPrint("Current Pid: %d\n", pid); PEPROCESS eprocess; PsLookupProcessByProcessId(pid, &eprocess); _LIST_ENTRY active_process_node = {0,0}; memcpy(&active_process_node, (CHAR*)eprocess + 0x88, 8); _LIST_ENTRY* head = active_process_node.Flink; PProcess((char*)eprocess); for (_LIST_ENTRY* cur=head; cur->Flink != head; cur = cur->Flink) { PProcess((char*)cur - 0x88); } }