mirror of
https://github.com/wavestone-cdt/EDRSandblast.git
synced 2026-06-11 01:41:20 +00:00
Changed the way found callbacks are stored (removed the size limit)
This commit is contained in:
@@ -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)
|
//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 {
|
enum kernel_callback_type_e {
|
||||||
NOTIFY_ROUTINE_CB,
|
NOTIFY_ROUTINE_CB,
|
||||||
OBJECT_CALLBACK
|
OBJECT_CALLBACK,
|
||||||
};
|
};
|
||||||
struct KRNL_CALLBACK {
|
struct KRNL_CALLBACK {
|
||||||
enum kernel_callback_type_e type;
|
enum kernel_callback_type_e type;
|
||||||
@@ -40,11 +40,12 @@ struct KRNL_CALLBACK {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct FOUND_EDR_CALLBACKS {
|
struct FOUND_EDR_CALLBACKS {
|
||||||
DWORD64 index;
|
SIZE_T size;
|
||||||
struct KRNL_CALLBACK EDR_CALLBACKS[256];
|
SIZE_T max_size;
|
||||||
|
struct KRNL_CALLBACK* EDR_CALLBACKS;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VOID AddFoundKernelCallback(struct FOUND_EDR_CALLBACKS* foundCallbacks, struct KRNL_CALLBACK* newCallback);
|
||||||
|
|
||||||
BOOL isDriverEDR(TCHAR* driver);
|
BOOL isDriverEDR(TCHAR* driver);
|
||||||
void RestoreEDRNotifyRoutineCallbacks(struct FOUND_EDR_CALLBACKS* edrDrivers);
|
void RestoreEDRNotifyRoutineCallbacks(struct FOUND_EDR_CALLBACKS* edrDrivers);
|
||||||
|
|||||||
@@ -58,8 +58,7 @@ BOOL EnumEDRSpecificNotifyRoutineCallbacks(enum NtoskrnlOffsetType notifyRoutine
|
|||||||
}
|
}
|
||||||
newFoundDriver.removed = FALSE;
|
newFoundDriver.removed = FALSE;
|
||||||
|
|
||||||
edrCallbacks->EDR_CALLBACKS[edrCallbacks->index] = newFoundDriver;
|
AddFoundKernelCallback(edrCallbacks, &newFoundDriver);
|
||||||
edrCallbacks->index++;
|
|
||||||
CurrentEDRCallbacksCount++;
|
CurrentEDRCallbacksCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +77,7 @@ void RemoveOrRestoreSpecificEDRNotifyRoutineCallbacks(enum NtoskrnlOffsetType no
|
|||||||
TCHAR* action = remove ? TEXT("Removing") : TEXT("Restoring");
|
TCHAR* action = remove ? TEXT("Removing") : TEXT("Restoring");
|
||||||
_tprintf_or_not(TEXT("[+] [NotifyRoutines]\t%s %s callbacks\n"), action, notifyRoutineTypeStrs[notifyRoutineType]);
|
_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];
|
struct KRNL_CALLBACK* cb = &edrCallbacks->EDR_CALLBACKS[i];
|
||||||
if (cb->type == NOTIFY_ROUTINE_CB &&
|
if (cb->type == NOTIFY_ROUTINE_CB &&
|
||||||
cb->addresses.notify_routine.type == notifyRoutineType &&
|
cb->addresses.notify_routine.type == notifyRoutineType &&
|
||||||
@@ -138,3 +137,18 @@ void RemoveEDRNotifyRoutineCallbacks(struct FOUND_EDR_CALLBACKS* edrCallbacks) {
|
|||||||
void RestoreEDRNotifyRoutineCallbacks(struct FOUND_EDR_CALLBACKS* edrCallbacks) {
|
void RestoreEDRNotifyRoutineCallbacks(struct FOUND_EDR_CALLBACKS* edrCallbacks) {
|
||||||
RemoveOrRestoreEDRNotifyRoutineCallbacks(edrCallbacks, FALSE);
|
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++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -192,10 +192,7 @@ BOOL EnumEDRProcessAndThreadObjectsCallbacks(struct FOUND_EDR_CALLBACKS* FoundOb
|
|||||||
for (DWORD64 cbEntry = ReadMemoryDWORD64(ObjectType_Callbacks_List);
|
for (DWORD64 cbEntry = ReadMemoryDWORD64(ObjectType_Callbacks_List);
|
||||||
cbEntry != ObjectType_Callbacks_List;
|
cbEntry != ObjectType_Callbacks_List;
|
||||||
cbEntry = ReadMemoryDWORD64(cbEntry)) {
|
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);
|
DWORD64 ObjectTypeField = ReadMemoryDWORD64(cbEntry + Offset_CALLBACK_ENTRY_ITEM_ObjectType);
|
||||||
if (ObjectTypeField != ObjectType) {
|
if (ObjectTypeField != ObjectType) {
|
||||||
_putts_or_not(TEXT("Unexpected value in callback entry (ObjectTypeField), exiting..."));
|
_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 "));
|
_tprintf_or_not(TEXT("[+] [ObjectCallblacks]\t\t\tCallback belongs to an EDR "));
|
||||||
if (Enabled) {
|
if (Enabled) {
|
||||||
_putts_or_not(TEXT("and is enabled!"));
|
_putts_or_not(TEXT("and is enabled!"));
|
||||||
struct KRNL_CALLBACK* cb = &FoundObjectCallbacks->EDR_CALLBACKS[FoundObjectCallbacks->index];
|
struct KRNL_CALLBACK cb;
|
||||||
cb->type = OBJECT_CALLBACK;
|
cb.type = OBJECT_CALLBACK;
|
||||||
cb->driver_name = driverNamePreOperation;
|
cb.driver_name = driverNamePreOperation;
|
||||||
cb->removed = FALSE;
|
cb.removed = FALSE;
|
||||||
cb->callback_func = PreOperation;
|
cb.callback_func = PreOperation;
|
||||||
cb->addresses.object_callback.enable_addr = cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled;
|
cb.addresses.object_callback.enable_addr = cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled;
|
||||||
FoundObjectCallbacks->index++;
|
AddFoundKernelCallback(FoundObjectCallbacks, &cb);
|
||||||
found |= TRUE;
|
found |= TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -257,18 +254,19 @@ BOOL EnumEDRProcessAndThreadObjectsCallbacks(struct FOUND_EDR_CALLBACKS* FoundOb
|
|||||||
_tprintf_or_not(TEXT("[+] [ObjectCallblacks]\t\t\tCallback belongs to an EDR "));
|
_tprintf_or_not(TEXT("[+] [ObjectCallblacks]\t\t\tCallback belongs to an EDR "));
|
||||||
if (Enabled) {
|
if (Enabled) {
|
||||||
_putts_or_not(TEXT("and is enabled!"));
|
_putts_or_not(TEXT("and is enabled!"));
|
||||||
if (FoundObjectCallbacks->index != 0 &&
|
if (FoundObjectCallbacks->size != 0 &&
|
||||||
FoundObjectCallbacks->EDR_CALLBACKS[FoundObjectCallbacks->index - 1].addresses.object_callback.enable_addr == cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled) {
|
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)
|
//skip if last callback function belong to the same callback entry (preoperation)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
struct KRNL_CALLBACK* cb = &FoundObjectCallbacks->EDR_CALLBACKS[FoundObjectCallbacks->index];
|
struct KRNL_CALLBACK cb;
|
||||||
cb->type = OBJECT_CALLBACK;
|
cb.type = OBJECT_CALLBACK;
|
||||||
cb->driver_name = driverNamePostOperation;
|
cb.driver_name = driverNamePostOperation;
|
||||||
cb->removed = FALSE;
|
cb.removed = FALSE;
|
||||||
cb->callback_func = PostOperation;
|
cb.callback_func = PostOperation;
|
||||||
cb->addresses.object_callback.enable_addr = cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled;
|
cb.addresses.object_callback.enable_addr = cbEntry + Offset_CALLBACK_ENTRY_ITEM_Enabled;
|
||||||
FoundObjectCallbacks->index++;
|
AddFoundKernelCallback(FoundObjectCallbacks, &cb);
|
||||||
found |= TRUE;
|
found |= TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -287,7 +285,7 @@ void EnableDisableEDRProcessAndThreadObjectsCallbacks(struct FOUND_EDR_CALLBACKS
|
|||||||
_putts_or_not(TEXT("Object callback offsets not loaded ! Aborting..."));
|
_putts_or_not(TEXT("Object callback offsets not loaded ! Aborting..."));
|
||||||
return;
|
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];
|
struct KRNL_CALLBACK* cb = &FoundObjectCallbacks->EDR_CALLBACKS[i];
|
||||||
if (cb->type == OBJECT_CALLBACK && cb->removed == enable) {
|
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);
|
_tprintf_or_not(TEXT("[+] [ObjectCallblacks]\t%s %s callback...\n"), enable ? TEXT("Enabling") : TEXT("Disabling"), cb->driver_name);
|
||||||
|
|||||||
@@ -10,17 +10,19 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "CiOffsets.h"
|
||||||
#include "CredGuard.h"
|
#include "CredGuard.h"
|
||||||
#include "DriverOps.h"
|
#include "DriverOps.h"
|
||||||
#include "FileUtils.h"
|
#include "FileUtils.h"
|
||||||
#include "Firewalling.h"
|
#include "Firewalling.h"
|
||||||
#include "ETWThreatIntel.h"
|
#include "ETWThreatIntel.h"
|
||||||
#include "KernelCallbacks.h"
|
#include "KernelCallbacks.h"
|
||||||
|
#include "KernelDSE.h"
|
||||||
#include "KernelMemoryPrimitives.h"
|
#include "KernelMemoryPrimitives.h"
|
||||||
#include "ProcessDump.h"
|
|
||||||
#include "ProcessDumpDirectSyscalls.h"
|
|
||||||
#include "NtoskrnlOffsets.h"
|
#include "NtoskrnlOffsets.h"
|
||||||
#include "ObjectCallbacks.h"
|
#include "ObjectCallbacks.h"
|
||||||
|
#include "ProcessDump.h"
|
||||||
|
#include "ProcessDumpDirectSyscalls.h"
|
||||||
#include "PEBBrowse.h"
|
#include "PEBBrowse.h"
|
||||||
#include "PrintFunctions.h"
|
#include "PrintFunctions.h"
|
||||||
#include "RunAsPPL.h"
|
#include "RunAsPPL.h"
|
||||||
@@ -28,8 +30,6 @@
|
|||||||
#include "Undoc.h"
|
#include "Undoc.h"
|
||||||
#include "UserlandHooks.h"
|
#include "UserlandHooks.h"
|
||||||
#include "WdigestOffsets.h"
|
#include "WdigestOffsets.h"
|
||||||
#include "CiOffsets.h"
|
|
||||||
#include "KernelDSE.h"
|
|
||||||
|
|
||||||
//TODO P1 : implement a "clean" mode that only removes the driver if installed
|
//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
|
//TODO P2 : replace all instances of exit(1) by a clean_exit() function that uninstalls the driver before exiting
|
||||||
|
|||||||
Reference in New Issue
Block a user