mirror-ac/driver/ioctl.c

287 lines
6.2 KiB
C
Raw Normal View History

2023-08-17 10:45:50 +02:00
#include "ioctl.h"
#include "common.h"
2023-08-19 04:52:57 +02:00
#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-26 14:07:06 +02:00
#include "pool.h"
2023-08-22 19:32:25 +02:00
#include "integrity.h"
2023-08-30 13:15:57 +02:00
#include "thread.h"
2023-09-02 10:54:04 +02:00
#include "queue.h"
2023-08-19 04:52:57 +02:00
2023-08-21 14:40:40 +02:00
#include "hv.h"
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-24 17:10:40 +02:00
BOOLEAN security_flag = FALSE;
/*
* The purpose of this is to prevent programs from opening a handle to our driver
* and trying to fuzz the IOCTL access or codes. This definitely isnt a perfect
* solution though... xD
*/
2023-09-01 18:45:06 +02:00
ReadProcessInitialisedConfigFlag( &security_flag );
2023-08-24 17:10:40 +02:00
if ( security_flag == FALSE &&
stack_location->Parameters.DeviceIoControl.IoControlCode != IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH )
2023-08-24 17:10:40 +02:00
goto end;
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
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();
2023-08-21 11:45:00 +02:00
2023-08-19 08:06:51 +02:00
KeWaitForSingleObject( thread, Executive, KernelMode, FALSE, NULL );
2023-08-21 11:45:00 +02:00
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:;
2023-09-02 10:54:04 +02:00
status = InitialiseProcessConfigOnProcessLaunch(Irp);
2023-08-24 15:12:49 +02:00
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "Failed to initialise driver config on proc launch with status %x", status );
goto end;
}
status = InitiateDriverCallbacks();
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "InitiateDriverCallbacks failed with status %x", status );
2023-08-20 16:12:04 +02:00
break;
2023-08-20 17:04:53 +02:00
case IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE:
2023-09-02 10:54:04 +02:00
status = HandlePeriodicGlobalReportQueueQuery(Irp);
2023-08-20 17:04:53 +02:00
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "Failed to handle period callback report queue" );
break;
2023-08-20 16:12:04 +02:00
2023-08-21 17:48:34 +02:00
case IOCTL_PERFORM_VIRTUALIZATION_CHECK:
status = PerformVirtualizationDetection( Irp );
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "PerformVirtualizationDetection failed with status %x", status );
break;
2023-08-22 10:51:52 +02:00
case IOCTL_ENUMERATE_HANDLE_TABLES:
/* can maybe implement this better so we can extract a status value */
EnumerateProcessListWithCallbackFunction(
EnumerateProcessHandles
);
break;
2023-08-22 19:32:25 +02:00
case IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS:
2023-08-31 18:42:38 +02:00
status = PsCreateSystemThread(
&handle,
PROCESS_ALL_ACCESS,
NULL,
NULL,
NULL,
RetrieveInMemoryModuleExecutableSections,
Irp
);
if ( !NT_SUCCESS( status ) )
{
DEBUG_ERROR( "Failed to start system thread to get executable regions" );
goto end;
}
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;
}
PAGED_CODE();
KeWaitForSingleObject( thread, Executive, KernelMode, FALSE, NULL );;
ZwClose( handle );
ObDereferenceObject( thread );
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "Failed to retrieve executable regions" );
2023-08-22 19:32:25 +02:00
break;
2023-08-23 14:14:20 +02:00
case IOCTL_REQUEST_TOTAL_MODULE_SIZE:
status = GetDriverImageSize( Irp );
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "Failed to retrieve driver image size" );
break;
2023-08-24 17:10:40 +02:00
case IOCTL_NOTIFY_DRIVER_ON_PROCESS_TERMINATION:
2023-08-24 15:12:49 +02:00
2023-09-01 18:45:06 +02:00
ClearProcessConfigOnProcessTermination();
2023-08-24 15:25:56 +02:00
UnregisterCallbacksOnProcessTermination();
2023-08-24 15:12:49 +02:00
break;
2023-08-28 17:00:52 +02:00
case IOCTL_SCAN_FOR_UNLINKED_PROCESS:
status = FindUnlinkedProcesses( Irp );
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "FindUNlinekdProcesses failed with status %x", status );
break;
2023-08-30 13:15:57 +02:00
case IOCTL_VALIDATE_KPRCB_CURRENT_THREAD:
ValidateKPCRBThreads( Irp );
break;
2023-09-01 13:46:31 +02:00
case IOCTL_PERFORM_INTEGRITY_CHECK:
status = VerifyInMemoryImageVsDiskImage();
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "VerifyInMemoryImageVsDisk failed with status %x", status );
break;
2023-09-02 15:47:15 +02:00
case IOCTL_DETECT_ATTACHED_THREADS:
DetectThreadsAttachedToProtectedProcess();
break;
2023-09-05 11:16:32 +02:00
case IOCTL_VALIDATE_PROCESS_LOADED_MODULE:
status = ValidateProcessLoadedModule( Irp );
if ( !NT_SUCCESS( status ) )
DEBUG_ERROR( "ValidateProcessLoadedModule failed with status %x", status );
break;
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" );
2023-08-30 15:23:04 +02:00
2023-09-02 10:54:04 +02:00
FreeGlobalReportQueueObjects();
2023-09-01 18:45:06 +02:00
ClearProcessConfigOnProcessTermination();
2023-08-30 18:29:44 +02:00
UnregisterCallbacksOnProcessTermination();
2023-08-30 15:23:04 +02:00
2023-08-17 10:45:50 +02:00
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return Irp->IoStatus.Status;
}
NTSTATUS DeviceCreate(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp
)
{
2023-08-21 11:45:00 +02:00
DEBUG_LOG( "Handle opened to DonnaAC" );
2023-08-17 10:45:50 +02:00
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return Irp->IoStatus.Status;
}