2023-08-17 10:45:50 +02:00
|
|
|
#include "ioctl.h"
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
|
2023-08-19 04:52:57 +02:00
|
|
|
#include "nmi.h"
|
|
|
|
#include "modules.h"
|
2023-08-20 16:12:04 +02:00
|
|
|
#include "driver.h"
|
2023-08-20 17:04:53 +02:00
|
|
|
#include "callbacks.h"
|
2023-08-19 04:52:57 +02:00
|
|
|
|
2023-08-17 10:45:50 +02:00
|
|
|
NTSTATUS DeviceControl(
|
|
|
|
_In_ PDRIVER_OBJECT DriverObject,
|
|
|
|
_In_ PIRP Irp
|
|
|
|
)
|
|
|
|
{
|
2023-08-19 04:52:57 +02:00
|
|
|
UNREFERENCED_PARAMETER( DriverObject );
|
|
|
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
PIO_STACK_LOCATION stack_location = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
HANDLE handle;
|
2023-08-19 08:06:51 +02:00
|
|
|
PKTHREAD thread;
|
2023-08-19 04:52:57 +02:00
|
|
|
|
|
|
|
switch ( stack_location->Parameters.DeviceIoControl.IoControlCode )
|
|
|
|
{
|
|
|
|
case IOCCTL_RUN_NMI_CALLBACKS:
|
|
|
|
|
|
|
|
status = HandleNmiIOCTL( Irp );
|
|
|
|
|
|
|
|
if ( !NT_SUCCESS( status ) )
|
|
|
|
DEBUG_ERROR( "RunNmiCallbacks failed with status %lx", status );
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IOCTL_VALIDATE_DRIVER_OBJECTS:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The reason this function is run in a new thread and not the thread
|
|
|
|
* issuing the IOCTL is because ZwOpenDirectoryObject issues a
|
|
|
|
* user mode handle if called on the user mode thread calling DeviceIoControl.
|
|
|
|
* This is a problem because when we pass said handle to ObReferenceObjectByHandle
|
|
|
|
* it will issue a bug check under windows driver verifier.
|
|
|
|
*/
|
2023-08-20 07:46:02 +02:00
|
|
|
|
|
|
|
DEBUG_LOG( "irp addr: %p", ( void* )Irp );
|
|
|
|
|
2023-08-19 04:52:57 +02:00
|
|
|
status = PsCreateSystemThread(
|
|
|
|
&handle,
|
|
|
|
PROCESS_ALL_ACCESS,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
HandleValidateDriversIOCTL,
|
|
|
|
Irp
|
|
|
|
);
|
|
|
|
|
|
|
|
if ( !NT_SUCCESS( status ) )
|
2023-08-19 08:06:51 +02:00
|
|
|
{
|
2023-08-19 04:52:57 +02:00
|
|
|
DEBUG_ERROR( "Failed to start thread to validate system drivers" );
|
2023-08-19 08:06:51 +02:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Thread objects are a type of dispatcher object, meaning when they are freed
|
|
|
|
* its set to the signal state and any waiters will be signalled. This allows
|
|
|
|
* us to wait til our threads terminated and the IRP buffer has been either filled
|
|
|
|
* or left empty and then from there we can complete the IRP and return.
|
|
|
|
*/
|
|
|
|
status = ObReferenceObjectByHandle(
|
|
|
|
handle,
|
|
|
|
THREAD_ALL_ACCESS,
|
|
|
|
*PsThreadType,
|
|
|
|
KernelMode,
|
|
|
|
&thread,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
|
|
|
|
if ( !NT_SUCCESS( status ) )
|
|
|
|
{
|
|
|
|
DEBUG_ERROR( "ObReferenceObjectbyhandle failed with status %lx", status );
|
|
|
|
ZwClose( handle );
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2023-08-20 07:46:02 +02:00
|
|
|
/* KeWaitForSingleObject with infinite time must be called from IRQL <= APC_LEVEL */
|
|
|
|
PAGED_CODE();
|
|
|
|
DEBUG_LOG( "waiting for thread to finish" );
|
2023-08-19 08:06:51 +02:00
|
|
|
KeWaitForSingleObject( thread, Executive, KernelMode, FALSE, NULL );
|
2023-08-20 07:46:02 +02:00
|
|
|
DEBUG_LOG( "THREAD FINISHED" );
|
2023-08-19 04:52:57 +02:00
|
|
|
ZwClose( handle );
|
2023-08-19 08:06:51 +02:00
|
|
|
ObDereferenceObject( thread );
|
|
|
|
|
2023-08-19 06:37:53 +02:00
|
|
|
break;
|
2023-08-19 04:52:57 +02:00
|
|
|
|
2023-08-20 16:12:04 +02:00
|
|
|
case IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH:;
|
|
|
|
|
|
|
|
PDRIVER_INITIATION_INFORMATION information = ( PDRIVER_INITIATION_INFORMATION )Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
UpdateProtectedProcessId( information->protected_process_id );
|
|
|
|
break;
|
|
|
|
|
2023-08-20 17:04:53 +02:00
|
|
|
case IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE:
|
|
|
|
|
|
|
|
status = HandlePeriodicCallbackReportQueue(Irp);
|
|
|
|
|
|
|
|
if ( !NT_SUCCESS( status ) )
|
|
|
|
DEBUG_ERROR( "Failed to handle period callback report queue" );
|
|
|
|
|
|
|
|
break;
|
2023-08-20 16:12:04 +02:00
|
|
|
|
2023-08-19 04:52:57 +02:00
|
|
|
default:
|
|
|
|
DEBUG_ERROR( "Invalid IOCTL passed to driver" );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-08-19 08:06:51 +02:00
|
|
|
end:
|
2023-08-19 04:52:57 +02:00
|
|
|
Irp->IoStatus.Status = status;
|
2023-08-20 07:46:02 +02:00
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
2023-08-19 04:52:57 +02:00
|
|
|
return status;
|
2023-08-17 10:45:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS DeviceClose(
|
|
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
|
|
_In_ PIRP Irp
|
|
|
|
)
|
|
|
|
{
|
|
|
|
DEBUG_LOG( "Handle closed to DonnaAC" );
|
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
|
|
return Irp->IoStatus.Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS DeviceCreate(
|
|
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
|
|
_In_ PIRP Irp
|
|
|
|
)
|
|
|
|
{
|
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
|
|
return Irp->IoStatus.Status;
|
|
|
|
}
|