VOID CBTdPostOperationCallback ( _In_ PVOID RegistrationContext, _In_ POB_POST_OPERATION_INFORMATION PostInfo ) { PTD_CALLBACK_REGISTRATION CallbackRegistration = (PTD_CALLBACK_REGISTRATION)RegistrationContext; TdCheckAndFreeCallContext (PostInfo, CallbackRegistration); if (PostInfo->ObjectType == *PsProcessType) { // // Ignore requests for processes other than our target process. // if (CallbackRegistration->TargetProcess != NULL && CallbackRegistration->TargetProcess != PostInfo->Object ) { return; } // // Also ignore requests that are trying to open/duplicate the current // process. // if (PostInfo->Object == PsGetCurrentProcess()) { return; } } else if (PostInfo->ObjectType == *PsThreadType) { HANDLE ProcessIdOfTargetThread = PsGetThreadProcessId ((PETHREAD)PostInfo->Object); // // Ignore requests for threads belonging to processes other than our // target process. // if (CallbackRegistration->TargetProcess != NULL && CallbackRegistration->TargetProcessId != ProcessIdOfTargetThread ) { return; } // // Also ignore requests for threads belonging to the current processes. // if (ProcessIdOfTargetThread == PsGetCurrentProcessId()) { return; } } else { TD_ASSERT (FALSE); } }
VOID TdDeviceUnload ( _In_ PDRIVER_OBJECT DriverObject ) { NTSTATUS Status = STATUS_SUCCESS; UNICODE_STRING DosDevicesLinkName = RTL_CONSTANT_STRING (TD_DOS_DEVICES_LINK_NAME); DbgPrintEx (DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: TdDeviceUnload\n"); // // Unregister process notify routines. // if (TdProcessNotifyRoutineSet2 == TRUE) { Status = PsSetCreateProcessNotifyRoutineEx ( TdCreateProcessNotifyRoutine2, TRUE ); TD_ASSERT (Status == STATUS_SUCCESS); TdProcessNotifyRoutineSet2 = FALSE; } // remove filtering and remove any OB callbacks TdbProtectName = FALSE; Status = TdDeleteProtectNameCallback(); TD_ASSERT (Status == STATUS_SUCCESS); // // Delete the link from our device name to a name in the Win32 namespace. // Status = IoDeleteSymbolicLink (&DosDevicesLinkName); if (Status != STATUS_INSUFFICIENT_RESOURCES) { // // IoDeleteSymbolicLink can fail with STATUS_INSUFFICIENT_RESOURCES. // TD_ASSERT (NT_SUCCESS (Status)); } // // Delete our device object. // IoDeleteDevice (DriverObject->DeviceObject); }
void TdCheckAndFreeCallContext ( _Inout_ POB_POST_OPERATION_INFORMATION PostInfo, _In_ PTD_CALLBACK_REGISTRATION CallbackRegistration ) { PTD_CALL_CONTEXT CallContext = (PTD_CALL_CONTEXT)PostInfo->CallContext; if (CallContext != NULL) { TD_ASSERT (CallContext->CallbackRegistration == CallbackRegistration); TD_ASSERT (CallContext->Operation == PostInfo->Operation); TD_ASSERT (CallContext->Object == PostInfo->Object); TD_ASSERT (CallContext->ObjectType == PostInfo->ObjectType); ExFreePoolWithTag (CallContext, TD_CALL_CONTEXT_TAG); } }
/////////////////////////////////////////////////////////////////////////////// /// /// Handle driver unloading. All this driver needs to do /// is to delete the device object and the symbolic link between our /// device name and the Win32 visible name. /// /////////////////////////////////////////////////////////////////////////////// VOID TdDeviceUnload( _In_ PDRIVER_OBJECT DriverObject ) { NTSTATUS Status = STATUS_SUCCESS; UNICODE_STRING DosDevicesLinkName = RTL_CONSTANT_STRING(QD_DOS_DEVICES_LINK_NAME); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "QuietDragon: TdDeviceUnload\n"); // Unregister process notify routines. if (gProcessNotifyRoutine_isSet == TRUE) { Status = PsSetCreateProcessNotifyRoutineEx( MyCreateProcessNotifyRoutine, TRUE ); TD_ASSERT(Status == STATUS_SUCCESS); gProcessNotifyRoutine_isSet = FALSE; } // TODO Need to clean up lists and locks // Free allocated mem PQD_COMM_CONTROL_DEVICE_EXTENSION controlExt = (PQD_COMM_CONTROL_DEVICE_EXTENSION)g_CommDeviceObject->DeviceExtension; ExFreePoolWithTag(controlExt->DecisionData, 'SRdd'); // Delete the link from our device name to a name in the Win32 namespace. Status = IoDeleteSymbolicLink(&DosDevicesLinkName); if (Status != STATUS_INSUFFICIENT_RESOURCES) { // IoDeleteSymbolicLink can fail with STATUS_INSUFFICIENT_RESOURCES. TD_ASSERT(NT_SUCCESS(Status)); } // Delete our device object. IoDeleteDevice(DriverObject->DeviceObject); }
/////////////////////////////////////////////////////////////////////////////// /// /// Driver entry /// /////////////////////////////////////////////////////////////////////////////// NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { NTSTATUS Status; UNICODE_STRING NtDeviceName = RTL_CONSTANT_STRING(QD_NT_DEVICE_NAME); UNICODE_STRING DosDevicesLinkName = RTL_CONSTANT_STRING(QD_DOS_DEVICES_LINK_NAME); BOOLEAN SymLinkCreated = FALSE; PQD_COMM_CONTROL_DEVICE_EXTENSION controlExt; UNREFERENCED_PARAMETER(RegistryPath); // Request NX Non-Paged Pool when available ExInitializeDriverRuntime(DrvRtPoolNxOptIn); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "QuietDragon: DriverEntry: Driver loaded\n"); // // Initialize globals. // // // Create our device object. // // TODO Consider using IoCreateDeviceSecure Status = IoCreateDevice( DriverObject, // pointer to driver object sizeof(QD_COMM_CONTROL_DEVICE_EXTENSION), // device extension size &NtDeviceName, // device name FILE_DEVICE_UNKNOWN, // device type 0, // device characteristics FALSE, // not exclusive &g_CommDeviceObject); // returned device object pointer if (!NT_SUCCESS(Status)) { goto Exit; } TD_ASSERT(g_CommDeviceObject == DriverObject->DeviceObject); // // Set dispatch routines. // DriverObject->MajorFunction[IRP_MJ_CREATE] = TdDeviceCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = TdDeviceClose; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TdDeviceCleanup; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TdDeviceControl; DriverObject->DriverUnload = TdDeviceUnload; // // Set up the device extension // controlExt = (PQD_COMM_CONTROL_DEVICE_EXTENSION)g_CommDeviceObject->DeviceExtension; controlExt->MagicNumber = QD_COMM_CONTROL_EXTENSION_MAGIC_NUMBER; InitializeListHead(&controlExt->ProcessQueue); ExInitializeFastMutex(&controlExt->ProcessQueueLock); InitializeListHead(&controlExt->RequestQueue); ExInitializeFastMutex(&controlExt->RequestQueueLock); ExInitializeFastMutex(&controlExt->DecisionDataLock); controlExt->DecisionData = (PCONTROL_PROC_INTERNAL)ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROL_PROC_INTERNAL)*QD_MAX_PROCS, 'SRdd'); RtlZeroMemory(controlExt->DecisionData, sizeof(CONTROL_PROC_INTERNAL)*QD_MAX_PROCS); // Init DecisionData for (USHORT i = 0; i < QD_MAX_PROCS; i++) { PCONTROL_PROC_INTERNAL control_proc = &(controlExt->DecisionData[i]); control_proc->StartTime.QuadPart = 0; KeInitializeEvent(&(control_proc->DecisionEvent), NotificationEvent, FALSE); } // // Create a link in the Win32 namespace. // Status = IoCreateSymbolicLink(&DosDevicesLinkName, &NtDeviceName); if (!NT_SUCCESS(Status)) { goto Exit; } SymLinkCreated = TRUE; // // Set process create routines. // Status = PsSetCreateProcessNotifyRoutineEx( MyCreateProcessNotifyRoutine, FALSE ); if (!NT_SUCCESS(Status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "QuietDragon: DriverEntry: PsSetCreateProcessNotifyRoutineEx returned 0x%x\n", Status); goto Exit; } gProcessNotifyRoutine_isSet = TRUE; Exit: if (!NT_SUCCESS(Status)) { if (gProcessNotifyRoutine_isSet == TRUE) { Status = PsSetCreateProcessNotifyRoutineEx( MyCreateProcessNotifyRoutine, TRUE ); TD_ASSERT(Status == STATUS_SUCCESS); gProcessNotifyRoutine_isSet = FALSE; } if (SymLinkCreated == TRUE) { IoDeleteSymbolicLink(&DosDevicesLinkName); } if (g_CommDeviceObject != NULL) { IoDeleteDevice(g_CommDeviceObject); } } return Status; }
// // CBTdPreOperationCallback // OB_PREOP_CALLBACK_STATUS CBTdPreOperationCallback ( _In_ PVOID RegistrationContext, _Inout_ POB_PRE_OPERATION_INFORMATION PreInfo ) { PTD_CALLBACK_REGISTRATION CallbackRegistration; ACCESS_MASK AccessBitsToClear = 0; ACCESS_MASK AccessBitsToSet = 0; ACCESS_MASK InitialDesiredAccess = 0; ACCESS_MASK OriginalDesiredAccess = 0; PACCESS_MASK DesiredAccess = NULL; LPCWSTR ObjectTypeName = NULL; LPCWSTR OperationName = NULL; // Not using driver specific values at this time CallbackRegistration = (PTD_CALLBACK_REGISTRATION)RegistrationContext; TD_ASSERT (PreInfo->CallContext == NULL); // Only want to filter attempts to access protected process // all other processes are left untouched if (PreInfo->ObjectType == *PsProcessType) { // // Ignore requests for processes other than our target process. // // if (TdProtectedTargetProcess != NULL && // TdProtectedTargetProcess != PreInfo->Object) if (TdProtectedTargetProcess != PreInfo->Object) { goto Exit; } // // Also ignore requests that are trying to open/duplicate the current // process. // if (PreInfo->Object == PsGetCurrentProcess()) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: CBTdPreOperationCallback: ignore process open/duplicate from the protected process itself\n"); goto Exit; } ObjectTypeName = L"PsProcessType"; AccessBitsToClear = CB_PROCESS_TERMINATE; AccessBitsToSet = 0; } else if (PreInfo->ObjectType == *PsThreadType) { HANDLE ProcessIdOfTargetThread = PsGetThreadProcessId ((PETHREAD)PreInfo->Object); // // Ignore requests for threads belonging to processes other than our // target process. // // if (CallbackRegistration->TargetProcess != NULL && // CallbackRegistration->TargetProcessId != ProcessIdOfTargetThread) if (TdProtectedTargetProcessId != ProcessIdOfTargetThread) { goto Exit; } // // Also ignore requests for threads belonging to the current processes. // if (ProcessIdOfTargetThread == PsGetCurrentProcessId()) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: CBTdPreOperationCallback: ignore thread open/duplicate from the protected process itself\n"); goto Exit; } ObjectTypeName = L"PsThreadType"; AccessBitsToClear = CB_THREAD_TERMINATE; AccessBitsToSet = 0; } else { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ObCallbackTest: CBTdPreOperationCallback: unexpected object type\n"); goto Exit; } switch (PreInfo->Operation) { case OB_OPERATION_HANDLE_CREATE: DesiredAccess = &PreInfo->Parameters->CreateHandleInformation.DesiredAccess; OriginalDesiredAccess = PreInfo->Parameters->CreateHandleInformation.OriginalDesiredAccess; OperationName = L"OB_OPERATION_HANDLE_CREATE"; break; case OB_OPERATION_HANDLE_DUPLICATE: DesiredAccess = &PreInfo->Parameters->DuplicateHandleInformation.DesiredAccess; OriginalDesiredAccess = PreInfo->Parameters->DuplicateHandleInformation.OriginalDesiredAccess; OperationName = L"OB_OPERATION_HANDLE_DUPLICATE"; break; default: TD_ASSERT (FALSE); break; } InitialDesiredAccess = *DesiredAccess; // Filter only if request made outside of the kernel if (PreInfo->KernelHandle != 1) { *DesiredAccess &= ~AccessBitsToClear; *DesiredAccess |= AccessBitsToSet; } // // Set call context. // TdSetCallContext (PreInfo, CallbackRegistration); DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: CBTdPreOperationCallback: PROTECTED process %p (ID 0x%p)\n", TdProtectedTargetProcess, (PVOID)TdProtectedTargetProcessId ); DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: CBTdPreOperationCallback\n" " Client Id: %p:%p\n" " Object: %p\n" " Type: %ls\n" " Operation: %ls (KernelHandle=%d)\n" " OriginalDesiredAccess: 0x%x\n" " DesiredAccess (in): 0x%x\n" " DesiredAccess (out): 0x%x\n", PsGetCurrentProcessId(), PsGetCurrentThreadId(), PreInfo->Object, ObjectTypeName, OperationName, PreInfo->KernelHandle, OriginalDesiredAccess, InitialDesiredAccess, *DesiredAccess ); Exit: return OB_PREOP_SUCCESS; }
NTSTATUS DriverEntry ( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { NTSTATUS Status; UNICODE_STRING NtDeviceName = RTL_CONSTANT_STRING (TD_NT_DEVICE_NAME); UNICODE_STRING DosDevicesLinkName = RTL_CONSTANT_STRING (TD_DOS_DEVICES_LINK_NAME); PDEVICE_OBJECT Device = NULL; BOOLEAN SymLinkCreated = FALSE; USHORT CallbackVersion; UNREFERENCED_PARAMETER (RegistryPath); DbgPrintEx (DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ObCallbackTest: DriverEntry: Driver loaded. Use ed nt!Kd_IHVDRIVER_Mask f (or 7) to enable more traces\n"); CallbackVersion = ObGetFilterVersion(); DbgPrintEx (DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "ObCallbackTest: DriverEntry: Callback version 0x%hx\n", CallbackVersion); // // Initialize globals. // KeInitializeGuardedMutex (&TdCallbacksMutex); // // Create our device object. // Status = IoCreateDevice ( DriverObject, // pointer to driver object 0, // device extension size &NtDeviceName, // device name FILE_DEVICE_UNKNOWN, // device type 0, // device characteristics FALSE, // not exclusive &Device); // returned device object pointer if (! NT_SUCCESS(Status)) { goto Exit; } TD_ASSERT (Device == DriverObject->DeviceObject); // // Set dispatch routines. // DriverObject->MajorFunction[IRP_MJ_CREATE] = TdDeviceCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = TdDeviceClose; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TdDeviceCleanup; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TdDeviceControl; DriverObject->DriverUnload = TdDeviceUnload; // // Create a link in the Win32 namespace. // Status = IoCreateSymbolicLink (&DosDevicesLinkName, &NtDeviceName); if (! NT_SUCCESS(Status)) { goto Exit; } SymLinkCreated = TRUE; // // Set process create routines. // Status = PsSetCreateProcessNotifyRoutineEx ( TdCreateProcessNotifyRoutine2, FALSE ); if (! NT_SUCCESS(Status)) { DbgPrintEx (DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ObCallbackTest: DriverEntry: PsSetCreateProcessNotifyRoutineEx(2) returned 0x%x\n", Status); goto Exit; } TdProcessNotifyRoutineSet2 = TRUE; Exit: if (!NT_SUCCESS (Status)) { if (TdProcessNotifyRoutineSet2 == TRUE) { Status = PsSetCreateProcessNotifyRoutineEx ( TdCreateProcessNotifyRoutine2, TRUE ); TD_ASSERT (Status == STATUS_SUCCESS); TdProcessNotifyRoutineSet2 = FALSE; } if (SymLinkCreated == TRUE) { IoDeleteSymbolicLink (&DosDevicesLinkName); } if (Device != NULL) { IoDeleteDevice (Device); } } return Status; }