#include #include "TelemetrySourcererDriver.h" #include "Callbacks.h" #include "Memory.h" #pragma comment(lib, "FltMgr.lib") UCHAR LI_PATTERN_W7_07600[] = { 0x41, 0x0f, 0xba, 0x6d, 0x00, 0x0a, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x4c, 0x8b, 0xf2, 0x4c, 0x8b, 0xf9 }; UCHAR LI_PATTERN_W8_08102[] = { 0xbf, 0x08, 0x00, 0x00, 0x00, 0x41, 0x89, 0x06, 0x0f, 0x1f, 0x04, 0x00, 0x48, 0x8b, 0xcb, 0xe8 }; UCHAR LI_PATTERN_W8_09431[] = { 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd7, 0x48, 0x8d, 0x0c, 0xd9, 0xe8 }; UCHAR LI_PATTERN_WX_10240[] = { 0x45, 0x33, 0xC0, 0x48, 0x8D, 0x0C, 0xD9, 0x48, 0x8B, 0xD7, 0xE8 }; CALLBACK_SEARCH_QUERY LoadImageCallbackQueries[14] = { { WINDOWS_INDEX::W7_07600, RTL_CONSTANT_STRING(L"FsRtlReleaseFile"), RTL_CONSTANT_STRING(L"IoSetPartitionInformationEx"), LI_PATTERN_W7_07600, sizeof(LI_PATTERN_W7_07600), -4 }, { WINDOWS_INDEX::W8_08102, RTL_CONSTANT_STRING(L"ExSizeOfRundownProtectionCacheAware"), RTL_CONSTANT_STRING(L"MmProbeAndLockProcessPages"), LI_PATTERN_W8_08102, sizeof(LI_PATTERN_W8_08102), -4 }, { WINDOWS_INDEX::W8_09431, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutine"), RTL_CONSTANT_STRING(L"PsSetCreateThreadNotifyRoutine"), LI_PATTERN_W8_09431, sizeof(LI_PATTERN_W8_09431), -4 }, { WINDOWS_INDEX::WX_10240, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutine"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_10586, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutine"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_14393, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutine"), RTL_CONSTANT_STRING(L"SeRegisterLogonSessionTerminatedRoutineEx"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_15063, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutine"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_16299, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutine"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_17134, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutine"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_17763, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutineEx"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_18362, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutineEx"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_18363, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutineEx"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_19041, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutineEx"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_19042, RTL_CONSTANT_STRING(L"PsSetLoadImageNotifyRoutineEx"), RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), LI_PATTERN_WX_10240, sizeof(LI_PATTERN_WX_10240), -4 }, }; UCHAR CP_PATTERN_W7_07600[] = { 0x4c, 0x8b, 0xf9, 0x48, 0x8d, 0x0c, 0xc1, 0xe8 }; UCHAR CP_PATTERN_W8_08102[] = { 0x8b, 0xc3, 0x48, 0x8d, 0x34, 0xc1, 0x48, 0x8b, 0xce, 0xe8 }; UCHAR CP_PATTERN_W8_09431[] = { 0x48, 0x8d, 0x04, 0xc1, 0x48, 0x89, 0x45, 0x70, 0x48, 0x8b, 0xc8, 0xe8 }; UCHAR CP_PATTERN_WX_10240[] = { 0x8b, 0xc3, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd6, 0x49, 0x8d, 0x0c, 0xc7, 0xe8 }; UCHAR CP_PATTERN_WX_10586[] = { 0x49, 0x8d, 0x0c, 0xff, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd6, 0xe8 }; UCHAR CP_PATTERN_WX_14393[] = { 0x49, 0x8d, 0x0c, 0xfc, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd6, 0xe8 }; UCHAR CP_PATTERN_WX_15063[] = { 0x49, 0x8d, 0x0c, 0xdc, 0x45, 0x33, 0xc0, 0x48, 0x8b, 0xd6, 0xe8 }; UCHAR CP_PATTERN_WX_16299[] = { 0x48, 0x8d, 0x0c, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x45, 0x33, 0xc0, 0x49, 0x03, 0xcd, 0x48, 0x8b }; CALLBACK_SEARCH_QUERY CreateProcessCallbackQueries[14] = { { WINDOWS_INDEX::W7_07600, RTL_CONSTANT_STRING(L"RtlAreAllAccessesGranted"), RTL_CONSTANT_STRING(L"RtlGetIntegerAtom"), CP_PATTERN_W7_07600, sizeof(CP_PATTERN_W7_07600), -4 }, { WINDOWS_INDEX::W8_08102, RTL_CONSTANT_STRING(L"PsAcquireProcessExitSynchronization"), RTL_CONSTANT_STRING(L"FsRtlAddToTunnelCache"), CP_PATTERN_W8_08102, sizeof(CP_PATTERN_W8_08102), -4 }, { WINDOWS_INDEX::W8_09431, RTL_CONSTANT_STRING(L"ObCreateObject"), RTL_CONSTANT_STRING(L"NtFindAtom"), CP_PATTERN_W8_09431, sizeof(CP_PATTERN_W8_09431), -4 }, { WINDOWS_INDEX::WX_10240, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"KeRegisterProcessorChangeCallback"), CP_PATTERN_WX_10240, sizeof(CP_PATTERN_WX_10240), -4 }, { WINDOWS_INDEX::WX_10586, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"KeRegisterProcessorChangeCallback"), CP_PATTERN_WX_10586, sizeof(CP_PATTERN_WX_10586), -4 }, { WINDOWS_INDEX::WX_14393, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"KeRegisterProcessorChangeCallback"), CP_PATTERN_WX_14393, sizeof(CP_PATTERN_WX_14393), -4 }, { WINDOWS_INDEX::WX_15063, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"KeRegisterProcessorChangeCallback"), CP_PATTERN_WX_15063, sizeof(CP_PATTERN_WX_15063), -4 }, { WINDOWS_INDEX::WX_16299, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"RtlGetSystemBootStatus"), CP_PATTERN_WX_16299, sizeof(CP_PATTERN_WX_16299), -4 }, { WINDOWS_INDEX::WX_17134, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"EtwEnableTrace"), CP_PATTERN_WX_16299, sizeof(CP_PATTERN_WX_16299), -4 }, { WINDOWS_INDEX::WX_17763, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"IoCreateDriver"), CP_PATTERN_WX_16299, sizeof(CP_PATTERN_WX_16299), -4 }, { WINDOWS_INDEX::WX_18362, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"IoCreateDriver"), CP_PATTERN_WX_16299, sizeof(CP_PATTERN_WX_16299), -4 }, { WINDOWS_INDEX::WX_18363, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"IoCreateDriver"), CP_PATTERN_WX_16299, sizeof(CP_PATTERN_WX_16299), -4 }, { WINDOWS_INDEX::WX_19041, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"IoCreateDriver"), CP_PATTERN_WX_16299, sizeof(CP_PATTERN_WX_16299), -4 }, { WINDOWS_INDEX::WX_19042, RTL_CONSTANT_STRING(L"PsSetCreateProcessNotifyRoutine"), RTL_CONSTANT_STRING(L"IoCreateDriver"), CP_PATTERN_WX_16299, sizeof(CP_PATTERN_WX_16299), -4 }, }; UCHAR CT_PATTERN_W7_07600[] = { 0xbf, 0x40, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xcb, 0xe8 }; UCHAR CT_PATTERN_WX_10240[] = { 0x48, 0x8b, 0xcd, 0xe8 }; CALLBACK_SEARCH_QUERY CreateThreadCallbackQueries[14] = { { WINDOWS_INDEX::W7_07600, RTL_CONSTANT_STRING(L"RtlUnicodeToMultiByteSize"), RTL_CONSTANT_STRING(L"MmLockPagableSectionByHandle"), CT_PATTERN_W7_07600, sizeof(CT_PATTERN_W7_07600), -5 }, { WINDOWS_INDEX::W8_08102, RTL_CONSTANT_STRING(L"PsAcquireProcessExitSynchronization"), RTL_CONSTANT_STRING(L"FsRtlAddToTunnelCache"), CT_PATTERN_W7_07600, sizeof(CT_PATTERN_W7_07600), -4 }, { WINDOWS_INDEX::W8_09431, RTL_CONSTANT_STRING(L"ObCreateObject"), RTL_CONSTANT_STRING(L"NtFindAtom"), CT_PATTERN_W7_07600, sizeof(CT_PATTERN_W7_07600), -5 }, { WINDOWS_INDEX::WX_10240, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_10586, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_14393, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_15063, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_16299, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_17134, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_17763, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_18362, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_18363, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_19041, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, { WINDOWS_INDEX::WX_19042, RTL_CONSTANT_STRING(L"PsRemoveCreateThreadNotifyRoutine"), RTL_CONSTANT_STRING(L"PsRemoveLoadImageNotifyRoutine"), CT_PATTERN_WX_10240, sizeof(CT_PATTERN_WX_10240), -8 }, }; UCHAR RG_PATTERN_W7_07600[] = { 0x48, 0x8b, 0xf8, 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x3b, 0xc3, 0x0f, 0x84 }; UCHAR RG_PATTERN_W8_08102[] = { 0x49, 0x8b, 0x04, 0x24, 0x48, 0x3b, 0x43, 0x18, 0x74 }; UCHAR RG_PATTERN_WX_10240[] = { 0x48, 0x8b, 0xf8, 0x48, 0x89, 0x44, 0x24, 0x40, 0x48, 0x85, 0xc0, 0x0f, 0x84 }; CALLBACK_SEARCH_QUERY RegistryCallbackQueries[14] = { { WINDOWS_INDEX::W7_07600, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"CmRegisterCallback"), RG_PATTERN_W7_07600, sizeof(RG_PATTERN_W7_07600), -9 }, { WINDOWS_INDEX::W8_08102, RTL_CONSTANT_STRING(L"CmSetCallbackObjectContext"), RTL_CONSTANT_STRING(L"CmGetCallbackVersion"), RG_PATTERN_W8_08102, sizeof(RG_PATTERN_W8_08102), -9 }, { WINDOWS_INDEX::W8_09431, RTL_CONSTANT_STRING(L"CmSetCallbackObjectContext"), RTL_CONSTANT_STRING(L"DbgkLkmdUnregisterCallback"), RG_PATTERN_W8_08102, sizeof(RG_PATTERN_W8_08102), -9 }, { WINDOWS_INDEX::WX_10240, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"FsRtlAllocateResource"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_10586, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"FsRtlAllocateResource"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_14393, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"FsRtlAllocateResource"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_15063, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"DbgkLkmdUnregisterCallback"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_16299, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"DbgkLkmdUnregisterCallback"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_17134, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"DbgkLkmdUnregisterCallback"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_17763, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"DbgkLkmdUnregisterCallback"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_18362, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"DbgkLkmdUnregisterCallback"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_18363, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"DbgkLkmdUnregisterCallback"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_19041, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"DbgkLkmdUnregisterCallback"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, { WINDOWS_INDEX::WX_19042, RTL_CONSTANT_STRING(L"CmUnRegisterCallback"), RTL_CONSTANT_STRING(L"DbgkLkmdUnregisterCallback"), RG_PATTERN_WX_10240, sizeof(RG_PATTERN_WX_10240), -9 }, }; UCHAR OB_PATTERN_W7_07600[] = { 0x41, 0x8a, 0xde, 0x44, 0x88, 0x74, 0x24, 0x47, 0x88, 0x5c, 0x24, 0x46, 0x4c, 0x89, 0x74, 0x24, 0x38, 0x4c, 0x89, 0x74, 0x24, 0x30, 0x49, 0x8b, 0xee, 0xc7, 0x44, 0x24, 0x48 }; UCHAR OB_PATTERN_W8_08102[] = { 0x41, 0x8a, 0xd8, 0x44, 0x88, 0x44, 0x24, 0x4f, 0x88, 0x5c, 0x24, 0x4e, 0x4c, 0x89, 0x44, 0x24, 0x38, 0x4d, 0x8b, 0xf0, 0x4c, 0x89, 0x44, 0x24, 0x30, 0xc7, 0x44, 0x24, 0x50 }; UCHAR OB_PATTERN_WX_10240[] = { 0x0f, 0xb7, 0x02, 0xff, 0xc9, 0x49, 0x03 }; CALLBACK_SEARCH_QUERY ObjectCallbackQueries[14] = { { WINDOWS_INDEX::W7_07600, RTL_CONSTANT_STRING(L"ObUnRegisterCallbacks"), RTL_CONSTANT_STRING(L"ObCreateObjectType"), OB_PATTERN_W7_07600, sizeof(OB_PATTERN_W7_07600), -4 }, { WINDOWS_INDEX::W8_08102, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"IoCreateController"), OB_PATTERN_W8_08102, sizeof(OB_PATTERN_W8_08102), -4 }, { WINDOWS_INDEX::W8_09431, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"RtlRunOnceInitialize"), OB_PATTERN_W8_08102, sizeof(OB_PATTERN_W8_08102), -4 }, { WINDOWS_INDEX::WX_10240, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"RtlRunOnceInitialize"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_10586, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"RtlRunOnceInitialize"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_14393, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"KseRegisterShim"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_15063, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"IoCreateDriver"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_16299, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"IoCreateDriver"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_17134, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"IoCreateDriver"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_17763, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"IoCreateDriver"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_18362, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"IoCreateDriver"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_18363, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"PoCreateThermalRequest"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_19041, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"IoCreateDriver"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, { WINDOWS_INDEX::WX_19042, RTL_CONSTANT_STRING(L"ObCreateObjectType"), RTL_CONSTANT_STRING(L"IoCreateDriver"), OB_PATTERN_WX_10240, sizeof(OB_PATTERN_WX_10240), 25 }, }; FLT_POSTOP_CALLBACK_STATUS PfltPostOperationCallback( PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID CompletionContext, FLT_POST_OPERATION_FLAGS Flags ) { UNREFERENCED_PARAMETER(Data); UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); UNREFERENCED_PARAMETER(Flags); return FLT_POSTOP_FINISHED_PROCESSING; } FLT_PREOP_CALLBACK_STATUS PfltPreOperationCallback( PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext ) { UNREFERENCED_PARAMETER(Data); UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); return FLT_PREOP_SUCCESS_NO_CALLBACK; } WINDOWS_INDEX GetWindowsIndex() { PfltPreOperationCallback(nullptr, nullptr, nullptr); PfltPostOperationCallback(nullptr, nullptr, nullptr, NULL); OSVERSIONINFOEXW OsVersionInfo; OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); RtlGetVersion((POSVERSIONINFOW)&OsVersionInfo); switch (OsVersionInfo.dwBuildNumber) { case 7600: case 7601: return WINDOWS_INDEX::W7_07600; break; case 8102: case 8250: case 9200: return WINDOWS_INDEX::W8_08102; case 9431: case 9600: return WINDOWS_INDEX::W8_09431; break; case 10240: // 1507 return WINDOWS_INDEX::WX_10240; break; case 10586: // 1511 return WINDOWS_INDEX::WX_10586; break; case 14393: // 1607 return WINDOWS_INDEX::WX_14393; break; case 15063: // 1703 return WINDOWS_INDEX::WX_15063; break; case 16299: // 1709 return WINDOWS_INDEX::WX_16299; break; case 17134: // 1803 return WINDOWS_INDEX::WX_17134; break; case 17763: // 1809 return WINDOWS_INDEX::WX_17763; break; case 18362: // 1903 return WINDOWS_INDEX::WX_18362; break; case 18363: // 1909 return WINDOWS_INDEX::WX_18363; break; case 19041: // 2004 return WINDOWS_INDEX::WX_19041; break; case 19042: // 20H2 return WINDOWS_INDEX::WX_19042; break; default: return WINDOWS_INDEX::Unsupported; } } NTSTATUS GetLoadImageNotifyCallbacks(OUT CALLBACK_INFO* CallbackArray, OUT ULONG* CallbackCount) { // Check if supported for this version of Windows. WINDOWS_INDEX WindowsIndex = GetWindowsIndex(); if (WindowsIndex == WINDOWS_INDEX::Unsupported) return STATUS_NOT_SUPPORTED; // Get search query. CALLBACK_SEARCH_QUERY Query = LoadImageCallbackQueries[(ULONG)WindowsIndex]; // Resolve function addresses to get the start and end of the search space. PUCHAR StartAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.StartFunction); PUCHAR EndAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.EndFunction); // Search for an offset to the PspLoadImageNotifyRoutine array. // This array contains the registered load image notification callbacks. PUCHAR PspLoadImageNotifyRoutine = nullptr; NTSTATUS Status = MemorySearch(StartAddress, EndAddress, Query.PatternBuffer, Query.PatternSize, &PspLoadImageNotifyRoutine); if (!NT_SUCCESS(Status)) return STATUS_NOT_FOUND; // Resolve the offset to get the address of PspLoadImageNotifyRoutine. PspLoadImageNotifyRoutine += Query.PatternOffset; PspLoadImageNotifyRoutine += *(PLONG)(PspLoadImageNotifyRoutine); PspLoadImageNotifyRoutine += sizeof(LONG); // Copy the callback addresses to the provided array. for (int i = 0; i < MAX_CALLBACKS_LOAD_IMAGE; i++) { // Check if a pointer to the callback exists at this index of the registered callbacks array. PVOID PointerToCallback = (PVOID)(*(PULONG64)((ULONG64)PspLoadImageNotifyRoutine + i * 8LL)); // If so, copy the callback address to the output array. if (PointerToCallback) { CallbackArray[i].Type = CALLBACK_TYPE::PsLoadImage; CallbackArray[i].Address = (PVOID)(*(PULONG64)((ULONG64)PointerToCallback & 0xFFFFFFFFFFFFFFF8)); } // Otherwise, exit the loop as there are no more callbacks left. else { *CallbackCount = i; break; } } return STATUS_SUCCESS; } NTSTATUS GetCreateProcessNotifyCallbacks(OUT CALLBACK_INFO* CallbackArray, OUT ULONG* CallbackCount) { // Check if supported for this version of Windows. WINDOWS_INDEX WindowsIndex = GetWindowsIndex(); if (WindowsIndex == WINDOWS_INDEX::Unsupported) return STATUS_NOT_SUPPORTED; // Get search query. CALLBACK_SEARCH_QUERY Query = CreateProcessCallbackQueries[(ULONG)WindowsIndex]; // Resolve function addresses to get the start and end of the search space. PUCHAR StartAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.StartFunction); PUCHAR EndAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.EndFunction); // Search for an offset to the PspCreateProcessNotifyRoutine array. PUCHAR PspSetCreateProcessNotifyRoutine = nullptr; NTSTATUS Status = MemorySearch(StartAddress, EndAddress, Query.PatternBuffer, Query.PatternSize, &PspSetCreateProcessNotifyRoutine); if (!NT_SUCCESS(Status)) return STATUS_NOT_FOUND; // Resolve the offset to get the address of PspCreateProcessNotifyRoutine. PspSetCreateProcessNotifyRoutine += Query.PatternOffset; PspSetCreateProcessNotifyRoutine += *(PLONG)(PspSetCreateProcessNotifyRoutine); PspSetCreateProcessNotifyRoutine += sizeof(LONG); // Copy the callback addresses to the provided array. for (int i = 0; i < MAX_CALLBACKS_CREATE_PROCESS; i++) { // Check if a pointer to the callback exists at this index of the registered callbacks array. PVOID PointerToCallback = (PVOID)(*(PULONG64)((ULONG64)PspSetCreateProcessNotifyRoutine + i * 8LL)); // If so, copy the callback address to the output array. if (PointerToCallback) { CallbackArray[i].Type = CALLBACK_TYPE::PsProcessCreation; CallbackArray[i].Address = (PVOID)(*(PULONG64)((ULONG64)PointerToCallback & 0xFFFFFFFFFFFFFFF8)); } // Otherwise, exit the loop as there are no more callbacks left. else { *CallbackCount = i; break; } } return STATUS_SUCCESS; } NTSTATUS GetCreateThreadNotifyCallbacks(OUT CALLBACK_INFO* CallbackArray, OUT ULONG* CallbackCount) { // Check if supported for this version of Windows. WINDOWS_INDEX WindowsIndex = GetWindowsIndex(); if (WindowsIndex == WINDOWS_INDEX::Unsupported) return STATUS_NOT_SUPPORTED; // Get search query. CALLBACK_SEARCH_QUERY Query = CreateThreadCallbackQueries[(ULONG)WindowsIndex]; // Resolve function addresses to get the start and end of the search space. PUCHAR StartAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.StartFunction); PUCHAR EndAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.EndFunction); // Search for an offset to the PspCreateThreadNotifyRoutine array. PUCHAR PspCreateThreadNotifyRoutine = nullptr; NTSTATUS Status = MemorySearch(StartAddress, EndAddress, Query.PatternBuffer, Query.PatternSize, &PspCreateThreadNotifyRoutine); if (!NT_SUCCESS(Status)) return STATUS_NOT_FOUND; // Resolve the offset to get the address of PspCreateThreadNotifyRoutine. PspCreateThreadNotifyRoutine += Query.PatternOffset; PspCreateThreadNotifyRoutine += *(PLONG)(PspCreateThreadNotifyRoutine); PspCreateThreadNotifyRoutine += sizeof(LONG); // Copy the callback addresses to the provided array. for (int i = 0; i < MAX_CALLBACKS_CREATE_THREAD; i++) { // Check if a pointer to the callback exists at this index of the registered callbacks array. PVOID PointerToCallback = (PVOID)(*(PULONG64)((ULONG64)PspCreateThreadNotifyRoutine + i * 8LL)); // If so, copy the callback address to the output array. if (PointerToCallback) { CallbackArray[i].Type = CALLBACK_TYPE::PsThreadCreation; CallbackArray[i].Address = (PVOID)(*(PULONG64)((ULONG64)PointerToCallback & 0xFFFFFFFFFFFFFFF8)); } // Otherwise, exit the loop as there are no more callbacks left. else { *CallbackCount = i; break; } } return STATUS_SUCCESS; } NTSTATUS GetRegistryCallbacks(OUT CALLBACK_INFO* CallbackArray, OUT ULONG* CallbackCount) { // Check if supported for this version of Windows. WINDOWS_INDEX WindowsIndex = GetWindowsIndex(); if (WindowsIndex == WINDOWS_INDEX::Unsupported) return STATUS_NOT_SUPPORTED; // Get search query. CALLBACK_SEARCH_QUERY Query = RegistryCallbackQueries[(ULONG)WindowsIndex]; // Resolve function addresses to get the start and end of the search space. PUCHAR StartAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.StartFunction); PUCHAR EndAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.EndFunction); // Search for an offset to the CallbackListHeadOrCmpCallBackVector linked-list head. PUCHAR CallbackListHeadOrCmpCallBackVector = nullptr; NTSTATUS Status = MemorySearch(StartAddress, EndAddress, Query.PatternBuffer, Query.PatternSize, &CallbackListHeadOrCmpCallBackVector); if (!NT_SUCCESS(Status)) return STATUS_NOT_FOUND; // Resolve the offset to get the address of CallbackListHeadOrCmpCallBackVector. CallbackListHeadOrCmpCallBackVector += Query.PatternOffset; CallbackListHeadOrCmpCallBackVector += *(PLONG)(CallbackListHeadOrCmpCallBackVector); CallbackListHeadOrCmpCallBackVector += sizeof(LONG); // Iterate through the linked list to populate the provided array. int i = 0; PLIST_ENTRY ListEntry = (PLIST_ENTRY)CallbackListHeadOrCmpCallBackVector; while (1) { PVOID CallbackFunction = *(PVOID*)((ULONG64)ListEntry + 0x28); CallbackArray[i].Type = CALLBACK_TYPE::CmRegistry; CallbackArray[i++].Address = CallbackFunction; ListEntry = ListEntry->Flink; // Break when back to first entry or array limit reached. if (((PVOID)ListEntry == (PVOID)CallbackListHeadOrCmpCallBackVector) || (i == MAX_CALLBACKS_REGISTRY)) { *CallbackCount = i; break; } }; return STATUS_SUCCESS; } NTSTATUS GetObjectCallbacks(OUT CALLBACK_INFO* CallbackArray, OUT ULONG* CallbackCount) { // Reset callback count to 0. *CallbackCount = 0; // Check if supported for this version of Windows. WINDOWS_INDEX WindowsIndex = GetWindowsIndex(); if (WindowsIndex == WINDOWS_INDEX::Unsupported) return STATUS_NOT_SUPPORTED; // Get search query. CALLBACK_SEARCH_QUERY Query = ObjectCallbackQueries[(ULONG)WindowsIndex]; // Resolve function addresses to get the start and end of the search space. PUCHAR StartAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.StartFunction); PUCHAR EndAddress = (PUCHAR)MmGetSystemRoutineAddress(&Query.EndFunction); // Search for an offset to the ObpTypeDirectoryObject linked-list head. PUCHAR ObpTypeDirectoryObject = nullptr; NTSTATUS Status = MemorySearch(StartAddress, EndAddress, Query.PatternBuffer, Query.PatternSize, &ObpTypeDirectoryObject); if (!NT_SUCCESS(Status)) return STATUS_NOT_FOUND; // Resolve the offset to get the address of CallbackListHeadOrCmpCallBackVector. ObpTypeDirectoryObject += Query.PatternOffset; ObpTypeDirectoryObject += *(PLONG)(ObpTypeDirectoryObject); ObpTypeDirectoryObject += sizeof(LONG); UNICODE_STRING TypesWhitelist[3] = { RTL_CONSTANT_STRING(L"Process"), RTL_CONSTANT_STRING(L"Thread"), RTL_CONSTANT_STRING(L"Desktop")}; POBJECT_DIRECTORY ObjectDirectory = (POBJECT_DIRECTORY)ObpTypeDirectoryObject; POBJECT_DIRECTORY_ENTRY* ObjectDirectoryEntries = (POBJECT_DIRECTORY_ENTRY*)ObjectDirectory->HashBuckets[0]; for (int i = 0; i < OBJECT_HASH_TABLE_SIZE; i++) { POBJECT_DIRECTORY_ENTRY ObjectDirectoryEntry = ObjectDirectoryEntries[i]; while (ObjectDirectoryEntry) { PVOID ObjectType = ObjectDirectoryEntry->ObjectType; PUNICODE_STRING ObjectName = (PUNICODE_STRING)((ULONG64)ObjectType + 0x10); UCHAR Offset = (GetWindowsIndex() == WINDOWS_INDEX::W7_07600) ? 0xC0 : 0xC8; POBJECT_CALLBACK_ENTRY ObjectCallbackEntry = (POBJECT_CALLBACK_ENTRY)((ULONG64)ObjectType + Offset); OBJECT_CALLBACK_TYPE ObjectCallbackType; if (!RtlCompareUnicodeString(ObjectName, &TypesWhitelist[0], TRUE)) ObjectCallbackType = OBJECT_CALLBACK_TYPE::Process; else if (!RtlCompareUnicodeString(ObjectName, &TypesWhitelist[1], TRUE)) ObjectCallbackType = OBJECT_CALLBACK_TYPE::Thread; else if (!RtlCompareUnicodeString(ObjectName, &TypesWhitelist[2], TRUE)) ObjectCallbackType = OBJECT_CALLBACK_TYPE::Desktop; else ObjectCallbackType = OBJECT_CALLBACK_TYPE::Unknown; if (ObjectCallbackType != OBJECT_CALLBACK_TYPE::Unknown) { do { if ((ObjectCallbackEntry->Active == 1) && (ObjectCallbackEntry->ObjectType)) { if (ObjectCallbackEntry->PreOperation) { switch (ObjectCallbackType) { case OBJECT_CALLBACK_TYPE::Process: CallbackArray[*CallbackCount].Type = CALLBACK_TYPE::ObProcessHandlePre; break; case OBJECT_CALLBACK_TYPE::Thread: CallbackArray[*CallbackCount].Type = CALLBACK_TYPE::ObThreadHandlePre; break; case OBJECT_CALLBACK_TYPE::Desktop: CallbackArray[*CallbackCount].Type = CALLBACK_TYPE::ObDesktopHandlePre; break; default: CallbackArray[*CallbackCount].Type = CALLBACK_TYPE::Unknown; break; } CallbackArray[*CallbackCount].Address = ObjectCallbackEntry->PreOperation; *CallbackCount += 1; } if (ObjectCallbackEntry->PostOperation) { switch (ObjectCallbackType) { case OBJECT_CALLBACK_TYPE::Process: CallbackArray[*CallbackCount].Type = CALLBACK_TYPE::ObProcessHandlePost; break; case OBJECT_CALLBACK_TYPE::Thread: CallbackArray[*CallbackCount].Type = CALLBACK_TYPE::ObThreadHandlePost; break; case OBJECT_CALLBACK_TYPE::Desktop: CallbackArray[*CallbackCount].Type = CALLBACK_TYPE::ObDesktopHandlePost; break; default: CallbackArray[*CallbackCount].Type = CALLBACK_TYPE::Unknown; break; } CallbackArray[*CallbackCount].Address = ObjectCallbackEntry->PostOperation; *CallbackCount += 1; } } ObjectCallbackEntry = (POBJECT_CALLBACK_ENTRY)ObjectCallbackEntry->CallbackList.Flink; } while (ObjectCallbackEntry != (POBJECT_CALLBACK_ENTRY)((ULONG64)ObjectType + Offset)); } ObjectDirectoryEntry = ObjectDirectoryEntry->ChainLink; } } return STATUS_SUCCESS; } NTSTATUS GetMinifilterCallbacks(OUT CALLBACK_INFO* CallbackArray, OUT ULONG* CallbackCount) { UNREFERENCED_PARAMETER(CallbackArray); UNREFERENCED_PARAMETER(CallbackCount); NTSTATUS Status = STATUS_SUCCESS; // Reset callback count to 0. *CallbackCount = 0; ULONG NumberFiltersReturned = 0; Status = FltEnumerateFilters(nullptr, 0, &NumberFiltersReturned); if (Status != STATUS_BUFFER_TOO_SMALL) return Status; SIZE_T BufferSize = sizeof(PFLT_FILTER) * NumberFiltersReturned; PFLT_FILTER* FilterList = (PFLT_FILTER*)ExAllocatePoolWithTag(NonPagedPool, BufferSize, DRIVER_TAG); if (!FilterList) return STATUS_INSUFFICIENT_RESOURCES; Status = FltEnumerateFilters(FilterList, (ULONG)BufferSize, &NumberFiltersReturned); if (!NT_SUCCESS(Status)) return Status; for (ULONG i = 0; i < NumberFiltersReturned; i++) { ULONG BytesReturned = 0; Status = FltGetFilterInformation(FilterList[i], FilterFullInformation, nullptr, 0, &BytesReturned); if (Status != STATUS_BUFFER_TOO_SMALL) continue; PFILTER_FULL_INFORMATION FullFilterInfo = (PFILTER_FULL_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, BytesReturned, DRIVER_TAG); if (!FullFilterInfo) continue; Status = FltGetFilterInformation(FilterList[i], FilterFullInformation, FullFilterInfo, BytesReturned, &BytesReturned); if (!NT_SUCCESS(Status)) continue; ULONG NumberInstancesReturned = 0; Status = FltEnumerateInstances(nullptr, FilterList[i], nullptr, 0, &NumberInstancesReturned); if (Status != STATUS_BUFFER_TOO_SMALL) continue; BufferSize = sizeof(PFLT_INSTANCE) * NumberInstancesReturned; PFLT_INSTANCE* InstanceList = (PFLT_INSTANCE*)ExAllocatePoolWithTag(NonPagedPool, BufferSize, DRIVER_TAG); if (!InstanceList) continue; Status = FltEnumerateInstances(nullptr, FilterList[i], InstanceList, NumberInstancesReturned, &NumberInstancesReturned); if (!NT_SUCCESS(Status)) continue; if (!NumberInstancesReturned) continue; for (ULONG j = 0x16; j < 0x32; j++) { // Hardcoding the offsets from https://github.com/gentilkiwi/mimikatz/blob/master/mimidrv/kkll_m_filters.c#L34. // This should probably be changed in the future. PVOID Callback = (PVOID)*(PULONG_PTR)((((ULONG_PTR)InstanceList[0]) + 0x90) + sizeof(PVOID) * j); if (Callback) { PVOID PreCallback = (PVOID) * (PULONG_PTR)(((ULONG_PTR)Callback) + 0x18); PVOID PostCallback = (PVOID) * (PULONG_PTR)(((ULONG_PTR)Callback) + 0x20); if (PreCallback) { CallbackArray[*CallbackCount].Type = (CALLBACK_TYPE)((j - 0x16) * 2 + 11); CallbackArray[*CallbackCount].Address = PreCallback; *CallbackCount += 1; } if (PostCallback) { CallbackArray[*CallbackCount].Type = (CALLBACK_TYPE)((j - 0x16) * 2 + 12); CallbackArray[*CallbackCount].Address = PostCallback; *CallbackCount += 1; } } } } return STATUS_SUCCESS; }