mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
shared mapping - lock free interweaving io
This commit is contained in:
parent
67fe04c2e2
commit
d743f49bd3
16 changed files with 632 additions and 234 deletions
133
.clang-format
133
.clang-format
|
@ -1,4 +1,131 @@
|
|||
---
|
||||
BasedOnStyle: LLVM
|
||||
Language: Cpp
|
||||
BasedOnStyle: webkit
|
||||
AccessModifierOffset: -4
|
||||
|
||||
...
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
|
||||
AlignConsecutiveMacros: true
|
||||
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
|
||||
AlignTrailingComments: true
|
||||
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: TopLevel
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
|
||||
AlwaysBreakTemplateDeclarations: true #false
|
||||
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakStringLiterals: false
|
||||
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^begin_wpp|^end_wpp|^FUNC |^USESUFFIX |^USESUFFIX '
|
||||
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
|
||||
DerivePointerAlignment: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 8
|
||||
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
Language: Cpp
|
||||
|
||||
MacroBlockBegin: '^BEGIN_MODULE$|^BEGIN_TEST_CLASS$|^BEGIN_TEST_METHOD$'
|
||||
MacroBlockEnd: '^END_MODULE$|^END_TEST_CLASS$|^END_TEST_METHOD$'
|
||||
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None #All
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
|
||||
Standard: Cpp11
|
||||
StatementMacros: [
|
||||
'EXTERN_C',
|
||||
'PAGED',
|
||||
'PAGEDX',
|
||||
'NONPAGED',
|
||||
'PNPCODE',
|
||||
'INITCODE',
|
||||
'_At_',
|
||||
'_When_',
|
||||
'_Success_',
|
||||
'_Check_return_',
|
||||
'_Must_inspect_result_',
|
||||
'_IRQL_requires_same_',
|
||||
'_IRQL_requires_',
|
||||
'_IRQL_requires_max_',
|
||||
'_IRQL_requires_min_',
|
||||
'_IRQL_saves_',
|
||||
'_IRQL_restores_',
|
||||
'_IRQL_saves_global_',
|
||||
'_IRQL_restores_global_',
|
||||
'_IRQL_raises_',
|
||||
'_IRQL_lowers_',
|
||||
'_Acquires_lock_',
|
||||
'_Releases_lock_',
|
||||
'_Acquires_exclusive_lock_',
|
||||
'_Releases_exclusive_lock_',
|
||||
'_Acquires_shared_lock_',
|
||||
'_Releases_shared_lock_',
|
||||
'_Requires_lock_held_',
|
||||
'_Use_decl_annotations_',
|
||||
'_Guarded_by_',
|
||||
'__drv_preferredFunction',
|
||||
'__drv_allocatesMem',
|
||||
'__drv_freesMem',
|
||||
]
|
||||
|
||||
TabWidth: '8'
|
||||
UseTab: Never
|
131
.clang-format-c
131
.clang-format-c
|
@ -1,131 +0,0 @@
|
|||
Language: Cpp
|
||||
BasedOnStyle: webkit
|
||||
AccessModifierOffset: -4
|
||||
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: true
|
||||
|
||||
AlignConsecutiveMacros: true
|
||||
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
|
||||
AlignTrailingComments: true
|
||||
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: TopLevel
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
|
||||
AlwaysBreakTemplateDeclarations: true #false
|
||||
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakStringLiterals: false
|
||||
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: '^begin_wpp|^end_wpp|^FUNC |^USESUFFIX |^USESUFFIX '
|
||||
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
|
||||
DerivePointerAlignment: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 8
|
||||
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
Language: Cpp
|
||||
|
||||
MacroBlockBegin: '^BEGIN_MODULE$|^BEGIN_TEST_CLASS$|^BEGIN_TEST_METHOD$'
|
||||
MacroBlockEnd: '^END_MODULE$|^END_TEST_CLASS$|^END_TEST_METHOD$'
|
||||
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None #All
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
|
||||
Standard: Cpp11
|
||||
StatementMacros: [
|
||||
'EXTERN_C',
|
||||
'PAGED',
|
||||
'PAGEDX',
|
||||
'NONPAGED',
|
||||
'PNPCODE',
|
||||
'INITCODE',
|
||||
'_At_',
|
||||
'_When_',
|
||||
'_Success_',
|
||||
'_Check_return_',
|
||||
'_Must_inspect_result_',
|
||||
'_IRQL_requires_same_',
|
||||
'_IRQL_requires_',
|
||||
'_IRQL_requires_max_',
|
||||
'_IRQL_requires_min_',
|
||||
'_IRQL_saves_',
|
||||
'_IRQL_restores_',
|
||||
'_IRQL_saves_global_',
|
||||
'_IRQL_restores_global_',
|
||||
'_IRQL_raises_',
|
||||
'_IRQL_lowers_',
|
||||
'_Acquires_lock_',
|
||||
'_Releases_lock_',
|
||||
'_Acquires_exclusive_lock_',
|
||||
'_Releases_exclusive_lock_',
|
||||
'_Acquires_shared_lock_',
|
||||
'_Releases_shared_lock_',
|
||||
'_Requires_lock_held_',
|
||||
'_Use_decl_annotations_',
|
||||
'_Guarded_by_',
|
||||
'__drv_preferredFunction',
|
||||
'__drv_allocatesMem',
|
||||
'__drv_freesMem',
|
||||
]
|
||||
|
||||
TabWidth: '8'
|
||||
UseTab: Never
|
4
.clang-format-cpp
Normal file
4
.clang-format-cpp
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
BasedOnStyle: LLVM
|
||||
|
||||
...
|
|
@ -91,6 +91,7 @@ DrvLoadInitialiseDriverConfig(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_ST
|
|||
|
||||
typedef struct _DRIVER_CONFIG
|
||||
{
|
||||
volatile LONG nmi_status;
|
||||
UNICODE_STRING unicode_driver_name;
|
||||
ANSI_STRING ansi_driver_name;
|
||||
UNICODE_STRING device_name;
|
||||
|
@ -110,6 +111,7 @@ typedef struct _DRIVER_CONFIG
|
|||
THREAD_LIST_HEAD thread_list;
|
||||
DRIVER_LIST_HEAD driver_list;
|
||||
PROCESS_LIST_HEAD process_list;
|
||||
SHARED_MAPPING mapping;
|
||||
|
||||
} DRIVER_CONFIG, *PDRIVER_CONFIG;
|
||||
|
||||
|
@ -125,6 +127,26 @@ PDRIVER_CONFIG g_DriverConfig = NULL;
|
|||
|
||||
#define POOL_TAG_CONFIG 'conf'
|
||||
|
||||
VOID
|
||||
UnsetNmiInProgressFlag()
|
||||
{
|
||||
InterlockedDecrement(&g_DriverConfig->nmi_status);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
IsNmiInProgress()
|
||||
{
|
||||
/* if the initial value is true, we dont own the lock hence return false */
|
||||
return InterlockedCompareExchange(&g_DriverConfig->nmi_status, TRUE, FALSE) == 0 ? FALSE
|
||||
: TRUE;
|
||||
}
|
||||
|
||||
PSHARED_MAPPING
|
||||
GetSharedMappingConfig()
|
||||
{
|
||||
return &g_DriverConfig->mapping;
|
||||
}
|
||||
|
||||
VOID
|
||||
AcquireDriverConfigLock()
|
||||
{
|
||||
|
@ -899,6 +921,7 @@ DrvLoadInitialiseDriverConfig(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_ST
|
|||
return status;
|
||||
}
|
||||
|
||||
/* when this function failed, we bugcheck in freeconfigstrings todo: fix */
|
||||
status = DrvLoadGatherSystemEnvironmentSettings();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
|
@ -981,7 +1004,7 @@ DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
|
|||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("ResolveDynamicImports failed with status %x", status);
|
||||
ImpIoDeleteDevice(DriverObject->DeviceObject);
|
||||
// ImpIoDeleteDevice(DriverObject->DeviceObject);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,4 +88,13 @@ IsDriverUnloading();
|
|||
PPROCESS_CONFIG
|
||||
GetProcessConfig();
|
||||
|
||||
PSHARED_MAPPING
|
||||
GetSharedMappingConfig();
|
||||
|
||||
VOID
|
||||
UnsetNmiInProgressFlag();
|
||||
|
||||
BOOLEAN
|
||||
IsNmiInProgress();
|
||||
|
||||
#endif
|
|
@ -243,6 +243,13 @@ StoreModuleExecutableRegionsInBuffer(_Outptr_result_bytebuffer_(*BytesWritten) P
|
|||
*/
|
||||
dos_header = (PIMAGE_DOS_HEADER)ModuleBase;
|
||||
|
||||
if (!MmIsAddressValid(dos_header))
|
||||
{
|
||||
ImpExFreePoolWithTag(*Buffer, POOL_TAG_INTEGRITY);
|
||||
*Buffer = NULL;
|
||||
return STATUS_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* The IMAGE_DOS_HEADER.e_lfanew stores the offset of the IMAGE_NT_HEADER from the base
|
||||
* of the image.
|
||||
|
|
277
driver/io.c
277
driver/io.c
|
@ -62,6 +62,8 @@ DispatchApcOperation(_In_ PAPC_OPERATION_ID Operation);
|
|||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20021, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_QUERY_DEFERRED_REPORTS \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20022, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_INITIATE_SHARED_MAPPING \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20023, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define APC_OPERATION_STACKWALK 0x1
|
||||
|
||||
|
@ -162,7 +164,7 @@ IrpQueueQueryPendingReports(_In_ PIRP Irp)
|
|||
VOID
|
||||
IrpQueueInsert(_In_ PIO_CSQ Csq, _In_ PIRP Irp)
|
||||
{
|
||||
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||
InsertTailList(&queue->queue, &Irp->Tail.Overlay.ListEntry);
|
||||
queue->count++;
|
||||
}
|
||||
|
@ -282,6 +284,263 @@ IrpQueueInitialise()
|
|||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
SharedMappingWorkRoutine(_In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PVOID Context)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
HANDLE handle = NULL;
|
||||
PSHARED_MAPPING state = (PSHARED_MAPPING)Context;
|
||||
|
||||
InterlockedIncrement(&state->work_item_status);
|
||||
|
||||
DEBUG_VERBOSE("SharedMapping work routine called. OperationId: %lx",
|
||||
state->kernel_buffer->operation_id);
|
||||
|
||||
switch (state->kernel_buffer->operation_id)
|
||||
{
|
||||
case ssRunNmiCallbacks:
|
||||
|
||||
DEBUG_INFO("SHARED_STATE_OPERATION_ID: RunNmiCallbacks Received.");
|
||||
|
||||
status = HandleNmiIOCTL();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("RunNmiCallbacks failed with status %lx", status);
|
||||
|
||||
break;
|
||||
|
||||
case ssValidateDriverObjects:
|
||||
|
||||
DEBUG_INFO("SHARED_STATE_OPERATION_ID: ValidateDriverObjects Received.");
|
||||
|
||||
status = ImpPsCreateSystemThread(&handle,
|
||||
PROCESS_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
HandleValidateDriversIOCTL,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("PsCreateSystemThread failed with status %x", status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ImpZwClose(handle);
|
||||
break;
|
||||
|
||||
case ssEnumerateHandleTables:
|
||||
|
||||
DEBUG_INFO("SHARED_STATE_OPERATION_ID: EnumerateHandleTables Received");
|
||||
|
||||
/* can maybe implement this better so we can extract a status value */
|
||||
EnumerateProcessListWithCallbackRoutine(EnumerateProcessHandles, NULL);
|
||||
|
||||
break;
|
||||
|
||||
case ssScanForUnlinkedProcesses:
|
||||
|
||||
DEBUG_INFO("SHARED_STATE_OPERATION_ID: ScanForUnlinkedProcesses Received");
|
||||
|
||||
status = FindUnlinkedProcesses();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("FindUnlinkedProcesses failed with status %x", status);
|
||||
|
||||
break;
|
||||
|
||||
case ssPerformModuleIntegrityCheck:
|
||||
|
||||
DEBUG_INFO("SHARED_STATE_OPERATION_ID: PerformIntegrityCheck Received");
|
||||
|
||||
status = ValidateOurDriverImage();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("VerifyInMemoryImageVsDiskImage failed with status %x", status);
|
||||
|
||||
break;
|
||||
|
||||
case ssScanForAttachedThreads:
|
||||
|
||||
DEBUG_INFO("SHARED_STATE_OPERATION_ID: ScanForAttachedThreads Received");
|
||||
|
||||
DetectThreadsAttachedToProtectedProcess();
|
||||
|
||||
break;
|
||||
|
||||
case ssScanForEptHooks:
|
||||
|
||||
DEBUG_INFO("SHARED_STATE_OPERATION_ID: ScanForEptHooks Received");
|
||||
|
||||
status = DetectEptHooksInKeyFunctions();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("DetectEpthooksInKeyFunctions failed with status %x", status);
|
||||
|
||||
break;
|
||||
|
||||
case ssInitiateDpcStackwalk:
|
||||
|
||||
DEBUG_INFO("SHARED_STATE_OPERATION_ID Received");
|
||||
|
||||
status = DispatchStackwalkToEachCpuViaDpc();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("DispatchStackwalkToEachCpuViaDpc failed with status %x",
|
||||
status);
|
||||
|
||||
break;
|
||||
|
||||
case ssValidateSystemModules:
|
||||
|
||||
DEBUG_INFO("SHARED_STATE_OPERATION_ID: ValidateSystemModules Received");
|
||||
|
||||
status = SystemModuleVerificationDispatcher();
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("ValidateSystemModules failed with status %x", status);
|
||||
|
||||
break;
|
||||
|
||||
default: DEBUG_ERROR("Invalid SHARED_STATE_OPERATION_ID Received");
|
||||
}
|
||||
|
||||
end:
|
||||
InterlockedDecrement(&state->work_item_status);
|
||||
}
|
||||
|
||||
/* again, we want to run our routine at apc level not dispatch level */
|
||||
VOID
|
||||
SharedMappingDpcRoutine(_In_ PKDPC Dpc,
|
||||
_In_opt_ PVOID DeferredContext,
|
||||
_In_opt_ PVOID SystemArgument1,
|
||||
_In_opt_ PVOID SystemArgument2)
|
||||
{
|
||||
PSHARED_MAPPING mapping = (PSHARED_MAPPING)DeferredContext;
|
||||
|
||||
if (!mapping->active || mapping->work_item_status)
|
||||
return;
|
||||
|
||||
IoQueueWorkItem(mapping->work_item, SharedMappingWorkRoutine, NormalWorkQueue, mapping);
|
||||
}
|
||||
|
||||
#define REPEAT_TIME_15_SEC 30000
|
||||
|
||||
VOID
|
||||
SharedMappingTerminate()
|
||||
{
|
||||
PSHARED_MAPPING mapping = GetSharedMappingConfig();
|
||||
|
||||
while (mapping->work_item_status)
|
||||
YieldProcessor();
|
||||
|
||||
mapping->active = FALSE;
|
||||
mapping->user_buffer = NULL;
|
||||
mapping->size = 0;
|
||||
|
||||
KeCancelTimer(&mapping->timer);
|
||||
IoFreeWorkItem(mapping->work_item);
|
||||
IoFreeMdl(mapping->mdl);
|
||||
ExFreePoolWithTag(mapping->kernel_buffer, POOL_TAG_INTEGRITY);
|
||||
|
||||
RtlZeroMemory(mapping, sizeof(SHARED_MAPPING));
|
||||
}
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
SharedMappingInitialiseTimer(_In_ PSHARED_MAPPING Mapping)
|
||||
{
|
||||
LARGE_INTEGER due_time = {0};
|
||||
LONG period = 0;
|
||||
|
||||
due_time.QuadPart = ABSOLUTE(SECONDS(30));
|
||||
|
||||
Mapping->work_item = IoAllocateWorkItem(GetDriverDeviceObject());
|
||||
|
||||
if (!Mapping->work_item)
|
||||
{
|
||||
DEBUG_ERROR("IoAllocateWorkItem failed with no status.");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
KeInitializeDpc(&Mapping->timer_dpc, SharedMappingDpcRoutine, Mapping);
|
||||
KeInitializeTimer(&Mapping->timer);
|
||||
KeSetTimerEx(&Mapping->timer, due_time, REPEAT_TIME_15_SEC, &Mapping->timer_dpc);
|
||||
|
||||
DEBUG_VERBOSE("Initialised shared mapping event timer.");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
SharedMappingInitialise(_In_ PIRP Irp)
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
PMDL mdl = NULL;
|
||||
PSHARED_MAPPING mapping = NULL;
|
||||
PSHARED_MAPPING_INIT mapping_init = NULL;
|
||||
PEPROCESS process = NULL;
|
||||
PVOID buffer = NULL;
|
||||
PVOID user_buffer = NULL;
|
||||
|
||||
mapping = GetSharedMappingConfig();
|
||||
|
||||
status = ValidateIrpOutputBuffer(Irp, sizeof(SHARED_MAPPING_INIT));
|
||||
|
||||
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
|
||||
{
|
||||
user_buffer = MmMapLockedPagesSpecifyCache(
|
||||
mdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority | MdlMappingNoExecute);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
status = GetExceptionCode();
|
||||
DEBUG_ERROR("MmMapLockedPagesSpecifyCache failed with status %x", status);
|
||||
IoFreeMdl(mdl);
|
||||
ExFreePoolWithTag(buffer, POOL_TAG_INTEGRITY);
|
||||
return status;
|
||||
}
|
||||
|
||||
mapping->kernel_buffer = (PSHARED_STATE)buffer;
|
||||
mapping->user_buffer = user_buffer;
|
||||
mapping->mdl = mdl;
|
||||
mapping->size = PAGE_SIZE;
|
||||
mapping->active = TRUE;
|
||||
mapping->work_item_status = FALSE;
|
||||
|
||||
SharedMappingInitialiseTimer(mapping);
|
||||
|
||||
mapping_init = (PSHARED_MAPPING_INIT)Irp->AssociatedIrp.SystemBuffer;
|
||||
mapping_init->buffer = user_buffer;
|
||||
mapping_init->size = PAGE_SIZE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
DispatchApcOperation(_In_ PAPC_OPERATION_ID Operation)
|
||||
|
@ -640,7 +899,7 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
|||
DEBUG_INFO("IOCTL_VALIDATE_SYSTEM_MODULES Received");
|
||||
|
||||
status = SystemModuleVerificationDispatcher();
|
||||
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("ValidateSystemModules failed with status %x", status);
|
||||
|
||||
|
@ -660,7 +919,7 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
|||
|
||||
case IOCTL_INSERT_IRP_INTO_QUEUE:;
|
||||
|
||||
//DEBUG_INFO("IOCTL_INSERT_IRP_INTO_QUEUE Received");
|
||||
// DEBUG_INFO("IOCTL_INSERT_IRP_INTO_QUEUE Received");
|
||||
|
||||
PIRP_QUEUE_HEAD queue = GetIrpQueueHead();
|
||||
|
||||
|
@ -670,8 +929,6 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP 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.
|
||||
*
|
||||
* TODO: some issue with using an incoming irp meant for the queue and finishing a deferred report.
|
||||
*/
|
||||
|
||||
/* before we queue our IRP, check if we can complete a deferred report */
|
||||
|
@ -690,6 +947,15 @@ DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
|||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
case IOCTL_INITIATE_SHARED_MAPPING:
|
||||
|
||||
status = SharedMappingInitialise(Irp);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("SharedMappingInitialise failed with status %x", status);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_WARNING("Invalid IOCTL passed to driver: %lx",
|
||||
stack_location->Parameters.DeviceIoControl.IoControlCode);
|
||||
|
@ -716,6 +982,7 @@ DeviceClose(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
|
|||
/* we also lose reports here, so sohuld pass em into the irp before freeing */
|
||||
ProcCloseClearProcessConfiguration();
|
||||
UnregisterProcessObCallbacks();
|
||||
SharedMappingTerminate();
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Irp->IoStatus.Status;
|
||||
|
|
42
driver/io.h
42
driver/io.h
|
@ -12,6 +12,48 @@ typedef struct _DRIVER_INITIATION_INFORMATION
|
|||
|
||||
} DRIVER_INITIATION_INFORMATION, *PDRIVER_INITIATION_INFORMATION;
|
||||
|
||||
typedef struct _SHARED_MAPPING_INIT
|
||||
{
|
||||
PVOID buffer;
|
||||
SIZE_T size;
|
||||
|
||||
} SHARED_MAPPING_INIT, *PSHARED_MAPPING_INIT;
|
||||
|
||||
typedef enum _SHARED_STATE_OPERATION_ID
|
||||
{
|
||||
ssRunNmiCallbacks = 0,
|
||||
ssValidateDriverObjects,
|
||||
ssEnumerateHandleTables,
|
||||
ssScanForUnlinkedProcesses,
|
||||
ssPerformModuleIntegrityCheck,
|
||||
ssScanForAttachedThreads,
|
||||
ssScanForEptHooks,
|
||||
ssInitiateDpcStackwalk,
|
||||
ssValidateSystemModules,
|
||||
|
||||
} SHARED_STATE_OPERATION_ID;
|
||||
|
||||
typedef struct _SHARED_STATE
|
||||
{
|
||||
volatile UINT32 status;
|
||||
volatile UINT16 operation_id;
|
||||
|
||||
} SHARED_STATE, *PSHARED_STATE;
|
||||
|
||||
typedef struct _SHARED_MAPPING
|
||||
{
|
||||
volatile LONG work_item_status;
|
||||
PVOID user_buffer;
|
||||
PSHARED_STATE kernel_buffer;
|
||||
PMDL mdl;
|
||||
SIZE_T size;
|
||||
volatile BOOLEAN active;
|
||||
KTIMER timer;
|
||||
KDPC timer_dpc;
|
||||
PIO_WORKITEM work_item;
|
||||
|
||||
} SHARED_MAPPING, *PSHARED_MAPPING;
|
||||
|
||||
NTSTATUS
|
||||
DeviceControl(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp);
|
||||
|
||||
|
|
|
@ -135,7 +135,7 @@ ValidateDriverObjects(_In_ PSYSTEM_MODULES SystemModules,
|
|||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules, _Inout_ PIRP Irp);
|
||||
AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules);
|
||||
|
||||
STATIC
|
||||
NTSTATUS
|
||||
|
@ -795,7 +795,7 @@ IsInstructionPointerInsideModule(_In_ UINT64 Rip,
|
|||
*/
|
||||
STATIC
|
||||
NTSTATUS
|
||||
AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules, _Inout_ PIRP Irp)
|
||||
AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
|
@ -810,27 +810,25 @@ AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules,
|
|||
/* Make sure our NMIs were run */
|
||||
if (!NmiContext[core].callback_count)
|
||||
{
|
||||
NTSTATUS status =
|
||||
ValidateIrpOutputBuffer(Irp, sizeof(NMI_CALLBACK_FAILURE));
|
||||
PNMI_CALLBACK_FAILURE report = ImpExAllocatePool2(
|
||||
POOL_FLAG_NON_PAGED, sizeof(NMI_CALLBACK_FAILURE), REPORT_POOL_TAG);
|
||||
|
||||
if (!report)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
report->report_code = REPORT_NMI_CALLBACK_FAILURE;
|
||||
report->kthread_address = NULL;
|
||||
report->invalid_rip = NULL;
|
||||
report->were_nmis_disabled = TRUE;
|
||||
|
||||
status = IrpQueueCompleteIrp(report, sizeof(NMI_CALLBACK_FAILURE));
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("ValidateIrpOutputBuffer failed with status %x",
|
||||
status);
|
||||
continue;
|
||||
DEBUG_ERROR("IrpQueueCompleteIrp failed with status %x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
NMI_CALLBACK_FAILURE report = {0};
|
||||
report.report_code = REPORT_NMI_CALLBACK_FAILURE;
|
||||
report.kthread_address = NULL;
|
||||
report.invalid_rip = NULL;
|
||||
report.were_nmis_disabled = TRUE;
|
||||
|
||||
Irp->IoStatus.Information = sizeof(NMI_CALLBACK_FAILURE);
|
||||
|
||||
RtlCopyMemory(
|
||||
Irp->AssociatedIrp.SystemBuffer, &report, sizeof(NMI_CALLBACK_FAILURE));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -905,36 +903,24 @@ AnalyseNmiData(_In_ PNMI_CONTEXT NmiContext, _In_ PSYSTEM_MODULES SystemModules,
|
|||
|
||||
if (!flag)
|
||||
{
|
||||
status = ValidateIrpOutputBuffer(Irp, sizeof(NMI_CALLBACK_FAILURE));
|
||||
PNMI_CALLBACK_FAILURE report =
|
||||
ImpExAllocatePool2(POOL_FLAG_NON_PAGED,
|
||||
sizeof(HIDDEN_SYSTEM_THREAD_REPORT),
|
||||
REPORT_POOL_TAG);
|
||||
|
||||
report->report_code = REPORT_NMI_CALLBACK_FAILURE;
|
||||
report->kthread_address = NmiContext[core].kthread;
|
||||
report->invalid_rip = NmiContext[core].interrupted_rip;
|
||||
report->were_nmis_disabled = FALSE;
|
||||
|
||||
status = IrpQueueCompleteIrp(report, sizeof(HIDDEN_SYSTEM_THREAD_REPORT));
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
DEBUG_ERROR("ValidateIrpOutputBuffer failed with status %x",
|
||||
status);
|
||||
DEBUG_ERROR("IrpQueueCompleteIrp failed with status %x", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: for now, we only handle 1 report at a time so we stop the
|
||||
* analysis once we receive a report since we only send a buffer
|
||||
* large enough for 1 report. In the future this should be changed
|
||||
* to a buffer that can hold atleast 4 reports (since the chance we
|
||||
* get 4 reports with a single NMI would be impossible) so we can
|
||||
* continue parsing the rest of the stack frames after receiving a
|
||||
* single report.
|
||||
*/
|
||||
|
||||
NMI_CALLBACK_FAILURE report = {0};
|
||||
report.report_code = REPORT_NMI_CALLBACK_FAILURE;
|
||||
report.kthread_address = NmiContext[core].kthread;
|
||||
report.invalid_rip = NmiContext[core].interrupted_rip;
|
||||
report.were_nmis_disabled = FALSE;
|
||||
|
||||
Irp->IoStatus.Information = sizeof(NMI_CALLBACK_FAILURE);
|
||||
|
||||
RtlCopyMemory(
|
||||
Irp->AssociatedIrp.SystemBuffer, &report, sizeof(NMI_CALLBACK_FAILURE));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -1024,7 +1010,7 @@ LaunchNonMaskableInterrupt()
|
|||
}
|
||||
|
||||
NTSTATUS
|
||||
HandleNmiIOCTL(_Inout_ PIRP Irp)
|
||||
HandleNmiIOCTL()
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
|
@ -1033,6 +1019,9 @@ HandleNmiIOCTL(_Inout_ PIRP Irp)
|
|||
SYSTEM_MODULES system_modules = {0};
|
||||
PNMI_CONTEXT nmi_context = NULL;
|
||||
|
||||
if (IsNmiInProgress())
|
||||
return STATUS_ALREADY_COMMITTED;
|
||||
|
||||
status = ValidateHalDispatchTables();
|
||||
|
||||
/* do we continue ? probably. */
|
||||
|
@ -1084,7 +1073,7 @@ HandleNmiIOCTL(_Inout_ PIRP Irp)
|
|||
return status;
|
||||
}
|
||||
|
||||
status = AnalyseNmiData(nmi_context, &system_modules, Irp);
|
||||
status = AnalyseNmiData(nmi_context, &system_modules);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
DEBUG_ERROR("Error analysing nmi data");
|
||||
|
@ -1093,6 +1082,7 @@ HandleNmiIOCTL(_Inout_ PIRP Irp)
|
|||
ImpExFreePoolWithTag(nmi_context, NMI_CONTEXT_POOL);
|
||||
ImpKeDeregisterNmiCallback(callback_handle);
|
||||
|
||||
UnsetNmiInProgressFlag();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ PRTL_MODULE_EXTENDED_INFO
|
|||
FindSystemModuleByName(_In_ LPCSTR ModuleName, _In_ PSYSTEM_MODULES SystemModules);
|
||||
|
||||
NTSTATUS
|
||||
HandleNmiIOCTL(_Inout_ PIRP Irp);
|
||||
HandleNmiIOCTL();
|
||||
|
||||
BOOLEAN
|
||||
FreeApcContextStructure(_Inout_ PAPC_CONTEXT_HEADER Context);
|
||||
|
|
|
@ -10,19 +10,23 @@ dispatcher::dispatcher::dispatcher(LPCWSTR driver_name,
|
|||
: thread_pool(DISPATCHER_THREAD_COUNT),
|
||||
k_interface(driver_name, message_queue) {}
|
||||
|
||||
void dispatcher::dispatcher::timer_test_callback() {
|
||||
LOG_INFO("Timer callback invoked from dispatcher class!!");
|
||||
void dispatcher::dispatcher::write_shared_mapping_operation() {
|
||||
int operation =
|
||||
helper::generate_rand_int(kernel_interface::SHARED_STATE_OPERATION_COUNT);
|
||||
LOG_INFO("Shared mapping operation callback received. operation: %lx",
|
||||
operation);
|
||||
this->k_interface.write_shared_mapping_operation(
|
||||
*reinterpret_cast<kernel_interface::shared_state_operation_id *>(
|
||||
&operation));
|
||||
}
|
||||
|
||||
void dispatcher::dispatcher::init_timer_callbacks() {
|
||||
/* we want to offset when our driver routines are called */
|
||||
this->k_interface.initiate_shared_mapping();
|
||||
std::optional<HANDLE> result = this->timers.insert_callback(
|
||||
std::bind(&dispatcher::dispatcher::timer_test_callback, this), 5, 5);
|
||||
this->timers.insert_callback(
|
||||
std::bind(&dispatcher::dispatcher::timer_test_callback, this), 7, 7);
|
||||
this->timers.insert_callback(
|
||||
std::bind(&dispatcher::dispatcher::timer_test_callback, this), 10, 10);
|
||||
|
||||
this->timers.remove_callback(result.value());
|
||||
std::bind(&dispatcher::dispatcher::write_shared_mapping_operation, this),
|
||||
WRITE_SHARED_MAPPING_DUE_TIME, WRITE_SHARED_MAPPING_PERIOD);
|
||||
helper::sleep_thread(TIMER_CALLBACK_DELAY);
|
||||
}
|
||||
|
||||
void dispatcher::dispatcher::run_timer_thread() {
|
||||
|
@ -38,10 +42,10 @@ void dispatcher::dispatcher::run() {
|
|||
this->init_timer_callbacks();
|
||||
this->run_timer_thread();
|
||||
this->run_io_port_thread();
|
||||
//thread_pool.queue_job([this]() { k_interface.run_completion_port(); });
|
||||
thread_pool.queue_job([this]() { k_interface.run_completion_port(); });
|
||||
while (true) {
|
||||
//this->issue_kernel_job();
|
||||
//helper::sleep_thread(DISPATCH_LOOP_SLEEP_TIME);
|
||||
this->issue_kernel_job();
|
||||
helper::sleep_thread(DISPATCH_LOOP_SLEEP_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
|
||||
namespace dispatcher {
|
||||
|
||||
static const int DISPATCH_LOOP_SLEEP_TIME = 10;
|
||||
static const int KERNEL_DISPATCH_FUNCTION_COUNT = 11;
|
||||
static const int DISPATCHER_THREAD_COUNT = 4;
|
||||
constexpr int DISPATCH_LOOP_SLEEP_TIME = 30;
|
||||
constexpr int KERNEL_DISPATCH_FUNCTION_COUNT = 11;
|
||||
constexpr int DISPATCHER_THREAD_COUNT = 4;
|
||||
constexpr int TIMER_CALLBACK_DELAY = 15;
|
||||
constexpr int WRITE_SHARED_MAPPING_PERIOD = 30;
|
||||
constexpr int WRITE_SHARED_MAPPING_DUE_TIME = 30;
|
||||
|
||||
class dispatcher {
|
||||
timer timers;
|
||||
|
@ -17,7 +20,7 @@ class dispatcher {
|
|||
kernel_interface::kernel_interface k_interface;
|
||||
|
||||
void issue_kernel_job();
|
||||
void timer_test_callback();
|
||||
void write_shared_mapping_operation();
|
||||
void init_timer_callbacks();
|
||||
void run_timer_thread();
|
||||
void run_io_port_thread();
|
||||
|
|
|
@ -85,8 +85,8 @@ void dispatcher::timer::close_handle_entry(HANDLE handle) {
|
|||
if (this->handles[entry] == handle) {
|
||||
CloseHandle(handle);
|
||||
this->handles[entry] = INVALID_HANDLE_VALUE;
|
||||
/* ordering doesnt matter, aslong as the valid handles are at the front of
|
||||
* the array and are contiguous */
|
||||
/* ordering doesnt matter, as long as the valid handles are at the front
|
||||
* of the array and are contiguous */
|
||||
std::sort(this->handles.begin(), this->handles.end());
|
||||
this->active_callbacks--;
|
||||
return;
|
||||
|
@ -110,10 +110,14 @@ void dispatcher::timer::query_removal_queue() {
|
|||
HANDLE entry = callbacks_to_remove.front();
|
||||
this->close_handle_entry(entry);
|
||||
this->callbacks_to_remove.pop();
|
||||
this->active_callbacks--;
|
||||
}
|
||||
}
|
||||
|
||||
/* todo: maybe have an event object that we can wait on whilst no events are queued, then when we do insert an event alert the event object ? though this isnt urgent for our use case...*/
|
||||
void dispatcher::timer::run_timer_thread() {
|
||||
if (this->active_callbacks == 0)
|
||||
return;
|
||||
while (true) {
|
||||
unsigned long index = WaitForMultipleObjects(
|
||||
this->active_callbacks, reinterpret_cast<HANDLE *>(&handles), false,
|
||||
|
@ -122,6 +126,9 @@ void dispatcher::timer::run_timer_thread() {
|
|||
std::lock_guard<std::mutex> lock(this->lock);
|
||||
this->dispatch_callback_for_index(index);
|
||||
this->query_removal_queue();
|
||||
/* maybe we should have some default event ? */
|
||||
if (this->active_callbacks == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
* array of handles which we pass to WaitForMultipleEvents
|
||||
|
@ -17,16 +17,11 @@
|
|||
* cos u cant just take a pointer to a member function for some reason lol like
|
||||
* tf
|
||||
*
|
||||
* this returns an index into the array
|
||||
*
|
||||
* setup a vector containing the job routine for the associated handle, then
|
||||
* call that job.
|
||||
*
|
||||
* If we activate another handle in the handles array, the next time the current
|
||||
* event is signalled and we are invoked, only then should we insert new
|
||||
* requests. This means we should implement some queue where new timer objects
|
||||
* are inserted into the queue, then when the current even is invoked, we can
|
||||
* recall WaitForMultipleObjects with the updated array count.
|
||||
* map maps a handle to a callback object, this object contains various
|
||||
* information bust most important the callback routine. When the event is
|
||||
* signaled, it returns a handle, use that handle to index the map and run the
|
||||
* callback routine. This has to be done as the handles needs to be in a
|
||||
* contiguous array, so we can use an array of callback objects.
|
||||
*/
|
||||
namespace dispatcher {
|
||||
|
||||
|
@ -65,8 +60,9 @@ public:
|
|||
timer();
|
||||
~timer();
|
||||
|
||||
std::optional<HANDLE> insert_callback(std::function<void()> routine, int due_time_seconds,
|
||||
int period_seconds);
|
||||
std::optional<HANDLE> insert_callback(std::function<void()> routine,
|
||||
int due_time_seconds,
|
||||
int period_seconds);
|
||||
void remove_callback(HANDLE handle);
|
||||
void run_timer_thread();
|
||||
};
|
||||
|
|
|
@ -273,18 +273,38 @@ void kernel_interface::kernel_interface::send_pending_irp() {
|
|||
LOG_ERROR("failed to insert irp into irp queue %x", status);
|
||||
}
|
||||
|
||||
//void kernel_interface::kernel_interface::query_deferred_reports() {
|
||||
// unsigned long bytes_returned = 0;
|
||||
// void *buffer = malloc(MAXIMUM_REPORT_BUFFER_SIZE);
|
||||
// if (!buffer)
|
||||
// return;
|
||||
// for (int i = 0; i < QUERY_DEFERRED_REPORT_COUNT; i++) {
|
||||
// unsigned int status =
|
||||
// generic_driver_call_output(ioctl_code::QueryDeferredReports, buffer,
|
||||
// MAXIMUM_REPORT_BUFFER_SIZE, &bytes_returned);
|
||||
// if (status && bytes_returned > 0)
|
||||
// helper::print_kernel_report(buffer);
|
||||
// memset(buffer, 0, MAXIMUM_REPORT_BUFFER_SIZE);
|
||||
// }
|
||||
// free(buffer);
|
||||
//}
|
||||
// void kernel_interface::kernel_interface::query_deferred_reports() {
|
||||
// unsigned long bytes_returned = 0;
|
||||
// void *buffer = malloc(MAXIMUM_REPORT_BUFFER_SIZE);
|
||||
// if (!buffer)
|
||||
// return;
|
||||
// for (int i = 0; i < QUERY_DEFERRED_REPORT_COUNT; i++) {
|
||||
// unsigned int status =
|
||||
// generic_driver_call_output(ioctl_code::QueryDeferredReports, buffer,
|
||||
// MAXIMUM_REPORT_BUFFER_SIZE,
|
||||
// &bytes_returned);
|
||||
// if (status && bytes_returned > 0)
|
||||
// helper::print_kernel_report(buffer);
|
||||
// memset(buffer, 0, MAXIMUM_REPORT_BUFFER_SIZE);
|
||||
// }
|
||||
// free(buffer);
|
||||
// }
|
||||
|
||||
void kernel_interface::kernel_interface::write_shared_mapping_operation(
|
||||
shared_state_operation_id operation_id) {
|
||||
InterlockedExchange16(
|
||||
reinterpret_cast<SHORT *>(&this->mapping.buffer->operation_id),
|
||||
operation_id);
|
||||
}
|
||||
|
||||
void kernel_interface::kernel_interface::initiate_shared_mapping() {
|
||||
LOG_INFO("Initialising shared memory buffer!");
|
||||
unsigned long bytes_returned = 0;
|
||||
unsigned long result = this->generic_driver_call_output(
|
||||
ioctl_code::InitiateSharedMapping, &this->mapping,
|
||||
sizeof(kernel_interface::shared_mapping), &bytes_returned);
|
||||
if (!result) {
|
||||
LOG_ERROR("DeviceIoControl failed with status %x", GetLastError());
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -136,8 +136,25 @@ enum ioctl_code
|
|||
InitiateDpcStackwalk = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20019, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||
ValidateSystemModules = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20020, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||
InsertIrpIntoIrpQueue = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20021, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||
QueryDeferredReports = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20022, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
QueryDeferredReports = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20022, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||
InitiateSharedMapping = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x20023, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
};
|
||||
|
||||
constexpr int SHARED_STATE_OPERATION_COUNT = 9;
|
||||
|
||||
enum shared_state_operation_id
|
||||
{
|
||||
ssRunNmiCallbacks = 0,
|
||||
ssValidateDriverObjects,
|
||||
ssEnumerateHandleTables,
|
||||
ssScanForUnlinkedProcesses,
|
||||
ssPerformModuleIntegrityCheck,
|
||||
ssScanForAttachedThreads,
|
||||
ssScanForEptHooks,
|
||||
ssInitiateDpcStackwalk,
|
||||
ssValidateSystemModules,
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
struct event_dispatcher {
|
||||
|
@ -181,6 +198,18 @@ class kernel_interface {
|
|||
std::mutex lock;
|
||||
std::vector<event_dispatcher> events;
|
||||
|
||||
struct shared_data {
|
||||
unsigned __int32 status;
|
||||
unsigned __int16 operation_id;
|
||||
};
|
||||
|
||||
struct shared_mapping {
|
||||
shared_data *buffer;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
shared_mapping mapping;
|
||||
|
||||
void initiate_completion_port();
|
||||
void terminate_completion_port();
|
||||
event_dispatcher *get_free_event_entry();
|
||||
|
@ -216,6 +245,7 @@ public:
|
|||
void verify_process_module_executable_regions();
|
||||
void initiate_apc_stackwalk();
|
||||
void send_pending_irp();
|
||||
void query_deferred_reports();
|
||||
void write_shared_mapping_operation(shared_state_operation_id operation_id);
|
||||
void initiate_shared_mapping();
|
||||
};
|
||||
} // namespace kernel_interface
|
Loading…
Reference in a new issue