mirror-ac/driver/io.c

1246 lines
34 KiB
C
Raw Permalink Normal View History

#include "io.h"
2023-08-17 10:45:50 +02:00
2023-08-20 17:04:53 +02:00
#include "callbacks.h"
2024-08-04 08:30:31 +02:00
#include "containers/map.h"
2024-08-01 06:21:53 +02:00
#include "driver.h"
2024-08-04 08:30:31 +02:00
#include "hv.h"
#include "hw.h"
#include "imports.h"
2023-08-22 19:32:25 +02:00
#include "integrity.h"
2024-08-04 08:30:31 +02:00
#include "lib/stdlib.h"
2024-08-01 06:21:53 +02:00
#include "modules.h"
#include "pool.h"
#include "session.h"
2024-08-04 08:30:31 +02:00
#include "thread.h"
2024-07-22 12:43:09 +02:00
2023-12-13 05:06:27 +01:00
STATIC
NTSTATUS
DispatchApcOperation(_In_ PAPC_OPERATION_ID Operation);
2023-10-06 13:08:30 +02:00
#ifdef ALLOC_PRAGMA
2024-04-13 10:23:14 +02:00
# pragma alloc_text(PAGE, DispatchApcOperation)
# pragma alloc_text(PAGE, DeviceControl)
# pragma alloc_text(PAGE, DeviceClose)
# pragma alloc_text(PAGE, DeviceCreate)
2023-10-06 13:08:30 +02:00
#endif
#define IOCTL_RUN_NMI_CALLBACKS \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20001, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_VALIDATE_DRIVER_OBJECTS \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20002, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20004, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20005, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_PERFORM_VIRTUALIZATION_CHECK \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20006, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_ENUMERATE_HANDLE_TABLES \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20007, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20008, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_REQUEST_TOTAL_MODULE_SIZE \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20009, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_NOTIFY_DRIVER_ON_PROCESS_TERMINATION \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20010, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_SCAN_FOR_UNLINKED_PROCESS \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20011, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_PERFORM_INTEGRITY_CHECK \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20013, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_DETECT_ATTACHED_THREADS \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20014, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_VALIDATE_PROCESS_LOADED_MODULE \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20015, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_REQUEST_HARDWARE_INFORMATION \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20016, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_INITIATE_APC_OPERATION \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20017, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_CHECK_FOR_EPT_HOOK \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20018, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-29 17:20:32 +01:00
#define IOCTL_LAUNCH_DPC_STACKWALK \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20019, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-12-13 05:06:27 +01:00
#define IOCTL_VALIDATE_SYSTEM_MODULES \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20020, METHOD_BUFFERED, FILE_ANY_ACCESS)
2024-01-11 10:16:55 +01:00
#define IOCTL_INSERT_IRP_INTO_QUEUE \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20021, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_QUERY_DEFERRED_REPORTS \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20022, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_INITIATE_SHARED_MAPPING \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20023, METHOD_BUFFERED, FILE_ANY_ACCESS)
2024-02-14 17:16:27 +01:00
#define IOCTL_VALIDATE_PCI_DEVICES \
2024-04-13 10:23:14 +02:00
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20024, METHOD_BUFFERED, FILE_ANY_ACCESS)
2024-05-04 17:43:01 +02:00
#define IOCTL_VALIDATE_WIN32K_TABLES \
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20025, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023-09-28 18:10:01 +02:00
#define APC_OPERATION_STACKWALK 0x1
/*
* Basic cancel-safe IRP queue implementation. Stores pending IRPs in a list,
* allowing us to dequeue entries to send data back to user mode without being
* invoked by the user mode module via an io completion port.
*
* user mode program will automatically queue another irp when an irp completes,
* ensuring queue has a sufficient supply.
2024-02-11 15:34:28 +01:00
*
* note: maybe we should use a spinlock here? Dont really want competing threads
* sleeping. I think spinlock should be used here.
*/
2024-05-04 17:43:01 +02:00
STATIC
2024-01-11 10:16:55 +01:00
VOID
IrpQueueAcquireLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
2024-01-11 10:16:55 +01:00
{
KeAcquireGuardedMutex(&GetActiveSession()->lock);
2024-01-11 10:16:55 +01:00
}
2024-05-04 17:43:01 +02:00
STATIC
2024-01-11 10:16:55 +01:00
VOID
2024-02-11 15:34:28 +01:00
IrpQueueReleaseLock(_In_ PIO_CSQ Csq, _In_ KIRQL Irql)
{
KeReleaseGuardedMutex(&GetActiveSession()->lock);
}
2024-05-04 17:43:01 +02:00
STATIC
PIRP
IrpQueuePeekNextEntry(_In_ PIO_CSQ Csq, _In_ PIRP Irp, _In_ PVOID Context)
2024-01-11 10:16:55 +01:00
{
2024-04-13 10:23:14 +02:00
UNREFERENCED_PARAMETER(Context);
2024-08-04 08:30:31 +02:00
NT_ASSERT(Irp != NULL);
2024-04-13 10:23:14 +02:00
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
2024-05-05 12:42:22 +02:00
if (queue->irp_count == 0)
2024-04-13 10:23:14 +02:00
return NULL;
2024-04-13 10:23:14 +02:00
return CONTAINING_RECORD(queue->queue.Flink, IRP, Tail.Overlay.ListEntry);
2024-01-11 10:16:55 +01:00
}
2024-05-04 17:43:01 +02:00
STATIC
2024-01-11 10:16:55 +01:00
VOID
IrpQueueRemove(_In_ PIO_CSQ Csq, _In_ PIRP Irp)
2024-01-11 10:16:55 +01:00
{
2024-04-13 10:23:14 +02:00
UNREFERENCED_PARAMETER(Csq);
2024-05-05 12:42:22 +02:00
GetIrpQueueHead()->irp_count--;
2024-04-13 10:23:14 +02:00
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
}
2024-05-04 17:43:01 +02:00
STATIC
BOOLEAN
2024-05-05 13:07:05 +02:00
IrpQueueIsThereDeferredPackets(_In_ PIRP_QUEUE_HEAD Queue)
{
2024-04-13 10:23:14 +02:00
return Queue->deferred_reports.count > 0 ? TRUE : FALSE;
}
2024-05-04 17:43:01 +02:00
STATIC
PDEFERRED_REPORT
2024-05-05 13:07:05 +02:00
IrpQueueRemoveDeferredPacket(_In_ PIRP_QUEUE_HEAD Queue)
{
2024-04-13 10:23:14 +02:00
return RemoveHeadList(&Queue->deferred_reports.head);
}
2024-01-28 08:34:09 +01:00
STATIC
VOID
2024-05-05 13:07:05 +02:00
IrpQueueFreeDeferredPacket(_In_ PDEFERRED_REPORT Report)
2024-01-28 08:34:09 +01:00
{
2024-04-13 10:23:14 +02:00
ImpExFreePoolWithTag(Report->buffer, REPORT_POOL_TAG);
ImpExFreePoolWithTag(Report, REPORT_POOL_TAG);
2024-01-28 08:34:09 +01:00
}
2024-05-05 13:07:05 +02:00
FORCEINLINE
STATIC
UINT16
GetPacketType(_In_ PVOID Buffer)
{
PPACKET_HEADER header = (PPACKET_HEADER)Buffer;
return header->packet_type;
}
FORCEINLINE
STATIC
VOID
IncrementPacketMetics(_In_ PIRP_QUEUE_HEAD Queue, UINT16 Type)
{
2024-05-05 13:29:32 +02:00
switch (Type) {
case PACKET_TYPE_HEARTBEAT: Queue->total_heartbeats_completed++; break;
case PACKET_TYPE_REPORT: Queue->total_reports_completed++; break;
}
2024-05-05 13:07:05 +02:00
Queue->total_irps_completed++;
}
2024-05-04 17:43:01 +02:00
STATIC
NTSTATUS
2024-05-05 13:07:05 +02:00
IrpQueueCompleteDeferredPacket(_In_ PDEFERRED_REPORT Report, _In_ PIRP Irp)
{
2024-08-04 08:30:31 +02:00
NT_ASSERT(Report != NULL);
2024-08-01 06:21:53 +02:00
NTSTATUS status = ValidateIrpOutputBuffer(Irp, Report->buffer_size);
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
UINT16 type = GetPacketType(Report->buffer);
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
return status;
2024-05-05 13:07:05 +02:00
IncrementPacketMetics(queue, type);
2024-07-22 12:43:09 +02:00
IntCopyMemory(
2024-08-01 06:21:53 +02:00
Irp->AssociatedIrp.SystemBuffer,
Report->buffer,
Report->buffer_size);
2024-08-01 06:21:53 +02:00
Irp->IoStatus.Status = STATUS_SUCCESS;
2024-04-13 10:23:14 +02:00
Irp->IoStatus.Information = Report->buffer_size;
IofCompleteRequest(Irp, IO_NO_INCREMENT);
2024-05-05 13:07:05 +02:00
IrpQueueFreeDeferredPacket(Report);
2024-04-13 10:23:14 +02:00
return STATUS_SUCCESS;
}
2024-05-04 17:43:01 +02:00
STATIC
NTSTATUS
2024-05-05 13:07:05 +02:00
IrpQueueQueryPendingPackets(_In_ PIRP Irp)
{
2024-08-04 08:30:31 +02:00
NT_ASSERT(Irp != NULL);
2024-08-01 06:21:53 +02:00
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
2024-04-13 10:23:14 +02:00
PDEFERRED_REPORT report = NULL;
2024-08-01 06:21:53 +02:00
NTSTATUS status = STATUS_UNSUCCESSFUL;
KIRQL irql = 0;
2024-04-13 10:23:14 +02:00
/*
* Important we hold the lock before we call IsThereDeferredReport to
* prevent the race condition where in the period between when we get a
* TRUE result and another thread removes the last entry from the list.
* We then request a deferred report and will receive a null value
* leading to a bugcheck in the subsequent call to
* CompleteDeferredReport.
*/
KeAcquireGuardedMutex(&queue->deferred_reports.lock);
DEBUG_INFO("deferred packet count: %lx", queue->deferred_reports.count);
2024-04-13 10:23:14 +02:00
2024-05-05 13:07:05 +02:00
if (IrpQueueIsThereDeferredPackets(queue)) {
report = IrpQueueRemoveDeferredPacket(queue);
status = IrpQueueCompleteDeferredPacket(report, Irp);
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status)) {
2024-05-05 13:07:05 +02:00
IrpQueueFreeDeferredPacket(report);
2024-04-13 10:23:14 +02:00
goto end;
}
2024-04-13 10:23:14 +02:00
queue->deferred_reports.count--;
}
end:
KeReleaseGuardedMutex(&queue->deferred_reports.lock);
2024-04-13 10:23:14 +02:00
return status;
2024-01-11 10:16:55 +01:00
}
2024-05-04 17:43:01 +02:00
STATIC
2024-01-11 10:16:55 +01:00
VOID
IrpQueueInsert(_In_ PIO_CSQ Csq, _In_ PIRP Irp)
{
2024-04-13 10:23:14 +02:00
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
InsertTailList(&queue->queue, &Irp->Tail.Overlay.ListEntry);
2024-05-05 12:42:22 +02:00
queue->irp_count++;
}
2024-05-04 17:43:01 +02:00
STATIC
VOID
IrpQueueCompleteCancelledIrp(_In_ PIO_CSQ Csq, _In_ PIRP Irp)
{
2024-04-13 10:23:14 +02:00
UNREFERENCED_PARAMETER(Csq);
2024-08-01 06:21:53 +02:00
Irp->IoStatus.Status = STATUS_CANCELLED;
2024-04-13 10:23:14 +02:00
Irp->IoStatus.Information = 0;
ImpIofCompleteRequest(Irp, IO_NO_INCREMENT);
}
2024-05-04 17:43:01 +02:00
STATIC
PDEFERRED_REPORT
2024-05-05 13:07:05 +02:00
IrpQueueAllocateDeferredPacket(_In_ PVOID Buffer, _In_ UINT32 BufferSize)
2024-01-11 10:16:55 +01:00
{
2024-08-04 08:30:31 +02:00
NT_ASSERT(Buffer != NULL);
NT_ASSERT(BufferSize != 0);
2024-04-13 10:23:14 +02:00
PDEFERRED_REPORT report = ImpExAllocatePool2(
2024-08-01 06:21:53 +02:00
POOL_FLAG_NON_PAGED,
sizeof(DEFERRED_REPORT),
REPORT_POOL_TAG);
2024-01-11 10:16:55 +01:00
2024-04-13 10:23:14 +02:00
if (!report)
return NULL;
2024-01-11 10:16:55 +01:00
2024-08-01 06:21:53 +02:00
report->buffer = Buffer;
2024-04-13 10:23:14 +02:00
report->buffer_size = BufferSize;
return report;
}
2024-07-13 07:43:50 +02:00
#define MAX_DEFERRED_REPORTS_COUNT 256
2024-02-09 08:41:35 +01:00
2024-05-04 17:43:01 +02:00
STATIC
VOID
2024-08-01 06:21:53 +02:00
IrpQueueDeferPacket(
_In_ PIRP_QUEUE_HEAD Queue, _In_ PVOID Buffer, _In_ UINT32 BufferSize)
{
2024-08-04 08:30:31 +02:00
NT_ASSERT(Queue != NULL);
NT_ASSERT(Buffer != NULL);
2024-04-13 10:23:14 +02:00
PDEFERRED_REPORT report = NULL;
/*
* arbitrary number, if we ever do have 100 deferred reports, theres
* probably a catastrophic error somewhere else
*/
if (Queue->deferred_reports.count > MAX_DEFERRED_REPORTS_COUNT) {
ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG);
return;
}
2024-01-11 10:16:55 +01:00
2024-05-05 13:07:05 +02:00
report = IrpQueueAllocateDeferredPacket(Buffer, BufferSize);
2024-04-13 10:23:14 +02:00
if (!report)
return;
KeAcquireGuardedMutex(&Queue->deferred_reports.lock);
2024-04-13 10:23:14 +02:00
InsertTailList(&Queue->deferred_reports.head, &report->list_entry);
Queue->deferred_reports.count++;
KeReleaseGuardedMutex(&Queue->deferred_reports.lock);
}
2024-02-14 17:56:03 +01:00
/*
* takes ownership of the buffer, and regardless of the outcome will free it.
*
* IMPORTANT: All report buffers must be allocated in non paged memory.
*/
2024-05-11 17:27:18 +02:00
STATIC
NTSTATUS
2024-05-05 13:07:05 +02:00
IrpQueueCompletePacket(_In_ PVOID Buffer, _In_ ULONG BufferSize)
{
2024-08-01 06:21:53 +02:00
NTSTATUS status = STATUS_UNSUCCESSFUL;
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
PIRP irp = IoCsqRemoveNextIrp(&queue->csq, NULL);
UINT16 type = GetPacketType(Buffer);
2024-04-13 10:23:14 +02:00
/*
* If no irps are available in our queue, lets store it in a deferred
* reports list which should be checked each time we insert a new irp
* into the queue.
*/
if (!irp) {
2024-05-05 13:07:05 +02:00
IrpQueueDeferPacket(queue, Buffer, BufferSize);
2024-04-13 10:23:14 +02:00
return STATUS_SUCCESS;
}
2024-04-13 10:23:14 +02:00
status = ValidateIrpOutputBuffer(irp, BufferSize);
2024-04-13 10:23:14 +02:00
/*
* Not sure how we should handle this, for now lets just free the buffer
* and return a status.
*/
if (!NT_SUCCESS(status)) {
ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG);
2024-08-01 06:21:53 +02:00
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
2024-04-13 10:23:14 +02:00
irp->IoStatus.Information = 0;
ImpIofCompleteRequest(irp, IO_NO_INCREMENT);
2024-02-09 08:41:35 +01:00
return status;
2024-04-13 10:23:14 +02:00
}
2024-05-05 13:07:05 +02:00
IncrementPacketMetics(queue, type);
2024-08-01 06:21:53 +02:00
irp->IoStatus.Status = STATUS_SUCCESS;
2024-04-13 10:23:14 +02:00
irp->IoStatus.Information = BufferSize;
2024-07-22 12:43:09 +02:00
IntCopyMemory(irp->AssociatedIrp.SystemBuffer, Buffer, BufferSize);
2024-04-13 10:23:14 +02:00
ImpExFreePoolWithTag(Buffer, REPORT_POOL_TAG);
ImpIofCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
2024-05-11 17:27:18 +02:00
/*
2024-05-15 11:48:09 +02:00
* Due to the fact that many reporting structures are holding a mutex when
* scheduling a report packet, we need an alternative queueing option from DPCs
* and spinlocks. Here we will use an array of work items (
*
* Hmm this is an interesting issue. Not sure how we shall resolve this, for now
* this works well enough.
2024-05-11 17:27:18 +02:00
*/
VOID
IrpQueueSchedulePacket(_In_ PVOID Buffer, _In_ UINT32 BufferLength)
{
IrpQueueCompletePacket(Buffer, BufferLength);
2024-05-11 17:27:18 +02:00
}
2024-05-05 14:00:08 +02:00
STATIC
VOID
2024-05-05 13:07:05 +02:00
IrpQueueFreeDeferredPackets()
{
2024-08-01 06:21:53 +02:00
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
2024-04-13 10:23:14 +02:00
PDEFERRED_REPORT report = NULL;
2024-08-01 06:21:53 +02:00
KIRQL irql = 0;
2024-04-13 10:23:14 +02:00
/* just in case... */
KeAcquireGuardedMutex(&queue->deferred_reports.lock);
2024-05-05 13:07:05 +02:00
while (IrpQueueIsThereDeferredPackets(queue)) {
report = IrpQueueRemoveDeferredPacket(queue);
IrpQueueFreeDeferredPacket(report);
2024-04-13 10:23:14 +02:00
}
KeReleaseGuardedMutex(&queue->deferred_reports.lock);
}
NTSTATUS
IrpQueueInitialise()
{
2024-08-01 06:21:53 +02:00
NTSTATUS status = STATUS_UNSUCCESSFUL;
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
2024-04-13 10:23:14 +02:00
KeInitializeGuardedMutex(&queue->lock);
KeInitializeGuardedMutex(&queue->deferred_reports.lock);
2024-04-13 10:23:14 +02:00
InitializeListHead(&queue->queue);
InitializeListHead(&queue->deferred_reports.head);
2024-08-01 06:21:53 +02:00
status = IoCsqInitialize(
&queue->csq,
IrpQueueInsert,
IrpQueueRemove,
IrpQueuePeekNextEntry,
IrpQueueAcquireLock,
IrpQueueReleaseLock,
IrpQueueCompleteCancelledIrp);
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR("IoCsqInitialize failed with status %x", status);
return status;
2024-01-11 10:16:55 +01:00
}
VOID
2024-08-01 06:21:53 +02:00
SharedMappingWorkRoutine(
_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
{
2024-08-01 06:21:53 +02:00
NTSTATUS status = STATUS_UNSUCCESSFUL;
HANDLE handle = NULL;
PSHARED_MAPPING state = (PSHARED_MAPPING)Context;
2024-04-13 10:23:14 +02:00
InterlockedIncrement(&state->work_item_status);
2024-08-01 06:21:53 +02:00
DEBUG_VERBOSE(
"SharedMapping work routine called. OperationId: %lx",
state->kernel_buffer->operation_id);
2024-04-13 10:23:14 +02:00
switch (state->kernel_buffer->operation_id) {
case ssRunNmiCallbacks:
2024-04-13 10:23:14 +02:00
DEBUG_INFO("SHARED_STATE_OPERATION_ID: RunNmiCallbacks Received.");
2024-04-13 10:23:14 +02:00
status = HandleNmiIOCTL();
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR("RunNmiCallbacks failed with status %lx", status);
2024-04-13 10:23:14 +02:00
break;
2024-04-13 10:23:14 +02:00
case ssValidateDriverObjects:
2024-04-13 10:23:14 +02:00
DEBUG_INFO(
"SHARED_STATE_OPERATION_ID: ValidateDriverObjects Received.");
2024-08-01 06:21:53 +02:00
status = ImpPsCreateSystemThread(
&handle,
PROCESS_ALL_ACCESS,
NULL,
NULL,
NULL,
HandleValidateDriversIOCTL,
NULL);
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsCreateSystemThread failed with status %x", status);
goto end;
}
2024-04-13 10:23:14 +02:00
ImpZwClose(handle);
break;
2024-04-13 10:23:14 +02:00
case ssEnumerateHandleTables:
2024-04-13 10:23:14 +02:00
DEBUG_INFO("SHARED_STATE_OPERATION_ID: EnumerateHandleTables Received");
2024-04-13 10:23:14 +02:00
/* can maybe implement this better so we can extract a status
* value */
2024-06-11 13:41:55 +02:00
RtlHashmapEnumerate(GetProcessHashmap(), EnumerateProcessHandles, NULL);
2024-04-13 10:23:14 +02:00
break;
2024-04-13 10:23:14 +02:00
case ssScanForUnlinkedProcesses:
// DEBUG_INFO(
// "SHARED_STATE_OPERATION_ID: ScanForUnlinkedProcesses Received");
// status = FindUnlinkedProcesses();
// if (!NT_SUCCESS(status))
// DEBUG_ERROR("FindUnlinkedProcesses failed with status %x",
// status);
2024-04-13 10:23:14 +02:00
break;
2024-04-13 10:23:14 +02:00
case ssPerformModuleIntegrityCheck:
2024-04-13 10:23:14 +02:00
DEBUG_INFO("SHARED_STATE_OPERATION_ID: PerformIntegrityCheck Received");
2024-04-13 10:23:14 +02:00
status = ValidateOurDriverImage();
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"VerifyInMemoryImageVsDiskImage failed with status %x",
status);
2024-04-13 10:23:14 +02:00
break;
2024-04-13 10:23:14 +02:00
case ssScanForAttachedThreads:
2024-04-13 10:23:14 +02:00
DEBUG_INFO(
"SHARED_STATE_OPERATION_ID: ScanForAttachedThreads Received");
2024-04-13 10:23:14 +02:00
DetectThreadsAttachedToProtectedProcess();
2024-04-13 10:23:14 +02:00
break;
2024-04-13 10:23:14 +02:00
case ssScanForEptHooks:
2024-04-13 10:23:14 +02:00
DEBUG_INFO("SHARED_STATE_OPERATION_ID: ScanForEptHooks Received");
2024-04-13 10:23:14 +02:00
status = DetectEptHooksInKeyFunctions();
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"DetectEpthooksInKeyFunctions failed with status %x",
status);
2024-04-13 10:23:14 +02:00
break;
2024-04-13 10:23:14 +02:00
case ssInitiateDpcStackwalk:
2024-04-13 10:23:14 +02:00
DEBUG_INFO("SHARED_STATE_OPERATION_ID Received");
2024-04-13 10:23:14 +02:00
status = DispatchStackwalkToEachCpuViaDpc();
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR(
"DispatchStackwalkToEachCpuViaDpc failed with status %x",
status);
2024-04-13 10:23:14 +02:00
break;
2024-04-13 10:23:14 +02:00
case ssValidateSystemModules:
2024-04-13 10:23:14 +02:00
DEBUG_INFO("SHARED_STATE_OPERATION_ID: ValidateSystemModules Received");
2024-04-13 10:23:14 +02:00
status = SystemModuleVerificationDispatcher();
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR("ValidateSystemModules failed with status %x", status);
2024-04-13 10:23:14 +02:00
break;
2024-05-04 17:43:01 +02:00
case ssValidateWin32kDispatchTables:
DEBUG_INFO(
"SHARED_STATE_OPERATION_ID: ValidateWin32kDispatchTables Received");
status = ValidateWin32kDispatchTables();
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"ValidateWin32kDispatchTables failed with status %x",
status);
2024-05-04 17:43:01 +02:00
break;
2024-04-13 10:23:14 +02:00
default: DEBUG_ERROR("Invalid SHARED_STATE_OPERATION_ID Received");
}
end:
2024-04-13 10:23:14 +02:00
InterlockedDecrement(&state->work_item_status);
}
/* again, we want to run our routine at apc level not dispatch level */
VOID
2024-08-01 06:21:53 +02:00
SharedMappingDpcRoutine(
_In_ PKDPC Dpc,
_In_opt_ PVOID DeferredContext,
_In_opt_ PVOID SystemArgument1,
_In_opt_ PVOID SystemArgument2)
{
2024-04-13 10:23:14 +02:00
PSHARED_MAPPING mapping = (PSHARED_MAPPING)DeferredContext;
2024-04-13 10:23:14 +02:00
if (!mapping->active || mapping->work_item_status)
return;
2024-04-13 10:23:14 +02:00
IoQueueWorkItem(
2024-08-01 06:21:53 +02:00
mapping->work_item,
SharedMappingWorkRoutine,
NormalWorkQueue,
mapping);
}
#define REPEAT_TIME_15_SEC 30000
VOID
SharedMappingTerminate()
{
2024-04-13 10:23:14 +02:00
PSHARED_MAPPING mapping = GetSharedMappingConfig();
2024-04-13 10:23:14 +02:00
if (!mapping->active)
return;
2024-04-13 10:23:14 +02:00
while (mapping->work_item_status)
YieldProcessor();
2024-08-01 06:21:53 +02:00
mapping->active = FALSE;
2024-04-13 10:23:14 +02:00
mapping->user_buffer = NULL;
2024-08-01 06:21:53 +02:00
mapping->size = 0;
2024-04-13 10:23:14 +02:00
KeCancelTimer(&mapping->timer);
IoFreeWorkItem(mapping->work_item);
IoFreeMdl(mapping->mdl);
ExFreePoolWithTag(mapping->kernel_buffer, POOL_TAG_INTEGRITY);
2024-04-13 10:23:14 +02:00
RtlZeroMemory(mapping, sizeof(SHARED_MAPPING));
}
STATIC
NTSTATUS
SharedMappingInitialiseTimer(_In_ PSHARED_MAPPING Mapping)
{
2024-04-13 10:23:14 +02:00
LARGE_INTEGER due_time = {0};
2024-08-01 06:21:53 +02:00
LONG period = 0;
2024-05-04 17:43:01 +02:00
due_time.QuadPart = -ABSOLUTE(SECONDS(30));
2024-04-13 10:23:14 +02:00
Mapping->work_item = IoAllocateWorkItem(GetDriverDeviceObject());
2024-04-13 10:23:14 +02:00
if (!Mapping->work_item) {
DEBUG_ERROR("IoAllocateWorkItem failed with no status.");
return STATUS_INSUFFICIENT_RESOURCES;
}
2024-04-13 10:23:14 +02:00
KeInitializeDpc(&Mapping->timer_dpc, SharedMappingDpcRoutine, Mapping);
KeInitializeTimer(&Mapping->timer);
KeSetTimerEx(
2024-08-01 06:21:53 +02:00
&Mapping->timer,
due_time,
REPEAT_TIME_15_SEC,
&Mapping->timer_dpc);
2024-04-13 10:23:14 +02:00
DEBUG_VERBOSE("Initialised shared mapping event timer.");
return STATUS_SUCCESS;
}
2024-05-04 17:43:01 +02:00
STATIC
VOID
2024-08-01 06:21:53 +02:00
InitSharedMappingStructure(
_Out_ PSHARED_MAPPING Mapping,
_In_ PVOID KernelBuffer,
_In_ PVOID UserBuffer,
_In_ PMDL Mdl)
2024-05-04 17:43:01 +02:00
{
2024-08-01 06:21:53 +02:00
Mapping->kernel_buffer = (PSHARED_STATE)KernelBuffer;
Mapping->user_buffer = UserBuffer;
Mapping->mdl = Mdl;
Mapping->size = PAGE_SIZE;
Mapping->active = TRUE;
2024-05-04 17:43:01 +02:00
Mapping->work_item_status = FALSE;
}
STATIC
NTSTATUS
SharedMappingInitialise(_In_ PIRP Irp)
{
2024-08-01 06:21:53 +02:00
NTSTATUS status = STATUS_UNSUCCESSFUL;
PMDL mdl = NULL;
PSHARED_MAPPING mapping = NULL;
2024-04-13 10:23:14 +02:00
PSHARED_MAPPING_INIT mapping_init = NULL;
2024-08-01 06:21:53 +02:00
PEPROCESS process = NULL;
PVOID buffer = NULL;
PVOID user_buffer = NULL;
2024-04-13 10:23:14 +02:00
mapping = GetSharedMappingConfig();
2024-04-13 10:23:14 +02:00
/* TODO: need to copy these out */
status = ValidateIrpOutputBuffer(Irp, sizeof(SHARED_MAPPING_INIT));
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("ValidateIrpOutputBuffer failed with status %x", status);
return status;
}
/*
* remember that ExAllocatePool2 zeroes the allocation, so no need to
* zero
*/
buffer =
ExAllocatePool2(POOL_FLAG_NON_PAGED, PAGE_SIZE, POOL_TAG_INTEGRITY);
if (!buffer)
return STATUS_INSUFFICIENT_RESOURCES;
mdl = IoAllocateMdl(buffer, PAGE_SIZE, FALSE, FALSE, NULL);
if (!mdl) {
DEBUG_ERROR("IoAllocateMdl failed with no status");
ExFreePoolWithTag(buffer, POOL_TAG_INTEGRITY);
return STATUS_INSUFFICIENT_RESOURCES;
}
MmBuildMdlForNonPagedPool(mdl);
__try {
2024-08-01 06:21:53 +02:00
user_buffer = MmMapLockedPagesSpecifyCache(
mdl,
UserMode,
MmCached,
NULL,
FALSE,
NormalPagePriority | MdlMappingNoExecute);
2024-04-13 10:23:14 +02:00
}
__except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"MmMapLockedPagesSpecifyCache failed with status %x",
status);
2024-04-13 10:23:14 +02:00
IoFreeMdl(mdl);
ExFreePoolWithTag(buffer, POOL_TAG_INTEGRITY);
return status;
}
2024-05-04 17:43:01 +02:00
InitSharedMappingStructure(mapping, buffer, user_buffer, mdl);
2024-04-13 10:23:14 +02:00
SharedMappingInitialiseTimer(mapping);
2024-04-13 10:23:14 +02:00
mapping_init = (PSHARED_MAPPING_INIT)Irp->AssociatedIrp.SystemBuffer;
mapping_init->buffer = user_buffer;
2024-08-01 06:21:53 +02:00
mapping_init->size = PAGE_SIZE;
2024-04-13 10:23:14 +02:00
return status;
}
2023-09-28 18:10:01 +02:00
STATIC
2023-10-05 08:27:17 +02:00
NTSTATUS
2023-12-13 05:06:27 +01:00
DispatchApcOperation(_In_ PAPC_OPERATION_ID Operation)
2023-09-28 18:10:01 +02:00
{
2024-04-13 10:23:14 +02:00
PAGED_CODE();
2023-10-09 20:19:51 +02:00
2024-04-13 10:23:14 +02:00
NTSTATUS status = STATUS_UNSUCCESSFUL;
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
DEBUG_VERBOSE("Dispatching APC Operation...");
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
switch (Operation->operation_id) {
case APC_OPERATION_STACKWALK:
2023-09-28 18:10:01 +02:00
2024-08-01 06:21:53 +02:00
DEBUG_INFO(
"Initiating APC stackwalk operation with operation id %i",
Operation->operation_id);
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
status = ValidateThreadsViaKernelApc();
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"ValidateThreadsViaKernelApc failed with status %x",
status);
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
return status;
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
default:
DEBUG_WARNING("Invalid operation ID passed");
return STATUS_INVALID_PARAMETER;
}
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
return STATUS_SUCCESS;
2023-09-28 18:10:01 +02:00
}
2023-09-27 15:10:12 +02:00
2023-11-09 08:30:59 +01:00
/*
* Obviously, its important we check that the input and output buffer sizes for
* each IRP is big enough to hold the incoming and outgoing information.
2023-12-13 05:06:27 +01:00
*
* Another important thing to note is that the windows IO manager will only zero
* out the size of the input buffer. Given that we use METHOD_BUFFERED for all
* communication, the input and output buffer are the same, with the size used
* being that of the greatest buffer passed to DeviceIoControl. The IO manager
* will then zero our the buffer to the size of the input buffer, so if the
* output buffer is larger then the input buffer there will be uninitialised
* memory in the buffer so we must zero out the buffer to the length of the
* output buffer.
2023-12-13 05:06:27 +01:00
*
* We then set the IoStatus.Information field to the size of the buffer we are
* passing back. If we don't do this and we allocate an output buffer of size
* 0x1000, yet only use 0x100 bytes, the user mode apps output buffer will
* receive 0x100 bytes + 0x900 bytes of uninitialised memory which is an
* information leak.
2023-12-13 05:06:27 +01:00
*/
2023-11-09 08:30:59 +01:00
NTSTATUS
2023-12-13 05:06:27 +01:00
ValidateIrpOutputBuffer(_In_ PIRP Irp, _In_ ULONG RequiredSize)
2023-11-09 08:30:59 +01:00
{
2024-04-13 10:23:14 +02:00
if (!Irp || !RequiredSize)
return STATUS_INVALID_PARAMETER;
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
PIO_STACK_LOCATION io = IoGetCurrentIrpStackLocation(Irp);
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
if (!io)
return STATUS_UNSUCCESSFUL;
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
if (io->Parameters.DeviceIoControl.OutputBufferLength < RequiredSize)
return STATUS_BUFFER_TOO_SMALL;
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
RtlSecureZeroMemory(Irp->AssociatedIrp.SystemBuffer, RequiredSize);
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
Irp->IoStatus.Information = RequiredSize;
2023-11-09 12:11:02 +01:00
2024-04-13 10:23:14 +02:00
return STATUS_SUCCESS;
2023-11-09 08:30:59 +01:00
}
/*
2023-12-13 05:06:27 +01:00
* Here we just check that the input buffers size matches the expected size..
* It isnt a very secure check but we can work on that later...
*/
2023-11-09 08:30:59 +01:00
NTSTATUS
2023-12-13 05:06:27 +01:00
ValidateIrpInputBuffer(_In_ PIRP Irp, _In_ ULONG RequiredSize)
2023-11-09 08:30:59 +01:00
{
2024-04-13 10:23:14 +02:00
if (!Irp || !RequiredSize)
return STATUS_INVALID_PARAMETER;
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
PIO_STACK_LOCATION io = IoGetCurrentIrpStackLocation(Irp);
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
if (!io)
return STATUS_UNSUCCESSFUL;
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
if (io->Parameters.DeviceIoControl.InputBufferLength != RequiredSize)
return STATUS_INVALID_BUFFER_SIZE;
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
return STATUS_SUCCESS;
2023-11-09 08:30:59 +01:00
}
2023-10-05 08:27:17 +02:00
NTSTATUS
2024-01-13 22:33:57 +01:00
DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
2023-08-17 10:45:50 +02:00
{
2024-04-13 10:23:14 +02:00
PAGED_CODE();
2023-12-13 05:06:27 +01:00
2024-08-01 06:21:53 +02:00
NTSTATUS status = STATUS_SUCCESS;
2024-04-13 10:23:14 +02:00
PIO_STACK_LOCATION stack_location = IoGetCurrentIrpStackLocation(Irp);
2024-08-01 06:21:53 +02:00
HANDLE handle = NULL;
PKTHREAD thread = NULL;
BOOLEAN security_flag = FALSE;
2024-03-04 05:28:06 +01:00
2024-04-13 10:23:14 +02:00
/*
* LMAO
*/
SessionIsActive(&security_flag);
2023-08-19 04:52:57 +02:00
2024-04-13 10:23:14 +02:00
if (security_flag == FALSE &&
stack_location->Parameters.DeviceIoControl.IoControlCode !=
IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH) {
status = STATUS_ACCESS_DENIED;
goto end;
}
2023-08-19 04:52:57 +02:00
2024-04-13 10:23:14 +02:00
switch (stack_location->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_RUN_NMI_CALLBACKS:
2023-08-19 04:52:57 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_RUN_NMI_CALLBACKS Received.");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
status = HandleNmiIOCTL(Irp);
2023-08-19 04:52:57 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR("RunNmiCallbacks failed with status %lx", status);
2023-08-19 04:52:57 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-08-20 07:46:02 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_VALIDATE_DRIVER_OBJECTS:
2023-08-19 04:52:57 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_VALIDATE_DRIVER_OBJECTS Received.");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
/*
* 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-19 08:06:51 +02:00
2024-08-01 06:21:53 +02:00
status = ImpPsCreateSystemThread(
&handle,
PROCESS_ALL_ACCESS,
NULL,
NULL,
NULL,
HandleValidateDriversIOCTL,
NULL);
2023-08-21 11:45:00 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsCreateSystemThread failed with status %x", status);
goto end;
}
2023-08-19 08:06:51 +02:00
2024-04-13 10:23:14 +02:00
ImpZwClose(handle);
break;
2023-08-24 15:12:49 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH:;
2023-10-05 08:27:17 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_NOTIFY_DRIVER_ON_PROCESS_LAUNCH Received");
2024-01-11 10:16:55 +01:00
2024-04-13 10:23:14 +02:00
status = SessionInitialise(Irp);
2024-01-11 10:16:55 +01:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("InitialiseSession failed with status %x", status);
goto end;
}
2024-01-11 10:16:55 +01:00
2024-04-13 10:23:14 +02:00
status = RegisterProcessObCallbacks();
2023-09-27 06:22:14 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR("EnableObCallbacks failed with status %x", status);
2023-09-27 06:22:14 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-08-20 17:04:53 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE:
2023-08-20 17:04:53 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_HANDLE_REPORTS_IN_CALLBACK_QUEUE Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
status = QueryActiveApcContextsForCompletion();
2023-08-20 16:12:04 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR(
"QueryActiveApcContextsForCompletion failed with status %x",
status);
2023-08-21 17:48:34 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-08-21 17:48:34 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_PERFORM_VIRTUALIZATION_CHECK:
2023-10-05 08:27:17 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_PERFORM_VIRTUALIZATION_CHECK Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
status = PerformVirtualizationDetection(Irp);
2023-08-22 10:51:52 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"PerformVirtualizationDetection failed with status %x",
status);
2023-08-22 10:51:52 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-08-22 19:32:25 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_ENUMERATE_HANDLE_TABLES:
2023-08-31 18:42:38 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_ENUMERATE_HANDLE_TABLES Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
/* can maybe implement this better so we can extract a status
* value */
2024-06-11 13:41:55 +02:00
RtlHashmapEnumerate(GetProcessHashmap(), EnumerateProcessHandles, NULL);
2023-08-31 18:42:38 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-08-31 18:42:38 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS:
2023-08-31 18:42:38 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_VERBOSE("IOCTL_RETRIEVE_MODULE_EXECUTABLE_REGIONS Received");
2024-08-01 06:21:53 +02:00
status = ImpPsCreateSystemThread(
&handle,
PROCESS_ALL_ACCESS,
NULL,
NULL,
NULL,
RetrieveInMemoryModuleExecutableSections,
Irp);
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsCreateSystemThread failed with status %x", status);
goto end;
}
2023-08-31 18:42:38 +02:00
2024-08-01 06:21:53 +02:00
status = ImpObReferenceObjectByHandle(
handle,
THREAD_ALL_ACCESS,
*PsThreadType,
KernelMode,
&thread,
NULL);
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status)) {
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"ObReferenceObjectbyhandle failed with status %lx",
status);
2024-04-13 10:23:14 +02:00
ImpZwClose(handle);
goto end;
}
2023-08-22 19:32:25 +02:00
2024-04-13 10:23:14 +02:00
ImpKeWaitForSingleObject(thread, Executive, KernelMode, FALSE, NULL);
2023-08-23 14:14:20 +02:00
2024-04-13 10:23:14 +02:00
ImpZwClose(handle);
ImpObDereferenceObject(thread);
2023-08-23 14:14:20 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-08-23 14:14:20 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_REQUEST_TOTAL_MODULE_SIZE:
2023-08-24 15:12:49 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_REQUEST_TOTAL_MODULE_SIZE Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
status = GetDriverImageSize(Irp);
2023-08-24 15:12:49 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR("GetDriverImageSize failed with status %x", status);
2023-08-24 15:12:49 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-08-28 17:00:52 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_NOTIFY_DRIVER_ON_PROCESS_TERMINATION:
2023-08-28 17:00:52 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_NOTIFY_DRIVER_ON_PROCESS_TERMINATION Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
SessionTerminate();
UnregisterProcessObCallbacks();
2023-08-28 17:00:52 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-08-28 17:00:52 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_SCAN_FOR_UNLINKED_PROCESS:
2023-08-30 13:15:57 +02:00
// DEBUG_INFO("IOCTL_SCAN_FOR_UNLINKED_PROCESS Received");
2023-12-23 19:52:55 +01:00
// status = FindUnlinkedProcesses();
2023-08-30 13:15:57 +02:00
// if (!NT_SUCCESS(status))
// DEBUG_ERROR("FindUnlinkedProcesses failed with status %x",
// status);
2023-08-30 13:15:57 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-09-01 13:46:31 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_PERFORM_INTEGRITY_CHECK:
2023-09-01 13:46:31 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_PERFORM_INTEGRITY_CHECK Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
status = ValidateOurDriverImage();
2023-09-01 13:46:31 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"VerifyInMemoryImageVsDiskImage failed with status %x",
status);
2023-09-02 15:47:15 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-09-02 15:47:15 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_DETECT_ATTACHED_THREADS:
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_DETECT_ATTACHED_THREADS Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
DetectThreadsAttachedToProtectedProcess();
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
break;
2023-09-02 15:47:15 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_VALIDATE_PROCESS_LOADED_MODULE:
2023-09-05 11:16:32 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_VALIDATE_PROCESS_LOADED_MODULE Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
status = ValidateProcessLoadedModule(Irp);
2023-09-05 11:16:32 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"ValidateProcessLoadedModule failed with status %x",
status);
2023-09-05 11:16:32 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-09-05 11:16:32 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_REQUEST_HARDWARE_INFORMATION:;
2023-09-07 19:49:36 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_REQUEST_HARDWARE_INFORMATION Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
PSYSTEM_INFORMATION system_information =
GetDriverConfigSystemInformation();
2023-09-07 19:49:36 +02:00
2024-04-13 10:23:14 +02:00
status = ValidateIrpOutputBuffer(Irp, sizeof(SYSTEM_INFORMATION));
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status)) {
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"ValidateIrpOutputBuffer failed with status %x",
status);
2024-04-13 10:23:14 +02:00
goto end;
}
2023-11-09 08:30:59 +01:00
2024-04-13 10:23:14 +02:00
Irp->IoStatus.Information = sizeof(SYSTEM_INFORMATION);
2023-09-07 19:49:36 +02:00
2024-08-01 06:21:53 +02:00
IntCopyMemory(
Irp->AssociatedIrp.SystemBuffer,
system_information,
sizeof(SYSTEM_INFORMATION));
2023-09-07 19:49:36 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-09-07 19:49:36 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_INITIATE_APC_OPERATION:;
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_INITIATE_APC_OPERATION Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
PAPC_OPERATION_ID operation =
(PAPC_OPERATION_ID)Irp->AssociatedIrp.SystemBuffer;
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
status = DispatchApcOperation(operation);
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR("DispatchApcOperation failed with status %x", status);
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_CHECK_FOR_EPT_HOOK:
2023-10-06 09:02:10 +02:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_CHECK_FOR_EPT_HOOK Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
status = DetectEptHooksInKeyFunctions();
2023-10-06 09:02:10 +02:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"DetectEpthooksInKeyFunctions failed with status %x",
status);
2023-10-06 09:02:10 +02:00
2024-04-13 10:23:14 +02:00
break;
2023-09-28 18:10:01 +02:00
2024-04-13 10:23:14 +02:00
case IOCTL_VALIDATE_SYSTEM_MODULES:
2023-10-30 12:57:24 +01:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_VALIDATE_SYSTEM_MODULES Received");
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
status = SystemModuleVerificationDispatcher();
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR("ValidateSystemModules failed with status %x", status);
2023-10-30 12:57:24 +01:00
2024-04-13 10:23:14 +02:00
break;
2023-10-30 12:57:24 +01:00
2024-04-13 10:23:14 +02:00
case IOCTL_LAUNCH_DPC_STACKWALK:
2023-12-29 17:20:32 +01:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_LAUNCH_DPC_STACKWALK Received");
2023-12-29 17:20:32 +01:00
2024-04-13 10:23:14 +02:00
status = DispatchStackwalkToEachCpuViaDpc();
2023-12-29 17:20:32 +01:00
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
DEBUG_ERROR(
"DispatchStackwalkToEachCpuViaDpc failed with status %x",
status);
2023-12-29 17:20:32 +01:00
2024-04-13 10:23:14 +02:00
break;
2023-12-29 17:20:32 +01:00
2024-04-13 10:23:14 +02:00
case IOCTL_INSERT_IRP_INTO_QUEUE:;
2024-01-11 10:16:55 +01:00
2024-04-13 10:23:14 +02:00
// DEBUG_INFO("IOCTL_INSERT_IRP_INTO_QUEUE Received");
2024-01-11 10:16:55 +01:00
2024-04-13 10:23:14 +02:00
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
2024-04-13 10:23:14 +02:00
/*
* Given the nature of the Windows IO subsystem and the
* cancel-safe queue implementation we use, we need to query for
* deferred reports before insert an irp into the queue. The
* reason for this is the cancel-safe queue will automically
* mark the irp as pending, so if we then use that irp to return
* a deferred report and return success here verifier has a lil
* cry.
*/
2024-04-13 10:23:14 +02:00
/* before we queue our IRP, check if we can complete a deferred
* report */
2024-05-05 13:07:05 +02:00
status = IrpQueueQueryPendingPackets(Irp);
2024-04-13 10:23:14 +02:00
/* if we return success, weve completed the irp, we can return
* success */
if (!NT_SUCCESS(status)) {
/* if there are no deferred reports, store the irp in
* the queue */
IoCsqInsertIrp(&queue->csq, Irp, NULL);
2024-04-13 10:23:14 +02:00
/* we dont want to complete the request */
return STATUS_PENDING;
}
2024-01-11 10:16:55 +01:00
2024-04-13 10:23:14 +02:00
return STATUS_SUCCESS;
2023-12-29 17:20:32 +01:00
2024-04-13 10:23:14 +02:00
case IOCTL_INITIATE_SHARED_MAPPING:
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_INITIATE_SHARED_MAPPING Received");
2024-02-14 17:56:03 +01:00
2024-04-13 10:23:14 +02:00
status = SharedMappingInitialise(Irp);
2024-04-13 10:23:14 +02:00
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"SharedMappingInitialise failed with status %x",
status);
2024-04-13 10:23:14 +02:00
break;
2024-04-13 10:23:14 +02:00
case IOCTL_VALIDATE_PCI_DEVICES:
2024-02-14 17:16:27 +01:00
2024-04-13 10:23:14 +02:00
DEBUG_INFO("IOCTL_VALIDATE_PCI_DEVICES Received");
2024-02-14 17:56:03 +01:00
2024-08-01 06:21:53 +02:00
status = ImpPsCreateSystemThread(
&handle,
PROCESS_ALL_ACCESS,
NULL,
NULL,
NULL,
ValidatePciDevices,
NULL);
2024-02-14 17:16:27 +01:00
if (!NT_SUCCESS(status)) {
DEBUG_ERROR("PsCreateSystemThread failed with status %x", status);
goto end;
}
2024-02-14 17:16:27 +01:00
ImpZwClose(handle);
2024-04-13 10:23:14 +02:00
break;
2024-02-14 17:16:27 +01:00
2024-05-04 17:43:01 +02:00
case IOCTL_VALIDATE_WIN32K_TABLES:
DEBUG_INFO("IOCTL_VALIDATE_WIN32K_TABLES Received");
status = ValidateWin32kDispatchTables();
if (!NT_SUCCESS(status))
2024-08-01 06:21:53 +02:00
DEBUG_ERROR(
"ValidateWin32kDispatchTables failed with status %x",
status);
2024-05-04 17:43:01 +02:00
break;
2024-04-13 10:23:14 +02:00
default:
2024-08-01 06:21:53 +02:00
DEBUG_WARNING(
"Invalid IOCTL passed to driver: %lx",
stack_location->Parameters.DeviceIoControl.IoControlCode);
2023-12-23 19:52:55 +01:00
2024-04-13 10:23:14 +02:00
status = STATUS_INVALID_PARAMETER;
break;
}
2023-08-19 04:52:57 +02:00
2023-08-19 08:06:51 +02:00
end:
2024-04-13 10:23:14 +02:00
DEBUG_VERBOSE("Completing IRP with status %x", status);
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
2023-08-17 10:45:50 +02:00
}
2024-01-11 10:16:55 +01:00
NTSTATUS
DeviceClose(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
2023-08-17 10:45:50 +02:00
{
2024-04-13 10:23:14 +02:00
PAGED_CODE();
UNREFERENCED_PARAMETER(DeviceObject);
DEBUG_INFO("Handle to driver closed.");
2023-08-30 15:23:04 +02:00
2024-06-16 13:42:13 +02:00
/* This needs to be fixed lol, cos anyone can just open a handle whhich
* might not begin a session.*/
2024-06-21 16:22:11 +02:00
if (GetActiveSession()->is_session_active) {
SessionTerminate();
UnregisterProcessObCallbacks();
SharedMappingTerminate();
}
2023-08-30 15:23:04 +02:00
2024-04-13 10:23:14 +02:00
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
2023-08-17 10:45:50 +02:00
}
2024-01-11 10:16:55 +01:00
NTSTATUS
DeviceCreate(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
2023-08-17 10:45:50 +02:00
{
2024-04-13 10:23:14 +02:00
PAGED_CODE();
UNREFERENCED_PARAMETER(DeviceObject);
DEBUG_INFO("Handle to driver opened.");
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
2023-08-17 10:45:50 +02:00
}