NTSTATUS ScDetective_DispatchDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS ntStatus = STATUS_SUCCESS; PVOID InputBuffer = NULL; PVOID OutputBuffer = NULL; ULONG cbInputBuffer = 0; ULONG cbOutputBuffer = 0; PIO_STACK_LOCATION irpSp = NULL; __try { irpSp = IoGetCurrentIrpStackLocation(Irp); InputBuffer = Irp->AssociatedIrp.SystemBuffer; cbInputBuffer = irpSp->Parameters.DeviceIoControl.InputBufferLength; OutputBuffer = Irp->AssociatedIrp.SystemBuffer; cbOutputBuffer = irpSp->Parameters.DeviceIoControl.OutputBufferLength; switch(irpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_DUMP_KERNEL_MEMORY: { PVOID DumpAddress; PMDL MdlCreate; if (cbInputBuffer == sizeof(ULONG)) { DumpAddress = (PVOID)((PULONG)InputBuffer)[0]; if (!MmIsAddressValid(DumpAddress)) { ntStatus = STATUS_INVALID_ADDRESS; break; } else { ScmMapVirtualAddress(DumpAddress, cbOutputBuffer, &MdlCreate); RtlCopyMemory(OutputBuffer, DumpAddress, cbOutputBuffer); ScmUnmapVirtualAddress(MdlCreate); Irp->IoStatus.Information = cbOutputBuffer; break; } } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_SSDT: // 获取 ssdt { ULONG NeedLen = 0; ULONG Number = GetSsdtServiceNumber(); NeedLen = Number * sizeof(SSDT_ADDRESS); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } Number = GetSsdtCurrentAddresses((PSSDT_ADDRESS)OutputBuffer, &NeedLen); if (Number == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = Number * sizeof(SSDT_ADDRESS); break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_UNHOOK_SSDT: // 恢复 ssdt { PSSDT_ADDRESS SsdtOrig = (PSSDT_ADDRESS)InputBuffer; if (cbInputBuffer < sizeof(SSDT_ADDRESS) || InputBuffer == NULL) { KdPrint(("输入缓冲区或输入缓冲区长度无效")); ntStatus = STATUS_UNSUCCESSFUL; break; } KdPrint(("要恢复的服务号:%d 原始地址:0x%X", SsdtOrig->nIndex, SsdtOrig->FunAddress)); if (!UnHookSsdtItem(SsdtOrig)) { KdPrint(("恢复失败")); ntStatus = STATUS_UNSUCCESSFUL; } break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_SSDTSHADOW: { ULONG Number = GetShadowSsdtServiceNumber(); ULONG NeedLen = 0; NeedLen = Number * sizeof(SSDT_ADDRESS); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } Number = GetShadowSsdtCurrentAddresses((PSSDT_ADDRESS)OutputBuffer, &NeedLen); if (Number == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = Number * sizeof(SSDT_ADDRESS); break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_UNHOOK_SSDTSHADOW: { PSSDT_ADDRESS ShadowSsdtOrig = (PSSDT_ADDRESS)InputBuffer; if (cbInputBuffer < sizeof(SSDT_ADDRESS) || InputBuffer == NULL) { KdPrint(("输入缓冲区或输入缓冲区长度无效")); ntStatus = STATUS_UNSUCCESSFUL; break; } KdPrint(("要恢复的服务号:%d 原始地址:0x%X", ShadowSsdtOrig->nIndex, ShadowSsdtOrig->FunAddress)); if (!UnHookShadowSsdtItem(ShadowSsdtOrig, g_CsrssProcess)) { ntStatus = STATUS_UNSUCCESSFUL; } break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_PROCESSES: { PPROCESS_LIST_HEAD ProcessHead; ULONG NeedLen; ULONG ReturnLength; ProcessHead = ScPsQuerySystemProcessList(); NeedLen = ProcessHead->NumberOfProcesses * sizeof(PROCESS_INFO); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyProcessList2Buffer((PPROCESS_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_PROCESS_IMAGE_PATH: { PEPROCESS Process = NULL; PUNICODE_STRING NameString; ULONG BufferSize; if (cbInputBuffer == sizeof(ULONG)) { Process = ((PEPROCESS*)InputBuffer)[0]; if (Process == NULL) { ntStatus = STATUS_ACCESS_DENIED; break; } } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (Process == g_SystemProcess) { if (cbOutputBuffer > sizeof(L"System")) { RtlCopyMemory(OutputBuffer, L"System", sizeof(L"System")); Irp->IoStatus.Information = sizeof(L"System"); break; } } else if (Process == g_IdleProcess) { if (cbOutputBuffer > sizeof(L"Idle")) { RtlCopyMemory(OutputBuffer, L"Idle", sizeof(L"Idle")); Irp->IoStatus.Information = sizeof(L"Idle"); break; } } if (cbOutputBuffer < 520) { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } BufferSize = cbOutputBuffer + sizeof(UNICODE_STRING); NameString = ExAllocatePoolWithTag(NonPagedPool, BufferSize, MEM_TAG); NameString->Buffer = (PWCH)((ULONG)NameString + 8); NameString->Length = 0; NameString->MaximumLength = (USHORT)cbOutputBuffer; ntStatus = ScPsGetProcessImagePath(Process, NameString); if (NT_SUCCESS(ntStatus)) { RtlCopyMemory(OutputBuffer, NameString->Buffer, NameString->Length); } Irp->IoStatus.Information = NameString->Length; ExFreePoolWithTag(NameString, MEM_TAG); break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_PROCESS_THREADS: { PTHREAD_LIST_HEAD ThreadHead = NULL; PEPROCESS EProcess = NULL; ULONG NeedLen = 0; ULONG ReturnLength = 0; if (cbInputBuffer == sizeof(ULONG)) { EProcess = ((PEPROCESS*)InputBuffer)[0]; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (EProcess == g_IdleProcess) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } } ThreadHead = ScPsQueryProcessThreadList(EProcess); if (ThreadHead == NULL) { ntStatus = STATUS_UNSUCCESSFUL; break; } NeedLen = ThreadHead->NumberOfThread * sizeof(THREAD_INFO); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyThreadList2Buffer((PTHREAD_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_PROCESS_MODULES: { PMODULE_LIST_HEAD ModuleHead = NULL; PEPROCESS EProcess = NULL; ULONG NeedLen = 0; ULONG ReturnLength = 0; if (cbInputBuffer == sizeof(ULONG)) { EProcess = ((PEPROCESS*)InputBuffer)[0]; } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } if (EProcess == g_IdleProcess) { if (cbOutputBuffer = sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } } ModuleHead = ScPsQueryProcessModuleList(EProcess); if (ModuleHead == NULL) { ntStatus = STATUS_UNSUCCESSFUL; break; } NeedLen = ModuleHead->NumberOfModules * sizeof(MODULE_INFO); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyModuleList2Buffer((PMODULE_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_GET_DRIVER_OBJECT: { PDRIVER_LIST_HEAD DriverHead = NULL; PEPROCESS EProcess = NULL; HANDLE UserEvent; PKEVENT kEvent; ULONG NeedLen = 0; ULONG ReturnLength = 0; if (cbInputBuffer == sizeof(HANDLE) * 2) { UserEvent = *(PHANDLE)InputBuffer; ntStatus = ObReferenceObjectByHandle(UserEvent, 0, *ExEventObjectType, UserMode, &kEvent, NULL); if (NT_SUCCESS(ntStatus)) { ScObQueryDriverObject(pdoGlobalDrvObj, kEvent); ObDereferenceObject(kEvent); } Irp->IoStatus.Information = 0; break; } DriverHead = ScObQueryDriverObject(NULL, NULL); if (DriverHead == NULL) { ntStatus = STATUS_UNSUCCESSFUL; break; } NeedLen = DriverHead->NumberOfDrivers * sizeof(DRIVER_INFO); if (cbOutputBuffer < NeedLen) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLen; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyDriverList2Buffer((PDRIVER_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_LIST_DIRECTORY: { PWCHAR pszDirectory; ULONG NeedLength; ULONG ReturnLength; PFILE_LIST_HEAD FileHead; pszDirectory = ExAllocatePoolWithTag(PagedPool, 260 * 2, MEM_TAG); RtlZeroMemory(pszDirectory, 260 * 2); if (cbInputBuffer == 260 * 2) { RtlCopyMemory(pszDirectory, InputBuffer, 260 * 2); } else { ntStatus = STATUS_BUFFER_TOO_SMALL; break; } FileHead = ScfsQueryDirectoryInformation(pszDirectory); if (FileHead == NULL) { ((PULONG)OutputBuffer)[0] = 0; Irp->IoStatus.Information = sizeof(ULONG); ntStatus = STATUS_SUCCESS; break; } NeedLength = FileHead->NumberOfItems * sizeof(FILE_INFO); if (cbOutputBuffer < NeedLength) { if (cbOutputBuffer == sizeof(ULONG)) { ((PULONG)OutputBuffer)[0] = NeedLength; Irp->IoStatus.Information = sizeof(ULONG); break; } ntStatus = STATUS_BUFFER_TOO_SMALL; break; } ReturnLength = ExCopyFileList2Buffer((PFILE_INFO)OutputBuffer); if (ReturnLength == 0) ntStatus = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = ReturnLength; ExFreePoolWithTag(pszDirectory, MEM_TAG); break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_PROTECT_MYSELF: { HANDLE ProcessId; if (cbInputBuffer == sizeof(ULONG)) { ProcessId = ((PHANDLE)InputBuffer)[0]; if (ProcessId) { ntStatus = ScPtHideProcessById(ProcessId); } } Irp->IoStatus.Information = 0; break; } ////////////////////////////////////////////////////////////////////////// case IOCTL_EXIT_PROCESS: ScPtUnloadRoutine(); break; ////////////////////////////////////////////////////////////////////////// default: Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; break; } } __except (EXCEPTION_EXECUTE_HANDLER) { ntStatus = GetExceptionCode(); Irp->IoStatus.Information = 0; } Irp->IoStatus.Status = ntStatus; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; }
应该像psnull那样把各个分发例程分两层处理的,不但看起来美观,而且方便管理
一旦内核和用户层交互多了,这该怎么管理啊,真后悔开始没有多参考优秀的工程啊
以后又有很多体力活要做了。。。