From 515a158c1cbbcaf45f8c23bebf56606862794c61 Mon Sep 17 00:00:00 2001 From: Ap3x Date: Fri, 21 Nov 2025 17:00:59 -0700 Subject: [PATCH 01/16] changes to debug print and wip of callbacks --- src/driver/include/callbacks.h | 16 +- src/driver/include/driver_constants.h | 5 +- src/driver/include/inject.h | 4 +- src/driver/include/pano_query.h | 2 +- src/driver/include/trace.h | 81 ++------- src/driver/src/callbacks.cpp | 240 ++------------------------ src/driver/src/driver.cpp | 31 ++-- src/driver/src/inject.cpp | 113 +----------- src/driver/src/pano_query.cpp | 21 +-- src/driver/src/trace.cpp | 100 ++--------- 10 files changed, 74 insertions(+), 539 deletions(-) diff --git a/src/driver/include/callbacks.h b/src/driver/include/callbacks.h index b4794a6..a481530 100644 --- a/src/driver/include/callbacks.h +++ b/src/driver/include/callbacks.h @@ -5,19 +5,18 @@ #define MAX_PATH 256 - -extern "C" PVOID NTAPI RtlImageDirectoryEntryToData( +EXTERN_C PVOID NTAPI RtlImageDirectoryEntryToData( _In_ PVOID BaseOfImage, _In_ BOOLEAN MappedAsImage, _In_ USHORT DirectoryEntry, _Out_ PULONG Size ); -extern "C" BOOLEAN NTAPI KeTestAlertThread( +EXTERN_C BOOLEAN NTAPI KeTestAlertThread( IN KPROCESSOR_MODE AlertMode ); -extern "C" BOOLEAN NTAPI PsIsProtectedProcess( +EXTERN_C BOOLEAN NTAPI PsIsProtectedProcess( _In_ PEPROCESS Process ); @@ -35,12 +34,9 @@ typedef struct _INJECT_SHELL } INJECT_SHELL, * PINJECT_SHELL; #pragma pack(pop) -extern "C" POBJECT_TYPE* IoDeviceObjectType; -//extern "C" PVOID RtlFindExportedRoutineByName(PVOID DllBase,PCHAR RoutineName); -EXTERN_C PVOID RtlImageDirectoryEntryToData(IN PVOID Base, - IN BOOLEAN MappedAsImage, - IN USHORT DirectoryEntry, - OUT PULONG Size); +EXTERN_C POBJECT_TYPE* IoDeviceObjectType; +EXTERN_C PVOID RtlImageDirectoryEntryToData(IN PVOID Base,IN BOOLEAN MappedAsImage,IN USHORT DirectoryEntry,OUT PULONG Size); VOID RemoveCallbacks(); + NTSTATUS InitializeKernelCallbacks(); diff --git a/src/driver/include/driver_constants.h b/src/driver/include/driver_constants.h index 1024da7..d671ac9 100644 --- a/src/driver/include/driver_constants.h +++ b/src/driver/include/driver_constants.h @@ -2,4 +2,7 @@ #define KERNEL_LINK L"\\Device\\Panoptes" #define KERNEL_LINK_SYM L"\\DosDevices\\Panoptes" #define KERNEL_DRIVER_SERVICE_NAME "Panoptes" -#define KERNEL_SERVICE_NAME "Panoptes" \ No newline at end of file +#define KERNEL_SERVICE_NAME "Panoptes" +#define PANOPTES_PREFIX_ERROR "[!] Panoptes: " +#define PANOPTES_PREFIX_WARNING "[-] Panoptes: " +#define PANOPTES_PREFIX_SUCCESS "[+] Panoptes: " \ No newline at end of file diff --git a/src/driver/include/inject.h b/src/driver/include/inject.h index a19e0be..f6fdca9 100644 --- a/src/driver/include/inject.h +++ b/src/driver/include/inject.h @@ -229,7 +229,7 @@ typedef KKERNEL_ROUTINE(NTAPI* PKKERNEL_ROUTINE); typedef VOID(NTAPI* PKRUNDOWN_ROUTINE)(_In_ PRKAPC Apc); -extern "C" VOID NTAPI KeInitializeApc( +EXTERN_C VOID NTAPI KeInitializeApc( _Out_ PRKAPC Apc, _In_ PRKTHREAD Thread, _In_ KAPC_ENVIRONMENT Environment, @@ -240,7 +240,7 @@ extern "C" VOID NTAPI KeInitializeApc( _In_opt_ PVOID NormalContext ); -extern "C" BOOLEAN NTAPI KeInsertQueueApc( +EXTERN_C BOOLEAN NTAPI KeInsertQueueApc( _Inout_ PRKAPC Apc, _In_opt_ PVOID SystemArgument1, _In_opt_ PVOID SystemArgument2, diff --git a/src/driver/include/pano_query.h b/src/driver/include/pano_query.h index c6f7298..8758b08 100644 --- a/src/driver/include/pano_query.h +++ b/src/driver/include/pano_query.h @@ -27,7 +27,7 @@ typedef struct _PROCESS_MITIGATION_POLICY_INFORMATION }Data; } PROCESS_MITIGATION_POLICY_INFORMATION, * PPROCESS_MITIGATION_POLICY_INFORMATION; -extern "C" NTSTATUS NTAPI ZwQueryInformationProcess( +EXTERN_C NTSTATUS NTAPI ZwQueryInformationProcess( HANDLE hProcess, PROCESSINFOCLASS infoType, /*out*/ PVOID pBuf, diff --git a/src/driver/include/trace.h b/src/driver/include/trace.h index f752996..24832a8 100644 --- a/src/driver/include/trace.h +++ b/src/driver/include/trace.h @@ -3,93 +3,38 @@ #include #pragma region TraceLogging Initialization -void TraceInit(); - -void TraceUninit(); +void TraceInitialize(BOOLEAN initialize = true); #pragma endregion #pragma region Driver Operations -void Log_DriverEntry( - PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath -); +void Log_DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath); -void Log_DriverExit( - PDRIVER_OBJECT DriverObject -); +void Log_DriverExit(PDRIVER_OBJECT DriverObject); #pragma endregion #pragma region Mail Slot Operations -void Log_MailSlotOpen( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -); +void Log_MailSlotOpen(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName); -void Log_MailSlotCreate( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -); +void Log_MailSlotCreate(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName); #pragma endregion #pragma region Named Pipe Operations -void Log_NamedPipeOpen( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -); +void Log_NamedPipeOpen(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName); -void Log_NamedPipeCreate( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -); +void Log_NamedPipeCreate(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName); #pragma endregion #pragma region File Operations -void Log_FileSuperseded( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -); +void Log_FileSuperseded(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName); -void Log_FileOverwritten( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -); +void Log_FileOverwritten(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName); -void Log_FileOpen( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName, - BOOLEAN Oplocked -); +void Log_FileOpen(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName,BOOLEAN Oplocked); -void Log_FileCreated( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName, - BOOLEAN Oplocked -); +void Log_FileCreated(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName,BOOLEAN Oplocked); -void Log_FileRead( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName, - LARGE_INTEGER FileOffset, - ULONG ReadLength, - BOOLEAN Compressed -); +void Log_FileRead(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName,LARGE_INTEGER FileOffset,ULONG ReadLength,BOOLEAN Compressed); -void Log_FileWrite( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName, - LARGE_INTEGER FileOffset, - ULONG ReadLength, - BOOLEAN Compressed -); +void Log_FileWrite(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName,LARGE_INTEGER FileOffset,ULONG ReadLength,BOOLEAN Compressed); #pragma endregion \ No newline at end of file diff --git a/src/driver/src/callbacks.cpp b/src/driver/src/callbacks.cpp index b8d8cdc..bdc8be0 100644 --- a/src/driver/src/callbacks.cpp +++ b/src/driver/src/callbacks.cpp @@ -1,5 +1,6 @@ #include "callbacks.h" #include "inject.h" +#include "driver_constants.h" #include "pano_query.h" #include #include "shellcode.h" @@ -9,13 +10,7 @@ LIST_ENTRY g_ProcessList{}; KSPIN_LOCK g_ProcessListLock{}; PVOID g_ObRegistrationHandle{}; -PVOID -NTAPI -RtlxFindExportedRoutineByName( - _In_ PVOID DllBase, - _In_ PANSI_STRING ExportName -) -{ +PVOID NTAPI RtlxFindExportedRoutineByName(_In_ PVOID DllBase,_In_ PANSI_STRING ExportName) { // // RtlFindExportedRoutineByName is not exported by ntoskrnl until Win10. // Following code is borrowed from ReactOS. @@ -135,75 +130,6 @@ RtlxFindExportedRoutineByName( return Function; } -//QUERY_INFO_PROCESS ZwQueryInformationProcessPtr; -// -//NTSTATUS InitializeZwQueryInformationProcessCallback() { -// UNICODE_STRING routineName; -// RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess"); -// //https://stackoverflow.com/questions/3707133/how-to-use-zwqueryinformationprocess-to-get-processimagefilename-in-a-kernel-dri -// ZwQueryInformationProcessPtr = (QUERY_INFO_PROCESS)MmGetSystemRoutineAddress(&routineName); -// if (ZwQueryInformationProcessPtr == NULL) { -// DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Cannot resolve ZwQueryInformationProcess\n"); -// return STATUS_INVALID_HANDLE; -// } -// -// return STATUS_SUCCESS; -//} - -OB_PREOP_CALLBACK_STATUS PreOperationCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation) -{ - PAGED_CODE(); - UNREFERENCED_PARAMETER(RegistrationContext); - UNREFERENCED_PARAMETER(OperationInformation); - //if (OperationInformation->ObjectType == *IoDeviceObjectType) - //{ - // ULONG returnLength; - // PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)OperationInformation->Object; - // // Query the object name - // NTSTATUS status = ObQueryNameString(deviceObject, NULL, 0, &returnLength); - // if (status != STATUS_INFO_LENGTH_MISMATCH) - // { - // return OB_PREOP_SUCCESS; - // } - // // Allocate memory for the name information - // POBJECT_NAME_INFORMATION objectNameInfo = NULL; - // objectNameInfo = (POBJECT_NAME_INFORMATION)ExAllocatePool2(POOL_FLAG_NON_PAGED, returnLength, 'NveD'); - // if (objectNameInfo == NULL) - // { - // return OB_PREOP_SUCCESS; - // } - // // Get the object name - // UNICODE_STRING deviceName; - // // Initialize the UNICODE_STRING - // RtlInitUnicodeString(&deviceName, NULL); - // // Allocate a buffer for the device name - // deviceName.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_NON_PAGED, returnLength, 'NveD'); - // if (deviceName.Buffer == NULL) - // { - // return OB_PREOP_SUCCESS; - // } - // status = ObQueryNameString(deviceObject, objectNameInfo, returnLength, &returnLength); - // if (NT_SUCCESS(status)) - // { - // // Copy the name to the output parameter - // RtlCopyUnicodeString(&deviceName, &objectNameInfo->Name); - // } - // if (deviceName.Buffer && wcsstr(deviceName.Buffer, L"\\Device\\NamedPipe\\") != NULL) - // { - // DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Named Pipe created: %wZ\n", deviceName.Buffer); - // } - // return OB_PREOP_SUCCESS; - //} - - return OB_PREOP_SUCCESS; -} - -//void PostOperationCallback(PVOID RegistrationContext,POB_POST_OPERATION_INFORMATION OperationInformation) -//{ -// UNREFERENCED_PARAMETER(OperationInformation); -// UNREFERENCED_PARAMETER(RegistrationContext); -//} - PPANO_PROCESS_INFO GetProcessInfo(HANDLE ProcessId) { //KIRQL OldIRQL; @@ -244,12 +170,6 @@ void NTAPI KernelRoutine(PKAPC apc, PKNORMAL_ROUTINE* NormalRoutine, PVOID* Norm ExFreePool(apc); } -struct InjectArgs { - PUNICODE_STRING DLLPath; - PUNICODE_STRING DllName; - PVOID DllHandle; -}; - BOOLEAN CanInject(PPANO_PROCESS_INFO processInfo) { if (processInfo->ntdllLoaded && processInfo->kernel32Loaded && processInfo->kernelBaseLoaded) @@ -390,7 +310,6 @@ VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIM UNICODE_STRING ntdllLoadImage; RtlInitUnicodeString(&ntdllLoadImage, L"ntdll.dll"); if (wcsstr(FullImageName->Buffer, ntdllLoadImage.Buffer) != NULL) { - //DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Loaded ntdll in %llu\n", (ULONG64)ProcessId); processInfo->ntdllLoaded = TRUE; return; } @@ -398,7 +317,6 @@ VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIM UNICODE_STRING kernel32LoadImage; RtlInitUnicodeString(&kernel32LoadImage, L"kernel32.dll"); if (wcsstr(FullImageName->Buffer, kernel32LoadImage.Buffer) != NULL) { - //DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Loaded kernel32 in %llu\n", (ULONG64)ProcessId); processInfo->kernel32Loaded = TRUE; processInfo->kernel32BaseAddress = ImageInfo->ImageBase; return; @@ -407,7 +325,6 @@ VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIM UNICODE_STRING kernelbaseLoadImage; RtlInitUnicodeString(&kernelbaseLoadImage, L"KernelBase.dll"); if (wcsstr(FullImageName->Buffer, kernelbaseLoadImage.Buffer) != NULL) { - //DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Loaded kernelbase in %llu\n", (ULONG64)ProcessId); processInfo->kernelBaseLoaded = TRUE; return; } @@ -423,95 +340,22 @@ VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIM PUNICODE_STRING processPath{}; status = SeLocateProcessImageName(targetProcess, &processPath); if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Failed to get process name, status: 0x%X\n", status); + KdPrint((PANOPTES_PREFIX_WARNING "Failed to get process name, status: 0x%X\n", status)); return; } processInfo->is64Bit = Is64BitProcess(targetProcess); if (processInfo->is64Bit) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Injecting into x64: (%llu) %wZ\n", (ULONG64)ProcessId, processPath); + KdPrint((PANOPTES_PREFIX_SUCCESS "Injecting into x64: (%llu) %wZ\n", (ULONG64)ProcessId, processPath)); } else { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Injecting Into x86: (%llu) %wZ\n", (ULONG64)ProcessId, processPath); + KdPrint((PANOPTES_PREFIX_SUCCESS "Injecting Into x86: (%llu) %wZ\n", (ULONG64)ProcessId, processPath)); } InstallKernelModeApcToInjectDll(ProcessId); processInfo->Injected = TRUE; } - //PEPROCESS ProcessStruct; - //PsLookupProcessByProcessId(ProcessId, &ProcessStruct); - // We dont want to deal with trying to inject into protected processes - //if (PsIsProtectedProcess(ProcessStruct)) - //{ - // //RemoveProcessInfoByProcessId(ProcessId); - // return; - //} - //if (ZwQueryInformationProcessPtr == NULL) - //{ - // DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Cannot resolve ZwQueryInformationProcess\n"); - // InitializeZwQueryInformationProcessCallback(); - //} - //ZwQueryInformationProcessPtr( - // ProcessStruct, - // ProcessBasicInformation, - // NULL, - // 0, - // NULL - //); - //HANDLE processHandle; - //NTSTATUS status = ObOpenObjectByPointer( - // ProcessStruct, - // OBJ_KERNEL_HANDLE, - // NULL, - // PROCESS_ALL_ACCESS, - // *PsProcessType, - // KernelMode, - // &processHandle - //); - //PROCESS_BASIC_INFORMATION pbi; - //ULONG returnLength; - //status = ZwQueryInformationProcessPtr( - // processHandle, - // ProcessBasicInformation, - // &pbi, - // sizeof(PROCESS_BASIC_INFORMATION), - // &returnLength - //); - //if (!processInfo->LdrLoadDllRoutineAddress) { - // ANSI_STRING ldrLoadDll; - // RtlInitAnsiString(&ldrLoadDll, "LdrLoadDll"); - // UNICODE_STRING kernel32LoadImage; - // RtlInitUnicodeString(&kernel32LoadImage, L"*\\ntdll.dll"); - // if (FsRtlIsNameInExpression(&kernel32LoadImage, FullImageName, TRUE, NULL)) { - // processInfo->LdrLoadDllRoutineAddress = RtlFindExportedRoutineByName((PVOID)ImageInfo->ImageBase, ldrLoadDll.Buffer); - // processInfo->NtdllLoaded = TRUE; - // return; - // } - //} - //else - //{ - // //UINT64 Process, ProcessHead; - // //NTSTATUS status = PsLookupProcessByProcessId(ProcessId, (PEPROCESS*)&ProcessHead); - // //if (!NT_SUCCESS(status)) - // //{ - // // return; - // //} - // //Process = ProcessHead; - // //UINT64 Thread, ThreadHead = *(UINT64*)(Process + 0x5e0) - 0x538; // Thread->ThreadListHead.Flink - // //Thread = ThreadHead; - // //bool found = false; - // //do { - // // if (*(UINT32*)(Thread + 0x74) & (1 << 4)) { // Thread.Tcb.MiscFlags & Alertable - // // found = true; - // // break; - // // } - // // Thread = *(UINT64*)(Thread + 0x538) - 0x538; // Thread->ThreadListEntry.Flink - // //} while (Thread != ThreadHead); - // DbgBreakPoint(); - // InjectDLL(ProcessId, processInfo); - //} - return; } @@ -520,38 +364,10 @@ VOID ProcessCreateCallback(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIF UNREFERENCED_PARAMETER(Process); if (CreateInfo != NULL) { - UNICODE_STRING onlyProc; - RtlInitUnicodeString(&onlyProc, L"die.exe"); - if (wcsstr(CreateInfo->ImageFileName->Buffer, onlyProc.Buffer) != NULL) { - PPANO_PROCESS_INFO processInfo = (PPANO_PROCESS_INFO)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(PANO_PROCESS_INFO), 'corP'); - if (processInfo) { - processInfo->ProcessId = ProcessId; - processInfo->Injected = FALSE; - processInfo->ntdllLoaded = FALSE; - processInfo->kernel32Loaded = FALSE; - processInfo->kernelBaseLoaded = FALSE; - - InsertTailList(&g_ProcessList, &processInfo->ListEntry); - } - - PROCESS_MITIGATION_POLICY_INFORMATION policyInfo{}; - NTSTATUS status = QueryProcessMitigationPolicy(ProcessId, &policyInfo); - if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Failed to get process mitigation policy, status: 0x%X\n", status); - } - } - - //if (CreateInfo->ImageFileName->Buffer != NULL) { - //DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Process Starting: %wZ\n", CreateInfo->ImageFileName->Buffer); - - // //EventWriteProcessCreation(NULL, (UINT64)ProcessId, processPath->Buffer, (UINT64)CreateInfo->ParentProcessId, 0, (UINT64)&policyInfo); - // EventWriteProcessCreation(NULL, (UINT64)ProcessId, processPath->Buffer, (UINT64)CreateInfo->ParentProcessId, 0, 0); - // ExFreePool(processPath->Buffer); - //} } else { - RemoveProcessInfo(ProcessId); + } } @@ -559,39 +375,10 @@ NTSTATUS InitializeKernelCallbacks() { PAGED_CODE(); NTSTATUS status; - //UNICODE_STRING callbackAltitude; - ////https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/load-order-groups-and-altitudes-for-minifilter-drivers - //RtlInitUnicodeString(&callbackAltitude, L"1931"); - - //OB_CALLBACK_REGISTRATION callbackRegistration; - //OB_OPERATION_REGISTRATION operationRegistration; - //RtlSecureZeroMemory(&operationRegistration, sizeof(OB_OPERATION_REGISTRATION)); - //RtlSecureZeroMemory(&callbackRegistration, sizeof(OB_CALLBACK_REGISTRATION)); - //operationRegistration.ObjectType = PsProcessType; - //operationRegistration.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE; - //operationRegistration.PreOperation = PreOperationCallback; - ////operationRegistration.PostOperation = PostOperationCallback; - //operationRegistration.PostOperation = NULL; - - //callbackRegistration.Version = OB_FLT_REGISTRATION_VERSION; - //callbackRegistration.OperationRegistrationCount = 1; - //callbackRegistration.Altitude = callbackAltitude; - //callbackRegistration.OperationRegistration = &operationRegistration; - //callbackRegistration.RegistrationContext = NULL; - - //status = ObRegisterCallbacks(&callbackRegistration, &g_ObRegistrationHandle); - //if (!NT_SUCCESS(status)) { - // DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] Panoptes: Driver Failed to Set Object Registration Callbacks - Ensure /INTEGRITYCHECK is added to the linker options\n"); - // return status; - //} - //DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Set Object Registration Callbacks\n"); - - InitializeListHead(&g_ProcessList); - //KeInitializeSpinLock(&g_ProcessListLock); + status = PsSetCreateProcessNotifyRoutineEx(ProcessCreateCallback, FALSE); if (!NT_SUCCESS(status)) { - //ObUnRegisterCallbacks(g_ObRegistrationHandle); - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] Panoptes: Driver Failed to Set Process Creation Notify Routine Notify Routine - Ensure /INTEGRITYCHECK is added to the linker options\n"); + KdPrint((PANOPTES_PREFIX_ERROR "Driver Failed to Set Process Creation Notify Routine Notify Routine - Ensure /INTEGRITYCHECK is added to the linker options\n")); return status; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Set Process Creation Notify Callbacks\n"); @@ -599,20 +386,23 @@ NTSTATUS InitializeKernelCallbacks() status = PsSetLoadImageNotifyRoutine(LoadImageNotifyRoutine); if (!NT_SUCCESS(status)) { NTSTATUS removeStatus = PsSetCreateProcessNotifyRoutineEx(ProcessCreateCallback, TRUE); + if (!NT_SUCCESS(removeStatus)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] Panoptes: Driver Failed to remove callback for Set Process Creation Notify Routine Notify Routine\n"); + KdPrint((PANOPTES_PREFIX_ERROR "Driver Failed to remove callback for Set Process Creation Notify Routine Notify Routine\n")); return removeStatus; } - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] Panoptes: Driver Failed to Set Process Load Image Notify Routine - Ensure /INTEGRITYCHECK is added to the linker options\n"); + + KdPrint((PANOPTES_PREFIX_ERROR "Driver Failed to Set Process Load Image Notify Routine - Ensure / INTEGRITYCHECK is added to the linker options\n")); + return status; } - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Set Image Load Notify Callbacks\n"); + + KdPrint((PANOPTES_PREFIX_SUCCESS "Set Image Load Notify Callbacks\n")); return STATUS_SUCCESS; } VOID RemoveCallbacks() { - //ObUnRegisterCallbacks(g_ObRegistrationHandle); PsSetCreateProcessNotifyRoutineEx(ProcessCreateCallback, TRUE); PsRemoveLoadImageNotifyRoutine(LoadImageNotifyRoutine); return; diff --git a/src/driver/src/driver.cpp b/src/driver/src/driver.cpp index d598295..f45e25e 100644 --- a/src/driver/src/driver.cpp +++ b/src/driver/src/driver.cpp @@ -3,51 +3,48 @@ #include "pano_query.h" #include "trace.h" #include "pano_filter.h" +#include +#include UNICODE_STRING g_deviceName; UNICODE_STRING g_symLink; PDEVICE_OBJECT g_deviceObject; UNICODE_STRING g_SymbolicLinkName; -void UnloadPanoptes(PDRIVER_OBJECT DriverObject) -{ +void UnloadPanoptes(PDRIVER_OBJECT DriverObject) { PAGED_CODE(); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Driver Exit\n"); Log_DriverExit(DriverObject); //IoDeleteDevice(driver_object); //IoDeleteSymbolicLink(&g_symLink); - TraceUninit(); RemoveCallbacks(); } -NTSTATUS DriverEntry( - PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath -) -{ +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) { PAGED_CODE(); DriverObject->DriverUnload = UnloadPanoptes; - TraceInit(); + TraceInitialize(); + Log_DriverEntry(DriverObject, RegistryPath); - NTSTATUS status = FilterInit(&DriverObject); - if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] Panoptes: An error occured when attempting to initialized filter\n"); - return status; - } + //NTSTATUS status = FilterInit(&DriverObject); + //if (!NT_SUCCESS(status)) { + // KdPrint(( PANOPTES_PREFIX_ERROR "An error occured when attempting to initialized filter\n")); + // return status; + //} //status = InitializeDriverLink(driver_object); //if (!NT_SUCCESS(status)) //{ - // DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] Panoptes: An error occured when attempting to initialized device pipe\n"); + // KdPrint(( PANOPTES_PREFIX_ERROR "An error occured when attempting to initialized device pipe\n")); // return status; //} - status = InitializeKernelCallbacks(); + NTSTATUS status = InitializeKernelCallbacks(); if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] Panoptes: An error occured when attempting to initialized kernel callbacks\n"); + KdPrint(( PANOPTES_PREFIX_ERROR "An error occured when attempting to initialized kernel callbacks\n")); return status; } diff --git a/src/driver/src/inject.cpp b/src/driver/src/inject.cpp index 0dd323a..a957c2a 100644 --- a/src/driver/src/inject.cpp +++ b/src/driver/src/inject.cpp @@ -1,13 +1,6 @@ #include "structs.h" #include "inject.h" -typedef NTSTATUS(NTAPI* PLDRLOADDLL)( - PWCHAR PathToFile, - ULONG Flags, - PUNICODE_STRING ModuleFileName, - PHANDLE ModuleHandle - ); - NTSTATUS WriteToTargetProcessMemory(PEPROCESS targetProcess, PVOID TargetAddress, SIZE_T Size, PVOID DataToWrite) { KAPC_STATE apcState; @@ -104,108 +97,4 @@ NTSTATUS AllocateMemoryInUserProcess(PEPROCESS targetProcess, SIZE_T Size, PVOID ObDereferenceObject(targetProcess); return status; -} - -//void kernel_free_kapc(PKAPC apc, PKNORMAL_ROUTINE*, PVOID*, PVOID*, PVOID*) -//{ -// delete apc; -// ExReleaseRundownProtection(&PendingOperations); -// -//} -// -//void rundown_free_kapc(PKAPC apc) -//{ -// delete apc; -// ExReleaseRundownProtection(&PendingOperations); -// -//} - -struct InjectArgs { - PCWSTR DLLPath; - PUNICODE_STRING DllName; - PVOID* DllHandle; -}; - -// -//bool InjectDLL(HANDLE ProcessId, PVOID processInfo) -//{ -// PPANO_PROCESS_INFO panoProcessInfo = (PPANO_PROCESS_INFO)processInfo; -// InjectArgs args; -// args.DllHandle = NULL; -// args.DLLPath = L"C:\\Program Files\\Panoptes"; -// PVOID allocatedAddressContainingShellcode; -// PVOID shellcodeAddress; -// // Get the EPROCESS pointer for the target process -// PEPROCESS targetProcess = NULL; -// NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &targetProcess); -// if (!NT_SUCCESS(status)) { -// return status; -// } -// -// if (panoProcessInfo->Is64Bit) -// { -// UNICODE_STRING moduleName; -// RtlInitUnicodeString(&moduleName, L"PanoptesDLLx64.dll"); -// args.DllName = &moduleName; -// SIZE_T dllPathx64Size = sizeof(_code_rawx64); -// status = AllocateMemoryInUserProcess(targetProcess, dllPathx64Size, &allocatedAddressContainingShellcode); -// if (!NT_SUCCESS(status)) { -// return false; -// } -// status = WriteToTargetProcessMemory(targetProcess, &allocatedAddressContainingShellcode, dllPathx64Size, _code_rawx64); -// shellcodeAddress = (PVOID)((UCHAR*)allocatedAddressContainingShellcode + FUNCTION_OFFSETx64); -// } -// else -// { -// UNICODE_STRING moduleName; -// RtlInitUnicodeString(&moduleName, L"PanoptesDLLx86.dll"); -// args.DllName = &moduleName; -// SIZE_T dllPathx86Size = sizeof(_code_rawx86); -// status = AllocateMemoryInUserProcess(targetProcess, dllPathx86Size, &allocatedAddressContainingShellcode); -// if (!NT_SUCCESS(status)) { -// return false; -// } -// status = WriteToTargetProcessMemory(targetProcess, &allocatedAddressContainingShellcode, dllPathx86Size, _code_rawx86); -// shellcodeAddress = (PVOID)((UCHAR*)allocatedAddressContainingShellcode + FUNCTION_OFFSETx86); -// } -// -// // Attach to the target process -// KAPC_STATE ApcState; -// KeStackAttachProcess(targetProcess, &ApcState); -// -// KAPC* apc = static_cast(ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KAPC), 'ldll')); -// if (nullptr == apc) { -// return false; -// } -// -// DbgBreakPoint(); -// -// KeInitializeApc( -// apc, -// KeGetCurrentThread(), -// OriginalApcEnvironment, -// NULL, -// NULL, -// reinterpret_cast(shellcodeAddress), -// UserMode, -// &args -// ); -// -// if (!KeInsertQueueApc( -// apc, -// NULL, -// NULL, -// IO_NO_INCREMENT -// )) -// { -// if (apc) { -// ExFreePoolWithTag(apc, 0); -// } -// KeUnstackDetachProcess(&ApcState); -// return false; -// } -// -// KeUnstackDetachProcess(&ApcState); -// //panoProcessInfo->Injected = true; -// return true; -//} +} \ No newline at end of file diff --git a/src/driver/src/pano_query.cpp b/src/driver/src/pano_query.cpp index e34e3aa..410f5ca 100644 --- a/src/driver/src/pano_query.cpp +++ b/src/driver/src/pano_query.cpp @@ -1,7 +1,6 @@ #include "pano_query.h" #include - NTSTATUS QueryProcessMitigationPolicy(HANDLE ProcessId, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo) { UNREFERENCED_PARAMETER(policyInfo); HANDLE hProcess; @@ -50,22 +49,4 @@ NTSTATUS QueryProcessMitigationPolicy(HANDLE ProcessId, PROCESS_MITIGATION_POLIC ZwClose(hProcess); return STATUS_SUCCESS; -} - - -//NTSTATUS InitializeZwQueryInformationProcess() { -// UNICODE_STRING routineName; -// RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess"); -// //https://stackoverflow.com/questions/3707133/how-to-use-zwqueryinformationprocess-to-get-processimagefilename-in-a-kernel-dri -// ZwQueryInformationProcess = (QUERY_INFO_PROCESS)MmGetSystemRoutineAddress(&routineName); -// if (ZwQueryInformationProcess == NULL) { -// DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Cannot resolve ZwQueryInformationProcess\n"); -// return STATUS_INVALID_HANDLE; -// } -// -// return STATUS_SUCCESS; -//} - - - - +} \ No newline at end of file diff --git a/src/driver/src/trace.cpp b/src/driver/src/trace.cpp index bd9efb5..efaf3f4 100644 --- a/src/driver/src/trace.cpp +++ b/src/driver/src/trace.cpp @@ -7,23 +7,18 @@ PDRIVER_OBJECT g_DriverObject; TRACELOGGING_DEFINE_PROVIDER(g_hPanoProvider, "Panoptes", (0x7036af95, 0x9daf, 0x4486, 0x8d, 0x93, 0x70, 0x5, 0xd4, 0x5a, 0x6a, 0x6)); -void TraceInit() +void TraceInitialize(BOOLEAN initialize) { + if (!initialize) { + TraceLoggingUnregister(g_hPanoProvider); + } + TraceLoggingRegister(g_hPanoProvider); } - -void TraceUninit() -{ - TraceLoggingUnregister(g_hPanoProvider); -} #pragma endregion #pragma region Driver Operations -void Log_DriverEntry( - PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath -) -{ +void Log_DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) { g_DriverObject = DriverObject; TraceLoggingWrite(g_hPanoProvider, "PanoptesStart", @@ -31,34 +26,21 @@ void Log_DriverEntry( TraceLoggingUnicodeString(RegistryPath, "RegPath")); } -void Log_DriverExit( - PDRIVER_OBJECT DriverObject -) -{ +void Log_DriverExit(PDRIVER_OBJECT DriverObject) { TraceLoggingWrite(g_hPanoProvider, "PanoptesExit", TraceLoggingPointer(DriverObject)); } #pragma endregion #pragma region Mail Slot Operations -void Log_MailSlotOpen( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -) -{ +void Log_MailSlotOpen(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName) { TraceLoggingWrite(g_hPanoProvider, "MailSlotOpen", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), TraceLoggingWideString(FileName, "MailSlotName")); } -void Log_MailSlotCreate( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -) -{ +void Log_MailSlotCreate(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName) { TraceLoggingWrite(g_hPanoProvider, "MailSlotCreate", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), @@ -67,24 +49,14 @@ void Log_MailSlotCreate( #pragma endregion #pragma region Named Pipe Operations -void Log_NamedPipeCreate( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -) -{ +void Log_NamedPipeCreate(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName) { TraceLoggingWrite(g_hPanoProvider, "NamedPipeCreate", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), TraceLoggingWideString(FileName, "NamedPipeName")); } -void Log_NamedPipeOpen( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -) -{ +void Log_NamedPipeOpen(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName){ TraceLoggingWrite(g_hPanoProvider, "NamedPipeOpen", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), @@ -94,13 +66,7 @@ void Log_NamedPipeOpen( #pragma region File Operations -void Log_FileCreated( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName, - BOOLEAN Oplocked -) -{ +void Log_FileCreated(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName,BOOLEAN Oplocked) { TraceLoggingWrite(g_hPanoProvider, "FileCreated", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), @@ -108,13 +74,7 @@ void Log_FileCreated( TraceLoggingBool(Oplocked, "Oplocked")); } -void Log_FileOpen( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName, - BOOLEAN Oplocked -) -{ +void Log_FileOpen(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName,BOOLEAN Oplocked) { TraceLoggingWrite(g_hPanoProvider, "FileOpened", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), @@ -122,27 +82,14 @@ void Log_FileOpen( TraceLoggingBool(Oplocked, "Oplocked")); } -void Log_FileOverwritten( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -) -{ +void Log_FileOverwritten(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName) { TraceLoggingWrite(g_hPanoProvider, "FileOverwritten", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), TraceLoggingWideString(FileName, "FileName")); } -void Log_FileRead( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName, - LARGE_INTEGER FileOffset, - ULONG ReadLength, - BOOLEAN Compressed -) -{ +void Log_FileRead(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName,LARGE_INTEGER FileOffset,ULONG ReadLength,BOOLEAN Compressed) { TraceLoggingWrite(g_hPanoProvider, "FileRead", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), @@ -152,15 +99,7 @@ void Log_FileRead( TraceLoggingBoolean(Compressed, "CompressedFile")); } -void Log_FileWrite( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName, - LARGE_INTEGER FileOffset, - ULONG ReadLength, - BOOLEAN Compressed -) -{ +void Log_FileWrite(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName,LARGE_INTEGER FileOffset,ULONG ReadLength,BOOLEAN Compressed) { TraceLoggingWrite(g_hPanoProvider, "FileWrite", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), @@ -170,12 +109,7 @@ void Log_FileWrite( TraceLoggingBoolean(Compressed, "CompressedFile")); } -void Log_FileSuperseded( - HANDLE ProcessId, - HANDLE ThreadId, - PWCH FileName -) -{ +void Log_FileSuperseded(HANDLE ProcessId,HANDLE ThreadId,PWCH FileName) { TraceLoggingWrite(g_hPanoProvider, "FileSuperseded", TraceLoggingValue(ProcessId, "SourceProcessId"), TraceLoggingValue(ThreadId, "SourceThreadId"), From 47f516c39b19c621830653e49296821186f79b6a Mon Sep 17 00:00:00 2001 From: Ap3x Date: Tue, 25 Nov 2025 22:08:47 -0700 Subject: [PATCH 02/16] Clean up driver flow and unused code --- CppProperties.json | 21 - src/driver/CMakeLists.txt | 15 +- src/driver/include/callbacks.h | 39 +- .../include/{pano_filter.h => filter.h} | 0 src/driver/include/inject.h | 20 +- src/driver/include/ioctl.h | 2 +- .../include/{driver_constants.h => pch.h} | 7 +- src/driver/include/shellcode.h | 170 -------- src/driver/include/state.h | 37 ++ src/driver/include/structs.h | 14 - src/driver/include/trace.h | 2 +- src/driver/include/{pano_query.h => utils.h} | 25 +- src/driver/src/callbacks.cpp | 406 +++--------------- src/driver/src/driver.cpp | 16 +- .../src/{pano_filter.cpp => filter.cpp} | 49 +-- src/driver/src/inject.cpp | 187 ++++---- src/driver/src/pano_query.cpp | 52 --- src/driver/src/state.cpp | 41 ++ src/driver/src/utils.cpp | 206 +++++++++ 19 files changed, 521 insertions(+), 788 deletions(-) delete mode 100644 CppProperties.json rename src/driver/include/{pano_filter.h => filter.h} (100%) rename src/driver/include/{driver_constants.h => pch.h} (66%) delete mode 100644 src/driver/include/shellcode.h create mode 100644 src/driver/include/state.h delete mode 100644 src/driver/include/structs.h rename src/driver/include/{pano_query.h => utils.h} (70%) rename src/driver/src/{pano_filter.cpp => filter.cpp} (91%) delete mode 100644 src/driver/src/pano_query.cpp create mode 100644 src/driver/src/state.cpp create mode 100644 src/driver/src/utils.cpp diff --git a/CppProperties.json b/CppProperties.json deleted file mode 100644 index 6017def..0000000 --- a/CppProperties.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "configurations": [ - { - "inheritEnvironments": [ - "msvc_x64" - ], - "name": "x64-Release", - "includePath": [ - "${env.INCLUDE}", - "${workspaceRoot}\\**" - ], - "defines": [ - "WIN32", - "NDEBUG", - "UNICODE", - "_UNICODE" - ], - "intelliSenseMode": "windows-msvc-x64" - } - ] -} \ No newline at end of file diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index 1ff7304..f93a353 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -9,29 +9,28 @@ find_package(WDK REQUIRED) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) - # Define source files set(SOURCE_FILES src/callbacks.cpp src/driver.cpp - src/pano_filter.cpp + src/filter.cpp src/inject.cpp src/ioctl.cpp - src/pano_query.cpp src/trace.cpp + src/state.cpp + src/utils.cpp ) # Define header files set(HEADER_FILES - include/driver_constants.h - include/pano_filter.h + include/pch.h + include/filter.h include/inject.h include/ioctl.h - include/pano_query.h - include/shellcode.h - include/structs.h include/trace.h include/callbacks.h + include/state.h + include/utils.h ) # Add the driver target diff --git a/src/driver/include/callbacks.h b/src/driver/include/callbacks.h index a481530..6b8f1b3 100644 --- a/src/driver/include/callbacks.h +++ b/src/driver/include/callbacks.h @@ -1,42 +1,7 @@ #pragma once -#include "structs.h" -#include -#include +#include "pch.h" -#define MAX_PATH 256 - -EXTERN_C PVOID NTAPI RtlImageDirectoryEntryToData( - _In_ PVOID BaseOfImage, - _In_ BOOLEAN MappedAsImage, - _In_ USHORT DirectoryEntry, - _Out_ PULONG Size -); - -EXTERN_C BOOLEAN NTAPI KeTestAlertThread( - IN KPROCESSOR_MODE AlertMode -); - -EXTERN_C BOOLEAN NTAPI PsIsProtectedProcess( - _In_ PEPROCESS Process -); - -#pragma pack(push, 1) -typedef struct _INJECT_SHELL -{ - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; - WCHAR DllName[MAX_PATH]; - ULONG Tag; - HANDLE ModuleHandle; - PVOID ModuleFileName; - CHAR ShellCode; -} INJECT_SHELL, * PINJECT_SHELL; -#pragma pack(pop) - -EXTERN_C POBJECT_TYPE* IoDeviceObjectType; -EXTERN_C PVOID RtlImageDirectoryEntryToData(IN PVOID Base,IN BOOLEAN MappedAsImage,IN USHORT DirectoryEntry,OUT PULONG Size); +EXTERN_C BOOLEAN NTAPI PsIsProtectedProcess(_In_ PEPROCESS Process); VOID RemoveCallbacks(); - NTSTATUS InitializeKernelCallbacks(); diff --git a/src/driver/include/pano_filter.h b/src/driver/include/filter.h similarity index 100% rename from src/driver/include/pano_filter.h rename to src/driver/include/filter.h diff --git a/src/driver/include/inject.h b/src/driver/include/inject.h index f6fdca9..eaacd8e 100644 --- a/src/driver/include/inject.h +++ b/src/driver/include/inject.h @@ -1,10 +1,12 @@ #pragma once +#include "pch.h" + + typedef unsigned long DWORD; typedef int BOOL; typedef unsigned char BYTE; typedef unsigned short WORD; -#define TAG 'inje' #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 @@ -233,7 +235,7 @@ EXTERN_C VOID NTAPI KeInitializeApc( _Out_ PRKAPC Apc, _In_ PRKTHREAD Thread, _In_ KAPC_ENVIRONMENT Environment, - _In_ PKKERNEL_ROUTINE KernelRoutine, + _In_ PKKERNEL_ROUTINE KernelRundown, _In_opt_ PKRUNDOWN_ROUTINE RundownRoutine, _In_opt_ PKNORMAL_ROUTINE NormalRoutine, _In_opt_ KPROCESSOR_MODE ProcessorMode, @@ -247,8 +249,16 @@ EXTERN_C BOOLEAN NTAPI KeInsertQueueApc( _In_ KPRIORITY Increment ); +EXTERN_C NTSTATUS NTAPI ZwWriteVirtualMemory( + HANDLE ProcessHandle, + PVOID BaseAddress, + PVOID Buffer, + SIZE_T BufferSize, + PSIZE_T NumberOfBytesWritten +); +EXTERN_C BOOLEAN NTAPI KeTestAlertThread( + IN KPROCESSOR_MODE AlertMode +); -bool InjectDLL(HANDLE ProcessId, PVOID processInfo); -NTSTATUS AllocateMemoryInUserProcess(PEPROCESS Process, SIZE_T Size, PVOID* AllocatedAddress); -NTSTATUS WriteToTargetProcessMemory(PEPROCESS Process, PVOID TargetAddress, SIZE_T Size, PVOID DataToWrite); +NTSTATUS InstallKernelModeApcToInjectDll(HANDLE ProcessId, PVOID ImageBase); diff --git a/src/driver/include/ioctl.h b/src/driver/include/ioctl.h index ef9daec..59cb283 100644 --- a/src/driver/include/ioctl.h +++ b/src/driver/include/ioctl.h @@ -1,4 +1,4 @@ #pragma once -#include "driver_constants.h" +#include "pch.h" #define IOCTL_TERMINATE_PROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/src/driver/include/driver_constants.h b/src/driver/include/pch.h similarity index 66% rename from src/driver/include/driver_constants.h rename to src/driver/include/pch.h index d671ac9..83f49c5 100644 --- a/src/driver/include/driver_constants.h +++ b/src/driver/include/pch.h @@ -1,8 +1,13 @@ #pragma once +#include +#include +#include + #define KERNEL_LINK L"\\Device\\Panoptes" #define KERNEL_LINK_SYM L"\\DosDevices\\Panoptes" #define KERNEL_DRIVER_SERVICE_NAME "Panoptes" #define KERNEL_SERVICE_NAME "Panoptes" #define PANOPTES_PREFIX_ERROR "[!] Panoptes: " #define PANOPTES_PREFIX_WARNING "[-] Panoptes: " -#define PANOPTES_PREFIX_SUCCESS "[+] Panoptes: " \ No newline at end of file +#define PANOPTES_PREFIX_SUCCESS "[+] Panoptes: " +#define DRIVER_TAG 'stnP' // 'Pnts' diff --git a/src/driver/include/shellcode.h b/src/driver/include/shellcode.h deleted file mode 100644 index 5441757..0000000 --- a/src/driver/include/shellcode.h +++ /dev/null @@ -1,170 +0,0 @@ -#pragma once -#include - -#define FUNCTION_OFFSETx64 0x270 -unsigned char _code_rawx64[1536] = { -0x00, 0x00, 0x00, 0x00, 0x10, 0x32, 0xb5, 0x67, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, -0xa0, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x44, 0x04, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, -0x03, 0x80, 0x03, 0x80, 0x34, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x3c, 0x10, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0xf8, 0x10, 0x00, 0x00, 0x2e, 0x13, 0x00, 0x00, 0xf0, 0x10, 0x00, 0x00, -0x3c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, -0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, -0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x76, 0x6f, 0x6c, 0x74, 0x6d, 0x64, 0x00, 0x00, 0x00, -0x44, 0x10, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x7a, -0x7a, 0x7a, 0x64, 0x62, 0x67, 0x00, 0x00, 0x00, 0xf0, 0x10, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, -0x2e, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6d, 0x6e, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x14, 0x00, 0x00, -0x5c, 0x00, 0x00, 0x00, 0x2e, 0x78, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, -0x30, 0x00, 0x00, 0x00, 0x2e, 0x70, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, -0x60, 0x00, 0x00, 0x00, 0x2e, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, -0x60, 0x30, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x2e, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x32, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x65, 0x48, 0x8b, 0x04, 0x25, 0x60, 0x00, 0x00, -0x00, 0x44, 0x8b, 0xfa, 0x44, 0x8b, 0xe9, 0x4c, 0x8b, 0x60, 0x18, 0x49, 0x83, 0xc4, 0x20, 0x4d, -0x8b, 0x34, 0x24, 0x4d, 0x3b, 0xf4, 0x0f, 0x84, 0x43, 0x01, 0x00, 0x00, 0x48, 0x89, 0x5c, 0x24, -0x28, 0x48, 0x89, 0x6c, 0x24, 0x30, 0x48, 0x89, 0x74, 0x24, 0x38, 0x48, 0x89, 0x7c, 0x24, 0x40, -0x49, 0x8b, 0x7e, 0x20, 0x48, 0x63, 0x47, 0x3c, 0x8b, 0x8c, 0x38, 0x88, 0x00, 0x00, 0x00, 0x48, -0x8d, 0x2c, 0x0f, 0x85, 0xc9, 0x0f, 0x84, 0xdc, 0x00, 0x00, 0x00, 0x44, 0x8b, 0x45, 0x0c, 0x45, -0x33, 0xd2, 0x4c, 0x03, 0xc7, 0x45, 0x0f, 0xb6, 0x08, 0x45, 0x84, 0xc9, 0x74, 0x4a, 0x41, 0x0f, -0xb6, 0xc1, 0x0f, 0x1f, 0x40, 0x00, 0x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, -0x2c, 0x20, 0x41, 0x8d, 0x51, 0x9f, 0x80, 0xfa, 0x19, 0x0f, 0xb6, 0xc8, 0x41, 0x0f, 0xb6, 0xc1, -0x4d, 0x8d, 0x40, 0x01, 0x0f, 0x47, 0xc8, 0x41, 0x69, 0xc2, 0xd2, 0x11, 0x00, 0x00, 0x0f, 0xbe, -0xd1, 0x03, 0xd0, 0x41, 0x0f, 0xb6, 0x00, 0x81, 0xe2, 0xff, 0xff, 0xff, 0x00, 0x44, 0x0f, 0xb6, -0xc8, 0x44, 0x03, 0xd2, 0x84, 0xc0, 0x75, 0xc8, 0x45, 0x3b, 0xd5, 0x75, 0x7a, 0x44, 0x8b, 0x5d, -0x20, 0x33, 0xdb, 0x8b, 0x75, 0x18, 0x4c, 0x03, 0xdf, 0x85, 0xf6, 0x74, 0x6a, 0x0f, 0x1f, 0x00, -0x45, 0x8b, 0x03, 0x45, 0x33, 0xc9, 0x4c, 0x03, 0xc7, 0x45, 0x0f, 0xb6, 0x10, 0x45, 0x84, 0xd2, -0x74, 0x46, 0x41, 0x0f, 0xb6, 0xc2, 0x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, -0x2c, 0x20, 0x41, 0x8d, 0x52, 0x9f, 0x80, 0xfa, 0x19, 0x0f, 0xb6, 0xc8, 0x41, 0x0f, 0xb6, 0xc2, -0x4d, 0x8d, 0x40, 0x01, 0x0f, 0x47, 0xc8, 0x41, 0x69, 0xc1, 0xd2, 0x11, 0x00, 0x00, 0x0f, 0xbe, -0xd1, 0x03, 0xd0, 0x41, 0x0f, 0xb6, 0x00, 0x81, 0xe2, 0xff, 0xff, 0xff, 0x00, 0x44, 0x0f, 0xb6, -0xd0, 0x44, 0x03, 0xca, 0x84, 0xc0, 0x75, 0xc8, 0x45, 0x3b, 0xf9, 0x74, 0x18, 0xff, 0xc3, 0x49, -0x83, 0xc3, 0x04, 0x3b, 0xde, 0x72, 0x99, 0x4d, 0x8b, 0x36, 0x4d, 0x3b, 0xf4, 0x0f, 0x85, 0xfd, -0xfe, 0xff, 0xff, 0xeb, 0x16, 0x8b, 0x45, 0x24, 0x8b, 0x4d, 0x1c, 0x48, 0x03, 0xc7, 0x48, 0x03, -0xcf, 0x0f, 0xb7, 0x14, 0x58, 0x8b, 0x04, 0x91, 0x48, 0x03, 0xc7, 0x48, 0x8b, 0x74, 0x24, 0x38, -0x48, 0x8b, 0x6c, 0x24, 0x30, 0x48, 0x8b, 0x5c, 0x24, 0x28, 0x48, 0x8b, 0x7c, 0x24, 0x40, 0x41, -0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, -0x4c, 0x89, 0x44, 0x24, 0x18, 0x48, 0x89, 0x54, 0x24, 0x10, 0x48, 0x89, 0x4c, 0x24, 0x08, 0x55, -0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x48, 0x8b, 0xec, 0x48, 0x83, 0xec, 0x68, 0xc7, 0x45, 0xb8, -0x6e, 0x74, 0x64, 0x6c, 0x4c, 0x8d, 0x45, 0xb8, 0xc7, 0x45, 0xbc, 0x6c, 0x2e, 0x64, 0x6c, 0x45, -0x33, 0xed, 0x66, 0xc7, 0x45, 0xc0, 0x6c, 0x00, 0xb2, 0x6e, 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, -0x8d, 0x42, 0x9f, 0x3c, 0x19, 0x77, 0x07, 0x41, 0x0f, 0xb6, 0x10, 0x80, 0xea, 0x20, 0x41, 0x69, -0xcd, 0xd2, 0x11, 0x00, 0x00, 0x49, 0xff, 0xc0, 0x0f, 0xbe, 0xc2, 0x41, 0x0f, 0xb6, 0x10, 0x03, -0xc8, 0x81, 0xe1, 0xff, 0xff, 0xff, 0x00, 0x44, 0x03, 0xe9, 0x84, 0xd2, 0x75, 0xd2, 0x88, 0x55, -0xd2, 0x4c, 0x8d, 0x45, 0xc8, 0xb2, 0x4c, 0xc7, 0x45, 0xc8, 0x4c, 0x64, 0x72, 0x4c, 0xc7, 0x45, -0xcc, 0x6f, 0x61, 0x64, 0x44, 0x45, 0x33, 0xf6, 0x66, 0xc7, 0x45, 0xd0, 0x6c, 0x6c, 0x66, 0x90, -0x8d, 0x42, 0x9f, 0x3c, 0x19, 0x77, 0x07, 0x41, 0x0f, 0xb6, 0x10, 0x80, 0xea, 0x20, 0x41, 0x69, -0xce, 0xd2, 0x11, 0x00, 0x00, 0x49, 0xff, 0xc0, 0x0f, 0xbe, 0xc2, 0x41, 0x0f, 0xb6, 0x10, 0x03, -0xc8, 0x81, 0xe1, 0xff, 0xff, 0xff, 0x00, 0x44, 0x03, 0xf1, 0x84, 0xd2, 0x75, 0xd2, 0x65, 0x48, -0x8b, 0x04, 0x25, 0x60, 0x00, 0x00, 0x00, 0x48, 0x89, 0x5c, 0x24, 0x60, 0x48, 0x89, 0x74, 0x24, -0x58, 0x48, 0x89, 0x7c, 0x24, 0x50, 0x48, 0x8b, 0x40, 0x18, 0x48, 0x83, 0xc0, 0x20, 0x4c, 0x89, -0x7c, 0x24, 0x48, 0x48, 0x89, 0x45, 0x40, 0x4c, 0x8b, 0x20, 0x4c, 0x3b, 0xe0, 0x0f, 0x84, 0x12, -0x01, 0x00, 0x00, 0x0f, 0x1f, 0x40, 0x00, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, -0x49, 0x8b, 0x7c, 0x24, 0x20, 0x48, 0x63, 0x47, 0x3c, 0x8b, 0x8c, 0x38, 0x88, 0x00, 0x00, 0x00, -0x4c, 0x8d, 0x3c, 0x0f, 0x85, 0xc9, 0x0f, 0x84, 0xdb, 0x00, 0x00, 0x00, 0x45, 0x8b, 0x47, 0x0c, -0x45, 0x33, 0xd2, 0x4c, 0x03, 0xc7, 0x45, 0x0f, 0xb6, 0x08, 0x45, 0x84, 0xc9, 0x74, 0x49, 0x41, -0x0f, 0xb6, 0xc1, 0x0f, 0x1f, 0x40, 0x00, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, -0x2c, 0x20, 0x41, 0x8d, 0x51, 0x9f, 0x80, 0xfa, 0x19, 0x0f, 0xb6, 0xc8, 0x41, 0x0f, 0xb6, 0xc1, -0x4d, 0x8d, 0x40, 0x01, 0x0f, 0x47, 0xc8, 0x41, 0x69, 0xc2, 0xd2, 0x11, 0x00, 0x00, 0x0f, 0xbe, -0xd1, 0x03, 0xd0, 0x41, 0x0f, 0xb6, 0x00, 0x81, 0xe2, 0xff, 0xff, 0xff, 0x00, 0x44, 0x0f, 0xb6, -0xc8, 0x44, 0x03, 0xd2, 0x84, 0xc0, 0x75, 0xc8, 0x45, 0x3b, 0xd5, 0x75, 0x7a, 0x45, 0x8b, 0x5f, -0x20, 0x33, 0xdb, 0x41, 0x8b, 0x77, 0x18, 0x4c, 0x03, 0xdf, 0x85, 0xf6, 0x74, 0x69, 0x66, 0x90, -0x45, 0x8b, 0x03, 0x45, 0x33, 0xc9, 0x4c, 0x03, 0xc7, 0x45, 0x0f, 0xb6, 0x10, 0x45, 0x84, 0xd2, -0x74, 0x46, 0x41, 0x0f, 0xb6, 0xc2, 0x66, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, -0x2c, 0x20, 0x41, 0x8d, 0x52, 0x9f, 0x80, 0xfa, 0x19, 0x0f, 0xb6, 0xc8, 0x41, 0x0f, 0xb6, 0xc2, -0x4d, 0x8d, 0x40, 0x01, 0x0f, 0x47, 0xc8, 0x41, 0x69, 0xc1, 0xd2, 0x11, 0x00, 0x00, 0x0f, 0xbe, -0xd1, 0x03, 0xd0, 0x41, 0x0f, 0xb6, 0x00, 0x81, 0xe2, 0xff, 0xff, 0xff, 0x00, 0x44, 0x0f, 0xb6, -0xd0, 0x44, 0x03, 0xca, 0x84, 0xc0, 0x75, 0xc8, 0x45, 0x3b, 0xf1, 0x74, 0x58, 0xff, 0xc3, 0x49, -0x83, 0xc3, 0x04, 0x3b, 0xde, 0x72, 0x99, 0x4d, 0x8b, 0x24, 0x24, 0x4c, 0x3b, 0x65, 0x40, 0x0f, -0x85, 0xfb, 0xfe, 0xff, 0xff, 0x48, 0x8b, 0x45, 0x40, 0x4c, 0x8b, 0x45, 0x38, 0x4c, 0x8d, 0x4d, -0x40, 0x48, 0x8b, 0x55, 0x30, 0x48, 0x8b, 0x4d, 0x28, 0x48, 0xc7, 0x45, 0x40, 0x00, 0x00, 0x00, -0x00, 0xff, 0xd0, 0x4c, 0x8b, 0x7c, 0x24, 0x48, 0xb0, 0x01, 0x48, 0x8b, 0x7c, 0x24, 0x50, 0x48, -0x8b, 0x74, 0x24, 0x58, 0x48, 0x8b, 0x5c, 0x24, 0x60, 0x48, 0x83, 0xc4, 0x68, 0x41, 0x5e, 0x41, -0x5d, 0x41, 0x5c, 0x5d, 0xc3, 0x41, 0x8b, 0x47, 0x24, 0x41, 0x8b, 0x4f, 0x1c, 0x48, 0x03, 0xc7, -0x48, 0x03, 0xcf, 0x0f, 0xb7, 0x14, 0x58, 0x8b, 0x04, 0x91, 0x48, 0x03, 0xc7, 0xeb, 0xaa, 0xcc, -0x01, 0x08, 0x04, 0x00, 0x08, 0xf0, 0x06, 0xe0, 0x04, 0xd0, 0x02, 0xc0, 0x21, 0x14, 0x08, 0x00, -0x14, 0x74, 0x08, 0x00, 0x0f, 0x64, 0x07, 0x00, 0x0a, 0x54, 0x06, 0x00, 0x05, 0x34, 0x05, 0x00, -0xf0, 0x10, 0x00, 0x00, 0x1c, 0x11, 0x00, 0x00, 0xd0, 0x14, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, -0xf0, 0x10, 0x00, 0x00, 0x1c, 0x11, 0x00, 0x00, 0xd0, 0x14, 0x00, 0x00, 0x01, 0xe3, 0x0d, 0x00, -0xe3, 0xf4, 0x09, 0x00, 0xd6, 0x74, 0x0a, 0x00, 0xd1, 0x64, 0x0b, 0x00, 0xcc, 0x34, 0x0c, 0x00, -0x1d, 0xc2, 0x16, 0xe0, 0x14, 0xd0, 0x12, 0xc0, 0x10, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -#define FUNCTION_OFFSETx86 0x200 -unsigned char _code_rawx86[1024] = { -0x00, 0x00, 0x00, 0x00, 0xba, 0x28, 0xb5, 0x67, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, -0x80, 0x00, 0x00, 0x00, 0x3c, 0x10, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, -0x03, 0x80, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x10, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0xc0, 0x10, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x10, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, -0x1c, 0x10, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x76, -0x6f, 0x6c, 0x74, 0x6d, 0x64, 0x00, 0x00, 0x00, 0x3c, 0x10, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, -0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x7a, 0x7a, 0x7a, 0x64, 0x62, 0x67, 0x00, 0x00, 0x00, -0xc0, 0x10, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6d, 0x6e, -0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x2e, 0x72, 0x73, 0x72, -0x63, 0x24, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, -0x2e, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x55, 0x8b, 0xec, 0x83, 0xec, 0x1c, 0x64, 0xa1, 0x30, 0x00, 0x00, 0x00, 0x8b, 0x48, 0x0c, 0x8b, -0x41, 0x14, 0x83, 0xc1, 0x14, 0x89, 0x4d, 0xe4, 0x89, 0x45, 0xf0, 0x3b, 0xc1, 0x0f, 0x84, 0x0c, -0x01, 0x00, 0x00, 0x53, 0x56, 0x57, 0x8b, 0x50, 0x10, 0x89, 0x55, 0xf8, 0x8b, 0x42, 0x3c, 0x8b, -0x44, 0x10, 0x78, 0x8d, 0x0c, 0x10, 0x89, 0x4d, 0xfc, 0x85, 0xc0, 0x0f, 0x84, 0xbb, 0x00, 0x00, -0x00, 0x8b, 0x71, 0x0c, 0x33, 0xff, 0x03, 0xf2, 0x8a, 0x1e, 0x84, 0xdb, 0x74, 0x37, 0x8a, 0xc3, -0x2c, 0x20, 0x8d, 0x53, 0x9f, 0x0f, 0xb6, 0xc8, 0x8d, 0x76, 0x01, 0x0f, 0xb6, 0xc3, 0x80, 0xfa, -0x19, 0x0f, 0x47, 0xc8, 0x69, 0xc7, 0xd2, 0x11, 0x00, 0x00, 0x0f, 0xbe, 0xc9, 0x03, 0xc8, 0x8a, -0x06, 0x81, 0xe1, 0xff, 0xff, 0xff, 0x00, 0x8a, 0xd8, 0x03, 0xf9, 0x84, 0xc0, 0x75, 0xd1, 0x8b, -0x55, 0xf8, 0x8b, 0x4d, 0xfc, 0x3b, 0x7d, 0x08, 0x75, 0x72, 0x8b, 0x45, 0xfc, 0x8b, 0x59, 0x20, -0x33, 0xc9, 0x03, 0xda, 0x89, 0x4d, 0xf4, 0x89, 0x5d, 0xe8, 0x8b, 0x40, 0x18, 0x89, 0x45, 0xec, -0x85, 0xc0, 0x74, 0x58, 0x8b, 0x34, 0x8b, 0x33, 0xff, 0x8a, 0x1c, 0x16, 0x03, 0xf2, 0x84, 0xdb, -0x74, 0x3a, 0x8a, 0xc3, 0x2c, 0x20, 0x8d, 0x53, 0x9f, 0x0f, 0xb6, 0xc8, 0x8d, 0x76, 0x01, 0x0f, -0xb6, 0xc3, 0x80, 0xfa, 0x19, 0x0f, 0x47, 0xc8, 0x69, 0xc7, 0xd2, 0x11, 0x00, 0x00, 0x0f, 0xbe, -0xc9, 0x03, 0xc8, 0x8a, 0x06, 0x81, 0xe1, 0xff, 0xff, 0xff, 0x00, 0x8a, 0xd8, 0x03, 0xf9, 0x84, -0xc0, 0x75, 0xd1, 0x8b, 0x4d, 0xf4, 0x8b, 0x55, 0xf8, 0x8b, 0x45, 0xec, 0x39, 0x7d, 0x0c, 0x74, -0x23, 0x8b, 0x5d, 0xe8, 0x41, 0x89, 0x4d, 0xf4, 0x3b, 0xc8, 0x72, 0xa8, 0x8b, 0x45, 0xf0, 0x8b, -0x00, 0x89, 0x45, 0xf0, 0x3b, 0x45, 0xe4, 0x0f, 0x85, 0x19, 0xff, 0xff, 0xff, 0x5f, 0x5e, 0x5b, -0x8b, 0xe5, 0x5d, 0xc3, 0x8b, 0x5d, 0xfc, 0x5f, 0x5e, 0x8b, 0x43, 0x24, 0x8d, 0x04, 0x48, 0x0f, -0xb7, 0x0c, 0x10, 0x8b, 0x43, 0x1c, 0x5b, 0x8d, 0x04, 0x88, 0x8b, 0x04, 0x10, 0x03, 0xc2, 0x8b, -0xe5, 0x5d, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, -0x55, 0x8b, 0xec, 0x83, 0xec, 0x38, 0x53, 0x56, 0x57, 0xc7, 0x45, 0xd4, 0x6e, 0x74, 0x64, 0x6c, -0x8d, 0x75, 0xd4, 0xc7, 0x45, 0xd8, 0x6c, 0x2e, 0x64, 0x6c, 0x33, 0xdb, 0x66, 0xc7, 0x45, 0xdc, -0x6c, 0x00, 0xb2, 0x6e, 0x8d, 0x42, 0x9f, 0x3c, 0x19, 0x77, 0x05, 0x8a, 0x16, 0x80, 0xea, 0x20, -0x69, 0xcb, 0xd2, 0x11, 0x00, 0x00, 0x46, 0x0f, 0xbe, 0xc2, 0x8a, 0x16, 0x03, 0xc8, 0x81, 0xe1, -0xff, 0xff, 0xff, 0x00, 0x03, 0xd9, 0x84, 0xd2, 0x75, 0xda, 0x89, 0x5d, 0xe8, 0x8d, 0x75, 0xc8, -0x88, 0x55, 0xd2, 0x33, 0xdb, 0xc7, 0x45, 0xc8, 0x4c, 0x64, 0x72, 0x4c, 0xb2, 0x4c, 0xc7, 0x45, -0xcc, 0x6f, 0x61, 0x64, 0x44, 0x66, 0xc7, 0x45, 0xd0, 0x6c, 0x6c, 0x0f, 0x1f, 0x44, 0x00, 0x00, -0x8d, 0x42, 0x9f, 0x3c, 0x19, 0x77, 0x05, 0x8a, 0x16, 0x80, 0xea, 0x20, 0x69, 0xcb, 0xd2, 0x11, -0x00, 0x00, 0x46, 0x0f, 0xbe, 0xc2, 0x8a, 0x16, 0x03, 0xc8, 0x81, 0xe1, 0xff, 0xff, 0xff, 0x00, -0x03, 0xd9, 0x84, 0xd2, 0x75, 0xda, 0x64, 0xa1, 0x30, 0x00, 0x00, 0x00, 0x89, 0x5d, 0xf4, 0x8b, -0x48, 0x0c, 0x8b, 0x41, 0x14, 0x83, 0xc1, 0x14, 0x89, 0x4d, 0xe0, 0x89, 0x45, 0xec, 0x3b, 0xc1, -0x0f, 0x84, 0xe8, 0x00, 0x00, 0x00, 0x8b, 0x50, 0x10, 0x89, 0x55, 0xf8, 0x8b, 0x42, 0x3c, 0x8b, -0x44, 0x10, 0x78, 0x8d, 0x0c, 0x10, 0x89, 0x4d, 0xfc, 0x85, 0xc0, 0x0f, 0x84, 0xbc, 0x00, 0x00, -0x00, 0x8b, 0x71, 0x0c, 0x33, 0xff, 0x03, 0xf2, 0x8a, 0x1e, 0x84, 0xdb, 0x74, 0x37, 0x8a, 0xc3, -0x2c, 0x20, 0x8d, 0x53, 0x9f, 0x0f, 0xb6, 0xc8, 0x8d, 0x76, 0x01, 0x0f, 0xb6, 0xc3, 0x80, 0xfa, -0x19, 0x0f, 0x47, 0xc8, 0x69, 0xc7, 0xd2, 0x11, 0x00, 0x00, 0x0f, 0xbe, 0xc9, 0x03, 0xc8, 0x8a, -0x06, 0x81, 0xe1, 0xff, 0xff, 0xff, 0x00, 0x8a, 0xd8, 0x03, 0xf9, 0x84, 0xc0, 0x75, 0xd1, 0x8b, -0x55, 0xf8, 0x8b, 0x4d, 0xfc, 0x3b, 0x7d, 0xe8, 0x75, 0x73, 0x8b, 0x45, 0xfc, 0x8b, 0x59, 0x20, -0x33, 0xc9, 0x03, 0xda, 0x89, 0x4d, 0xf0, 0x89, 0x5d, 0xe4, 0x39, 0x48, 0x18, 0x76, 0x5e, 0x8b, -0x45, 0xf4, 0x8b, 0x34, 0x8b, 0x33, 0xff, 0x8a, 0x1c, 0x16, 0x03, 0xf2, 0x84, 0xdb, 0x74, 0x3a, -0x8a, 0xc3, 0x2c, 0x20, 0x8d, 0x53, 0x9f, 0x0f, 0xb6, 0xc8, 0x8d, 0x76, 0x01, 0x0f, 0xb6, 0xc3, -0x80, 0xfa, 0x19, 0x0f, 0x47, 0xc8, 0x69, 0xc7, 0xd2, 0x11, 0x00, 0x00, 0x0f, 0xbe, 0xc9, 0x03, -0xc8, 0x8a, 0x06, 0x81, 0xe1, 0xff, 0xff, 0xff, 0x00, 0x8a, 0xd8, 0x03, 0xf9, 0x84, 0xc0, 0x75, -0xd1, 0x8b, 0x4d, 0xf0, 0x8b, 0x55, 0xf8, 0x8b, 0x45, 0xf4, 0x8b, 0x5d, 0xfc, 0x3b, 0xc7, 0x74, -0x38, 0x41, 0x3b, 0x4b, 0x18, 0x8b, 0x5d, 0xe4, 0x89, 0x4d, 0xf0, 0x72, 0xa5, 0x8b, 0x45, 0xec, -0x8b, 0x00, 0x89, 0x45, 0xec, 0x3b, 0x45, 0xe0, 0x0f, 0x85, 0x18, 0xff, 0xff, 0xff, 0x8b, 0x45, -0xe0, 0x8d, 0x4d, 0x14, 0x51, 0xff, 0x75, 0x10, 0xff, 0x75, 0x0c, 0xff, 0x75, 0x08, 0xff, 0xd0, -0x5f, 0x5e, 0xb0, 0x01, 0x5b, 0x8b, 0xe5, 0x5d, 0xc3, 0x8b, 0x43, 0x24, 0x8d, 0x04, 0x48, 0x0f, -0xb7, 0x0c, 0x10, 0x8b, 0x43, 0x1c, 0x8d, 0x04, 0x88, 0x8b, 0x04, 0x10, 0x03, 0xc2, 0xeb, 0xd1, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; \ No newline at end of file diff --git a/src/driver/include/state.h b/src/driver/include/state.h new file mode 100644 index 0000000..21b1d74 --- /dev/null +++ b/src/driver/include/state.h @@ -0,0 +1,37 @@ +#pragma once +#include + +typedef struct _PANO_PROCESS_INFO +{ + ULONG ProcessId; + BOOLEAN is64Bit; + BOOLEAN Injected; + BOOLEAN kernel32Loaded; + BOOLEAN kernelBaseLoaded; + BOOLEAN ntdllLoaded; +} PANO_PROCESS_INFO, * PPANO_PROCESS_INFO; + +struct PanoptesState { + LARGE_INTEGER RegistryCookie; + RTL_AVL_TABLE Processes; + FAST_MUTEX ProcessesLock; + PCALLBACK_OBJECT ProcessCreateCallback; + PVOID ImageBase; + + NTSTATUS Init(); + void Term(); + +private: + static RTL_GENERIC_COMPARE_RESULTS ProcessCompare( + _In_ PRTL_AVL_TABLE Table, + _In_ PVOID FirstStruct, + _In_ PVOID SecondStruct); + + static PVOID TableAlloc( + _In_ struct _RTL_AVL_TABLE* Table, + _In_ CLONG ByteSize); + + static VOID TableFree( + _In_ struct _RTL_AVL_TABLE* Table, + _In_ __drv_freesMem(Mem) _Post_invalid_ PVOID Buffer); +}; \ No newline at end of file diff --git a/src/driver/include/structs.h b/src/driver/include/structs.h deleted file mode 100644 index ab8047f..0000000 --- a/src/driver/include/structs.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include - -typedef struct _PANO_PROCESS_INFO -{ - LIST_ENTRY ListEntry; - BOOLEAN is64Bit; - HANDLE ProcessId; - BOOLEAN Injected; - BOOLEAN ntdllLoaded; - BOOLEAN kernel32Loaded; - BOOLEAN kernelBaseLoaded; - PVOID kernel32BaseAddress; -} PANO_PROCESS_INFO, * PPANO_PROCESS_INFO; \ No newline at end of file diff --git a/src/driver/include/trace.h b/src/driver/include/trace.h index 24832a8..e0cdc3a 100644 --- a/src/driver/include/trace.h +++ b/src/driver/include/trace.h @@ -1,5 +1,5 @@ #pragma once -#include +#include "pch.h" #include #pragma region TraceLogging Initialization diff --git a/src/driver/include/pano_query.h b/src/driver/include/utils.h similarity index 70% rename from src/driver/include/pano_query.h rename to src/driver/include/utils.h index 8758b08..150e729 100644 --- a/src/driver/include/pano_query.h +++ b/src/driver/include/utils.h @@ -1,5 +1,5 @@ -#pragma once -#include "structs.h" +#include "pch.h" +#include "inject.h" #pragma region Structs typedef struct _PROCESS_MITIGATION_POLICY_INFORMATION @@ -26,15 +26,26 @@ typedef struct _PROCESS_MITIGATION_POLICY_INFORMATION PROCESS_MITIGATION_SEHOP_POLICY SEHOPPolicy; }Data; } PROCESS_MITIGATION_POLICY_INFORMATION, * PPROCESS_MITIGATION_POLICY_INFORMATION; +#pragma endregion EXTERN_C NTSTATUS NTAPI ZwQueryInformationProcess( - HANDLE hProcess, - PROCESSINFOCLASS infoType, - /*out*/ PVOID pBuf, - /*sizeof pBuf*/ ULONG lenBuf, + HANDLE hProcess, + PROCESSINFOCLASS infoType, + /*out*/ PVOID pBuf, + /*sizeof pBuf*/ ULONG lenBuf, SIZE_T* /*PULONG*/ returnLength ); -#pragma endregion +EXTERN_C PVOID NTAPI RtlImageDirectoryEntryToData( + _In_ PVOID BaseOfImage, + _In_ BOOLEAN MappedAsImage, + _In_ USHORT DirectoryEntry, + _Out_ PULONG Size +); +BOOLEAN Is64BitProcess(PEPROCESS targetProcess); +NTSTATUS GetFileNameFromPath(PUNICODE_STRING FullPath, PUNICODE_STRING FileName); NTSTATUS QueryProcessMitigationPolicy(HANDLE ProcessId, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo); + +PVOID NTAPI RtlxFindExportedRoutineByName(_In_ PVOID DllBase, _In_ PANSI_STRING ExportName); +EXTERN_C PVOID RtlImageDirectoryEntryToData(IN PVOID Base, IN BOOLEAN MappedAsImage, IN USHORT DirectoryEntry, OUT PULONG Size); diff --git a/src/driver/src/callbacks.cpp b/src/driver/src/callbacks.cpp index bdc8be0..e18cbef 100644 --- a/src/driver/src/callbacks.cpp +++ b/src/driver/src/callbacks.cpp @@ -1,387 +1,120 @@ #include "callbacks.h" +#include "state.h" #include "inject.h" -#include "driver_constants.h" -#include "pano_query.h" -#include -#include "shellcode.h" +#include "utils.h" - -LIST_ENTRY g_ProcessList{}; -KSPIN_LOCK g_ProcessListLock{}; -PVOID g_ObRegistrationHandle{}; - -PVOID NTAPI RtlxFindExportedRoutineByName(_In_ PVOID DllBase,_In_ PANSI_STRING ExportName) { - // - // RtlFindExportedRoutineByName is not exported by ntoskrnl until Win10. - // Following code is borrowed from ReactOS. - // - - PULONG NameTable; - PUSHORT OrdinalTable; - PIMAGE_EXPORT_DIRECTORY ExportDirectory; - LONG Low = 0, Mid = 0, High, Ret; - USHORT Ordinal; - PVOID Function; - ULONG ExportSize; - PULONG ExportTable; - - // - // Get the export directory. - // - - ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(DllBase, - TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, - &ExportSize); - - if (!ExportDirectory) - { - return NULL; - } - - // - // Setup name tables. - // - - NameTable = (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfNames); - OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase + ExportDirectory->AddressOfNameOrdinals); - - // - // Do a binary search. - // - - High = ExportDirectory->NumberOfNames - 1; - while (High >= Low) - { - // - // Get new middle value. - // - - Mid = (Low + High) >> 1; - - // - // Compare name. - // - - Ret = strcmp(ExportName->Buffer, (PCHAR)DllBase + NameTable[Mid]); - if (Ret < 0) - { - // - // Update high. - // - High = Mid - 1; - } - else if (Ret > 0) - { - // - // Update low. - // - Low = Mid + 1; - } - else - { - // - // We got it. - // - break; - } - } - - // - // Check if we couldn't find it. - // - - if (High < Low) - { - return NULL; - } - - // - // Otherwise, this is the ordinal. - // - - Ordinal = OrdinalTable[Mid]; - - // - // Validate the ordinal. - // - - if (Ordinal >= ExportDirectory->NumberOfFunctions) - { - return NULL; - } - - // - // Resolve the address and write it. - // - - ExportTable = (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfFunctions); - Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]); - - // - // We found it! - // - - NT_ASSERT( - (Function < (PVOID)ExportDirectory) || - (Function > (PVOID)((ULONG_PTR)ExportDirectory + ExportSize)) - ); - - return Function; -} +PanoptesState g_State{}; PPANO_PROCESS_INFO GetProcessInfo(HANDLE ProcessId) { - //KIRQL OldIRQL; - //ExAcquireSpinLock(&g_ProcessListLock, &OldIRQL); - PLIST_ENTRY entry = g_ProcessList.Flink; - while (entry != &g_ProcessList) { - PPANO_PROCESS_INFO processInfo = CONTAINING_RECORD(entry, PANO_PROCESS_INFO, ListEntry); - if (processInfo->ProcessId == ProcessId) { - return processInfo; - } - entry = entry->Flink; + auto pi = (PPANO_PROCESS_INFO)RtlLookupElementGenericTableAvl(&g_State.Processes, &ProcessId); + if (pi != nullptr) { + return pi; } - //ExReleaseSpinLock(&g_ProcessListLock, NULL); - return NULL; + return nullptr; } -VOID RemoveProcessInfo(HANDLE ProcessId) -{ - PLIST_ENTRY entry = g_ProcessList.Flink; - while (entry != &g_ProcessList) { - PPANO_PROCESS_INFO processInfo = CONTAINING_RECORD(entry, PANO_PROCESS_INFO, ListEntry); - if (processInfo->ProcessId == ProcessId) { - RemoveEntryList(entry); - return; - } - entry = entry->Flink; - } +VOID RemoveProcessInfo(HANDLE ProcessId) { + ExAcquireFastMutex(&g_State.ProcessesLock); + PANO_PROCESS_INFO pi; + pi.ProcessId = HandleToUlong(ProcessId); + RtlDeleteElementGenericTableAvl(&g_State.Processes, &pi); + KdPrint((PANOPTES_PREFIX_SUCCESS "Process %u deleted from table\n", pi.ProcessId)); + ExReleaseFastMutex(&g_State.ProcessesLock); return; } -void NTAPI KernelRoutine(PKAPC apc, PKNORMAL_ROUTINE* NormalRoutine, PVOID* NormalContext, PVOID* SystemArgument1, PVOID* SystemArgument2) -{ - UNREFERENCED_PARAMETER(NormalRoutine); - UNREFERENCED_PARAMETER(NormalContext); - UNREFERENCED_PARAMETER(SystemArgument1); - UNREFERENCED_PARAMETER(SystemArgument2); - - ExFreePool(apc); -} - -BOOLEAN CanInject(PPANO_PROCESS_INFO processInfo) -{ - if (processInfo->ntdllLoaded && processInfo->kernel32Loaded && processInfo->kernelBaseLoaded) - { - return TRUE; - } - return FALSE; -} - -VOID InjectDllKernelApc(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2) -{ - DbgPrint("InjectDll Entered"); - HANDLE pProcessId = (HANDLE)NormalContext; - UNREFERENCED_PARAMETER(SystemArgument1); - UNREFERENCED_PARAMETER(SystemArgument2); - - if (nullptr == pProcessId) - { - DbgPrint("InjectDll - pProcessId is null"); - } - - PPANO_PROCESS_INFO pi = GetProcessInfo(pProcessId); - ANSI_STRING loadDllRoutineName = RTL_CONSTANT_STRING("LoadLibraryExW"); - PVOID shellcodeAddress = RtlxFindExportedRoutineByName(pi->kernel32BaseAddress, &loadDllRoutineName); - - - - UNICODE_STRING dllToInject; - UNICODE_STRING dllFullPathx64; - UNICODE_STRING dllFullPathx86; - RtlInitUnicodeString(&dllFullPathx64, L"C:\\Program Files\\Panoptes\\PanoptesDLLx64.dll"); - RtlInitUnicodeString(&dllFullPathx86, L"C:\\Program Files\\Panoptes\\PanoptesDLLx86.dll"); - PVOID allocatedAddressContainingDllFullPath = nullptr; - - if (pi->is64Bit) - { - dllToInject = dllFullPathx64; - } - else - { - dllToInject = dllFullPathx86; - } - - NTSTATUS status = ZwAllocateVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, 0, (PSIZE_T)&dllToInject.Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - if (!NT_SUCCESS(status)) - { - DbgPrint("Error: Unable to allocate memory in the target process."); - return; - } - RtlCopyMemory(allocatedAddressContainingDllFullPath, dllToInject.Buffer, dllToInject.Length); +// https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/windows-kernel-mode-process-and-thread-manager#best +// This callback is ran in PASSIVE_LEVEL IRQL, but with safe mode enabled so no actions that would lock this function and prevent the image from loading like mutexes +VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo) { + UNREFERENCED_PARAMETER(ImageInfo); + ULONG id = HandleToUlong(ProcessId); - PKAPC pKapc = (PKAPC)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KAPC), 'tikt'); // Allocate the APC object - if (!pKapc) - { - DbgPrint("Error: Unable to allocate the APC object."); - ZwFreeVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, (PSIZE_T)&dllToInject.Length, MEM_RELEASE); // Free the allocated memory + if (PsIsProtectedProcess(PsGetCurrentProcess())){ + KdPrint((PANOPTES_PREFIX_WARNING "Skipping protected process %u\n", id)); + RemoveProcessInfo(ProcessId); return; } - KeInitializeApc(pKapc, KeGetCurrentThread(), OriginalApcEnvironment, KernelRoutine, NULL, (PKNORMAL_ROUTINE)(shellcodeAddress), UserMode, allocatedAddressContainingDllFullPath); // Initialize the APC + UNICODE_STRING loadedImageName{}; + GetFileNameFromPath(FullImageName, &loadedImageName); - DbgPrint("Inserting APC to target thread"); - if (!KeInsertQueueApc(pKapc, NULL, NULL, IO_NO_INCREMENT)) - { - DbgPrint("Error: Unable to insert APC to target thread."); - ZwFreeVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, (PSIZE_T)&dllToInject.Length, MEM_RELEASE); // Free the allocated memory - ExFreePool(pKapc); // Free the APC object + auto pi = GetProcessInfo(ProcessId); + if (pi == nullptr) { return; } - KeTestAlertThread(UserMode); - - DbgPrint("InjectDllKernelApc exiting"); -} - -NTSTATUS InstallKernelModeApcToInjectDll(HANDLE ProcessId) -{ - PRKAPC pKapc = nullptr; - PETHREAD pThread = nullptr; - - pKapc = (PKAPC)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KAPC), 'tiky'); // Allocate the APC object - if (nullptr == pKapc) - { - DbgPrint("InstallKernelModeApcToInjectDll Failed to allocate memory for the APC"); - return STATUS_INSUFFICIENT_RESOURCES; - } - - pThread = KeGetCurrentThread(); - KeInitializeApc(pKapc, pThread, - OriginalApcEnvironment, - KernelRoutine, NULL, - (PKNORMAL_ROUTINE)InjectDllKernelApc, - KernelMode, (PVOID)ProcessId); - if (!KeInsertQueueApc(pKapc, NULL, NULL, IO_NO_INCREMENT)) - { - DbgPrint("InstallKernelModeApcToInjectDll Failed to insert APC"); - ExFreePool(pKapc); // Free the APC object - return STATUS_UNSUCCESSFUL; - } - else - { - DbgPrint("InstallKernelModeApcToInjectDll APC delivered"); - } - - return STATUS_SUCCESS; -} - -BOOLEAN Is64BitProcess(PEPROCESS targetProcess) { - UINT64* processAsUint64 = reinterpret_cast(targetProcess); - PVOID* wow64ProcessPtr = reinterpret_cast(processAsUint64 + 0x580 / sizeof(UINT64)); - if (*wow64ProcessPtr == NULL) - { - return TRUE; - } - return FALSE; -} - -VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo) -{ - PAGED_CODE(); - UNREFERENCED_PARAMETER(ImageInfo); - - PPANO_PROCESS_INFO processInfo = GetProcessInfo(ProcessId); - if (!processInfo || processInfo->Injected) - { + if (pi->kernel32Loaded && pi->kernelBaseLoaded && pi->ntdllLoaded) { + if (pi->Injected) { + return; + } + KdPrint((PANOPTES_PREFIX_SUCCESS "All required images loaded for process %u, attempting injection\n", id)); + auto test = g_State.ImageBase; + InstallKernelModeApcToInjectDll(ProcessId, test); + pi->Injected = TRUE; return; } - if (PsIsProtectedProcess(PsGetCurrentProcess())) - { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Skipping protected process %llu", (ULONG64)ProcessId); - RemoveProcessInfo(ProcessId); - return; + UNICODE_STRING ntdllLoadImage; + RtlInitUnicodeString(&ntdllLoadImage, L"ntdll.dll"); + if (RtlCompareUnicodeString(&ntdllLoadImage, &loadedImageName, TRUE) == 0) { + pi->ntdllLoaded = TRUE; } - if (!CanInject(processInfo)) - { - UNICODE_STRING ntdllLoadImage; - RtlInitUnicodeString(&ntdllLoadImage, L"ntdll.dll"); - if (wcsstr(FullImageName->Buffer, ntdllLoadImage.Buffer) != NULL) { - processInfo->ntdllLoaded = TRUE; - return; - } - - UNICODE_STRING kernel32LoadImage; - RtlInitUnicodeString(&kernel32LoadImage, L"kernel32.dll"); - if (wcsstr(FullImageName->Buffer, kernel32LoadImage.Buffer) != NULL) { - processInfo->kernel32Loaded = TRUE; - processInfo->kernel32BaseAddress = ImageInfo->ImageBase; - return; - } - - UNICODE_STRING kernelbaseLoadImage; - RtlInitUnicodeString(&kernelbaseLoadImage, L"KernelBase.dll"); - if (wcsstr(FullImageName->Buffer, kernelbaseLoadImage.Buffer) != NULL) { - processInfo->kernelBaseLoaded = TRUE; + UNICODE_STRING kernel32LoadImage; + RtlInitUnicodeString(&kernel32LoadImage, L"kernel32.dll"); + if (RtlCompareUnicodeString(&kernel32LoadImage, &loadedImageName, TRUE) == 0) { + PVOID ImageBaseValue = g_State.ImageBase; + if (ImageBaseValue == nullptr) { return; } + RtlCopyMemory(g_State.ImageBase, &ImageInfo->ImageBase, sizeof(PVOID)); + pi->kernel32Loaded = TRUE; } - else - { - PEPROCESS targetProcess = NULL; - NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &targetProcess); - if (!NT_SUCCESS(status)) { - return; - } - PUNICODE_STRING processPath{}; - status = SeLocateProcessImageName(targetProcess, &processPath); - if (!NT_SUCCESS(status)) { - KdPrint((PANOPTES_PREFIX_WARNING "Failed to get process name, status: 0x%X\n", status)); - return; - } - - processInfo->is64Bit = Is64BitProcess(targetProcess); - if (processInfo->is64Bit) { - KdPrint((PANOPTES_PREFIX_SUCCESS "Injecting into x64: (%llu) %wZ\n", (ULONG64)ProcessId, processPath)); - } - else { - KdPrint((PANOPTES_PREFIX_SUCCESS "Injecting Into x86: (%llu) %wZ\n", (ULONG64)ProcessId, processPath)); - } - - InstallKernelModeApcToInjectDll(ProcessId); - processInfo->Injected = TRUE; + UNICODE_STRING kernelbaseLoadImage; + RtlInitUnicodeString(&kernel32LoadImage, L"kernelbase.dll"); + if (RtlCompareUnicodeString(&kernel32LoadImage, &loadedImageName, TRUE) == 0) { + KdPrint((PANOPTES_PREFIX_SUCCESS "Attempting to injected Into %u\n", id)); + pi->kernelBaseLoaded = TRUE; } return; } -VOID ProcessCreateCallback(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo) -{ +_Use_decl_annotations_ +VOID ProcessCreateCallback(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo) { UNREFERENCED_PARAMETER(Process); + ULONG id = HandleToUlong(ProcessId); if (CreateInfo != NULL) { - + ExAcquireFastMutex(&g_State.ProcessesLock); + //Check if process info already exists + auto pi = (PPANO_PROCESS_INFO)RtlLookupElementGenericTableAvl(&g_State.Processes, &id); + if (pi == nullptr) { + PANO_PROCESS_INFO newProcessEntry{}; + newProcessEntry.ProcessId = id; + pi = (PPANO_PROCESS_INFO)RtlInsertElementGenericTableAvl(&g_State.Processes, &newProcessEntry, sizeof(newProcessEntry), nullptr); + KdPrint((PANOPTES_PREFIX_SUCCESS "Process %u added to table\n", id)); + } + ExReleaseFastMutex(&g_State.ProcessesLock); } else { - + RemoveProcessInfo(&id); + KdPrint((PANOPTES_PREFIX_SUCCESS "Process %u terminated and removed from table\n", id)); } } -NTSTATUS InitializeKernelCallbacks() -{ +NTSTATUS InitializeKernelCallbacks() { PAGED_CODE(); NTSTATUS status; - + status = PsSetCreateProcessNotifyRoutineEx(ProcessCreateCallback, FALSE); if (!NT_SUCCESS(status)) { KdPrint((PANOPTES_PREFIX_ERROR "Driver Failed to Set Process Creation Notify Routine Notify Routine - Ensure /INTEGRITYCHECK is added to the linker options\n")); return status; } - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Set Process Creation Notify Callbacks\n"); + KdPrint((PANOPTES_PREFIX_SUCCESS "Set Process Creation Notify Callbacks\n")); status = PsSetLoadImageNotifyRoutine(LoadImageNotifyRoutine); if (!NT_SUCCESS(status)) { @@ -393,11 +126,11 @@ NTSTATUS InitializeKernelCallbacks() } KdPrint((PANOPTES_PREFIX_ERROR "Driver Failed to Set Process Load Image Notify Routine - Ensure / INTEGRITYCHECK is added to the linker options\n")); - return status; } KdPrint((PANOPTES_PREFIX_SUCCESS "Set Image Load Notify Callbacks\n")); + status = g_State.Init(); return STATUS_SUCCESS; } @@ -405,5 +138,6 @@ NTSTATUS InitializeKernelCallbacks() VOID RemoveCallbacks() { PsSetCreateProcessNotifyRoutineEx(ProcessCreateCallback, TRUE); PsRemoveLoadImageNotifyRoutine(LoadImageNotifyRoutine); + g_State.Term(); return; } diff --git a/src/driver/src/driver.cpp b/src/driver/src/driver.cpp index f45e25e..45d652a 100644 --- a/src/driver/src/driver.cpp +++ b/src/driver/src/driver.cpp @@ -1,10 +1,8 @@ -#include "driver_constants.h" +#include "pch.h" #include "callbacks.h" -#include "pano_query.h" #include "trace.h" -#include "pano_filter.h" -#include -#include +#include "filter.h" +#include "state.h" UNICODE_STRING g_deviceName; UNICODE_STRING g_symLink; @@ -13,8 +11,8 @@ UNICODE_STRING g_SymbolicLinkName; void UnloadPanoptes(PDRIVER_OBJECT DriverObject) { PAGED_CODE(); - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Driver Exit\n"); - Log_DriverExit(DriverObject); + KdPrint(( PANOPTES_PREFIX_SUCCESS "Driver Exit\n")); + //Log_DriverExit(DriverObject); //IoDeleteDevice(driver_object); //IoDeleteSymbolicLink(&g_symLink); RemoveCallbacks(); @@ -24,9 +22,9 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) PAGED_CODE(); DriverObject->DriverUnload = UnloadPanoptes; - TraceInitialize(); + //TraceInitialize(); - Log_DriverEntry(DriverObject, RegistryPath); + //Log_DriverEntry(DriverObject, RegistryPath); //NTSTATUS status = FilterInit(&DriverObject); //if (!NT_SUCCESS(status)) { diff --git a/src/driver/src/pano_filter.cpp b/src/driver/src/filter.cpp similarity index 91% rename from src/driver/src/pano_filter.cpp rename to src/driver/src/filter.cpp index 8dff8ec..908fef1 100644 --- a/src/driver/src/pano_filter.cpp +++ b/src/driver/src/filter.cpp @@ -1,12 +1,9 @@ -#include "pano_filter.h" +#include "filter.h" #include "trace.h" PFLT_FILTER g_FilterHandle; -PWCH GetFileInfo( - PFLT_CALLBACK_DATA Data -) -{ +PWCH GetFileInfo(PFLT_CALLBACK_DATA Data) { PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_FILESYSTEM_ONLY | FLT_FILE_NAME_DO_NOT_CACHE, &fileNameInfo); if (!NT_SUCCESS(status)) { @@ -21,10 +18,7 @@ PWCH GetFileInfo( } } -void MailSlotStatus( - PFLT_CALLBACK_DATA Data -) -{ +void MailSlotStatus(PFLT_CALLBACK_DATA Data) { PWCH fileName = GetFileInfo(Data); HANDLE sourceProcessId = PsGetCurrentProcessId(); HANDLE sourceThreadId = PsGetThreadId(Data->Thread); @@ -40,10 +34,7 @@ void MailSlotStatus( } } -void NamedPipeStatus( - PFLT_CALLBACK_DATA Data -) -{ +void NamedPipeStatus(PFLT_CALLBACK_DATA Data) { PWCH fileName = GetFileInfo(Data); HANDLE sourceProcessId = PsGetCurrentProcessId(); HANDLE sourceThreadId = PsGetThreadId(Data->Thread); @@ -59,10 +50,7 @@ void NamedPipeStatus( } } -void FileWriteStatus( - PFLT_CALLBACK_DATA Data -) -{ +void FileWriteStatus(PFLT_CALLBACK_DATA Data) { PWCH fileName = GetFileInfo(Data); HANDLE sourceProcessId = PsGetCurrentProcessId(); HANDLE sourceThreadId = PsGetThreadId(Data->Thread); @@ -80,10 +68,7 @@ void FileWriteStatus( } } -void FileReadStatus( - PFLT_CALLBACK_DATA Data -) -{ +void FileReadStatus(PFLT_CALLBACK_DATA Data) { PWCH fileName = GetFileInfo(Data); HANDLE sourceProcessId = PsGetCurrentProcessId(); @@ -102,10 +87,7 @@ void FileReadStatus( } } -void FileCreationStatus( - PFLT_CALLBACK_DATA Data -) -{ +void FileCreationStatus(PFLT_CALLBACK_DATA Data) { PWCH fileName = GetFileInfo(Data); HANDLE sourceProcessId = PsGetCurrentProcessId(); @@ -132,13 +114,7 @@ void FileCreationStatus( } } -FLT_POSTOP_CALLBACK_STATUS PostOperationCallback( - PFLT_CALLBACK_DATA Data, - PCFLT_RELATED_OBJECTS FltObjects, - PVOID CompletionContext, - FLT_POST_OPERATION_FLAGS Flags -) -{ +FLT_POSTOP_CALLBACK_STATUS PostOperationCallback(PFLT_CALLBACK_DATA Data,PCFLT_RELATED_OBJECTS FltObjects,PVOID CompletionContext,FLT_POST_OPERATION_FLAGS Flags) { UNREFERENCED_PARAMETER(FltObjects); UNREFERENCED_PARAMETER(CompletionContext); UNREFERENCED_PARAMETER(Flags); @@ -174,11 +150,7 @@ FLT_POSTOP_CALLBACK_STATUS PostOperationCallback( return FLT_POSTOP_FINISHED_PROCESSING; } -NTSTATUS PanoptesFilterUnload -( - _In_ FLT_FILTER_UNLOAD_FLAGS Flags -) -{ +NTSTATUS PanoptesFilterUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags) { PAGED_CODE(); NTSTATUS status; if (Flags == FLTFL_FILTER_UNLOAD_MANDATORY) { @@ -241,8 +213,7 @@ const FLT_REGISTRATION FilterRegistration = { #pragma endregion -NTSTATUS FilterInit(PDRIVER_OBJECT* DriverObject) -{ +NTSTATUS FilterInit(PDRIVER_OBJECT* DriverObject) { NTSTATUS status = FltRegisterFilter( *DriverObject, //Driver &FilterRegistration, //Registration diff --git a/src/driver/src/inject.cpp b/src/driver/src/inject.cpp index a957c2a..79e09c1 100644 --- a/src/driver/src/inject.cpp +++ b/src/driver/src/inject.cpp @@ -1,100 +1,113 @@ -#include "structs.h" #include "inject.h" +#include "utils.h" -NTSTATUS WriteToTargetProcessMemory(PEPROCESS targetProcess, PVOID TargetAddress, SIZE_T Size, PVOID DataToWrite) +void NTAPI KernelRundown(PKAPC apc, PKNORMAL_ROUTINE* NormalRoutine, PVOID* NormalContext, PVOID* SystemArgument1, PVOID* SystemArgument2) { - KAPC_STATE apcState; - PMDL mdl = NULL; - PVOID kernelAddress = NULL; - NTSTATUS status = STATUS_SUCCESS; - - // Attach to the target process - KeStackAttachProcess(targetProcess, &apcState); - - __try { - // Create the MDL for the target process memory - mdl = IoAllocateMdl(TargetAddress, (ULONG)Size, FALSE, FALSE, NULL); - if (!mdl) { - status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - __try { - // Probe and lock the pages - MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess); - - // Map the MDL to system address space - kernelAddress = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority); - if (!kernelAddress) { - status = STATUS_INSUFFICIENT_RESOURCES; - __leave; - } - - // Write to the mapped address - RtlCopyMemory(kernelAddress, DataToWrite, Size); - } - __except (EXCEPTION_EXECUTE_HANDLER) { - status = GetExceptionCode(); - } + UNREFERENCED_PARAMETER(NormalRoutine); + UNREFERENCED_PARAMETER(NormalContext); + UNREFERENCED_PARAMETER(SystemArgument1); + UNREFERENCED_PARAMETER(SystemArgument2); + + ExFreePool(apc); +} + +VOID KernelAPCRoutine(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2) +{ + UNREFERENCED_PARAMETER(SystemArgument2); + + if (NormalContext == nullptr) { + KdPrint(("InjectDll - processId is null")); + return; } - __finally { - // Cleanup - if (kernelAddress) { - MmUnmapLockedPages(kernelAddress, mdl); - } - if (mdl) { - if (mdl->MdlFlags & MDL_PAGES_LOCKED) { - MmUnlockPages(mdl); - } - IoFreeMdl(mdl); - } - - // Detach from the target process - KeUnstackDetachProcess(&apcState); - - // Dereference the process - ObDereferenceObject(targetProcess); + + ULONG processId = HandleToUlong(NormalContext); + + PEPROCESS targetProcess{}; + NTSTATUS status = PsLookupProcessByProcessId(NormalContext, &targetProcess); + if (!NT_SUCCESS(status)) { + return; + } + +#ifdef _DEBUG + PUNICODE_STRING processPath{}; + status = SeLocateProcessImageName(targetProcess, &processPath); + if (!NT_SUCCESS(status)) { + return; } - return status; + UNICODE_STRING onlyProc{}; + RtlInitUnicodeString(&onlyProc, L"die.exe"); + if (wcsstr(processPath->Buffer, onlyProc.Buffer) == NULL) { + return; + } +#endif + + ANSI_STRING loadDllRoutineName = RTL_CONSTANT_STRING("LoadLibraryExW"); + PVOID testVal2 = SystemArgument1; + PVOID testVal3 = *static_cast(testVal2); + PVOID functionAddress = RtlxFindExportedRoutineByName(testVal3, &loadDllRoutineName); + if (functionAddress == nullptr) { + KdPrint((PANOPTES_PREFIX_ERROR "Unable to find LoadLibraryExW in target process (%u)\n", processId)); + return; + } + + UNICODE_STRING dllToInject; + UNICODE_STRING dllFullPathx64; + UNICODE_STRING dllFullPathx86; + RtlInitUnicodeString(&dllFullPathx64, L"C:\\Program Files\\Panoptes\\PanoptesDLLx64.dll"); + RtlInitUnicodeString(&dllFullPathx86, L"C:\\Program Files\\Panoptes\\PanoptesDLLx86.dll"); + + if (Is64BitProcess(targetProcess)) + dllToInject = dllFullPathx64; + else + dllToInject = dllFullPathx86; + + PVOID allocatedAddressContainingDllFullPath = nullptr; + status = ZwAllocateVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, 0, (PSIZE_T)&dllToInject.Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (!NT_SUCCESS(status)) { + KdPrint((PANOPTES_PREFIX_ERROR "Unable to allocate memory for the absolute DLL path in the target process (%u)\n", processId)); + return; + } + RtlCopyMemory(allocatedAddressContainingDllFullPath, dllToInject.Buffer, dllToInject.Length); + + PKAPC pKapc = (PKAPC)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KAPC), DRIVER_TAG); + if (!pKapc) { + KdPrint((PANOPTES_PREFIX_ERROR "Unable to allocate the KAPC object (%u)\n", processId)); + ZwFreeVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, (PSIZE_T)&dllToInject.Length, MEM_RELEASE); // Free the allocated memory + return; + } + + KeInitializeApc(pKapc, KeGetCurrentThread(), OriginalApcEnvironment, KernelRundown, NULL, (PKNORMAL_ROUTINE)(functionAddress), UserMode, allocatedAddressContainingDllFullPath); // Initialize the APC + if (!KeInsertQueueApc(pKapc, NULL, NULL, IO_NO_INCREMENT)) + { + KdPrint((PANOPTES_PREFIX_ERROR "Unable to insert the KAPC object into target process(%u)\n", processId)); + ZwFreeVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, (PSIZE_T)&dllToInject.Length, MEM_RELEASE); // Free the allocated memory + ExFreePool(pKapc); // Free the APC object + return; + } + + KeTestAlertThread(UserMode); } -NTSTATUS AllocateMemoryInUserProcess(PEPROCESS targetProcess, SIZE_T Size, PVOID* AllocatedAddress) +NTSTATUS InstallKernelModeApcToInjectDll(HANDLE ProcessId, PVOID ImageBase) { - HANDLE processHandle = NULL; - NTSTATUS status; - SIZE_T allocSize = Size; - PVOID baseAddress = NULL; - - // Open a handle to the process - status = ObOpenObjectByPointer(targetProcess, - OBJ_KERNEL_HANDLE, - NULL, - PROCESS_ALL_ACCESS, - *PsProcessType, - KernelMode, - &processHandle); - - if (NT_SUCCESS(status)) { - // Allocate memory in the target process - status = ZwAllocateVirtualMemory(processHandle, - &baseAddress, - 0, - &allocSize, - MEM_COMMIT | MEM_RESERVE, - PAGE_READWRITE); - - if (NT_SUCCESS(status)) { - //RtlZeroMemory(baseAddress, Size); - *AllocatedAddress = baseAddress; - } - - // Close the process handle - ZwClose(processHandle); + PRKAPC pKapc = nullptr; + + pKapc = (PKAPC)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KAPC), DRIVER_TAG); // Allocate the APC object + if (nullptr == pKapc) { + KdPrint((PANOPTES_PREFIX_ERROR "InstallKernelModeApcToInjectDll Failed to allocate memory for the APC")); + return STATUS_INSUFFICIENT_RESOURCES; } - // Dereference the process - ObDereferenceObject(targetProcess); + KeInitializeApc(pKapc, KeGetCurrentThread(),OriginalApcEnvironment,KernelRundown, NULL,(PKNORMAL_ROUTINE)KernelAPCRoutine,KernelMode, (PVOID)ProcessId); + if (!KeInsertQueueApc(pKapc, ImageBase, NULL, IO_NO_INCREMENT)) { + KdPrint((PANOPTES_PREFIX_ERROR "InstallKernelModeApcToInjectDll Failed to insert APC")); + ExFreePool(pKapc); // Free the APC object + return STATUS_UNSUCCESSFUL; + } + else { + KdPrint((PANOPTES_PREFIX_SUCCESS "InstallKernelModeApcToInjectDll APC delivered")); + } - return status; + return STATUS_SUCCESS; } \ No newline at end of file diff --git a/src/driver/src/pano_query.cpp b/src/driver/src/pano_query.cpp deleted file mode 100644 index 410f5ca..0000000 --- a/src/driver/src/pano_query.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "pano_query.h" -#include - -NTSTATUS QueryProcessMitigationPolicy(HANDLE ProcessId, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo) { - UNREFERENCED_PARAMETER(policyInfo); - HANDLE hProcess; - PEPROCESS eProcess; - - if (ProcessId == NULL) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Invalid ProcessId\n"); - return STATUS_INVALID_PARAMETER; //0xC000000D - } - - NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &eProcess); - if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: PsLookupProcessByProcessId failed with status 0x%X\n", status); - return status; - } - - status = ObOpenObjectByPointer( - eProcess, - OBJ_KERNEL_HANDLE, - NULL, - 0x1000,//PROCESS_QUERY_LIMITED_INFORMATION, - *PsProcessType, - KernelMode, - &hProcess); - - ObDereferenceObject(eProcess); - - if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: ObOpenObjectByPointer failed with status 0x%X\n", status); - return status; - } - - PROCESS_MITIGATION_POLICY_INFORMATION policyInfoLocal; - policyInfoLocal.Policy = ProcessSignaturePolicy; - status = ZwQueryInformationProcess(hProcess, ProcessMitigationPolicy, &policyInfoLocal, sizeof(policyInfoLocal), nullptr); - if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: ZwQueryInformationProcess failed with status 0x%X\n", status); - } - - if (&policyInfoLocal != NULL) { - if (policyInfoLocal.Data.SignaturePolicy.MicrosoftSignedOnly != 0) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Process with MicrosoftOnly"); - } - } - - ZwClose(hProcess); - - return STATUS_SUCCESS; -} \ No newline at end of file diff --git a/src/driver/src/state.cpp b/src/driver/src/state.cpp new file mode 100644 index 0000000..a0ab97d --- /dev/null +++ b/src/driver/src/state.cpp @@ -0,0 +1,41 @@ +#include "pch.h" +#include "state.h" + +NTSTATUS PanoptesState::Init() { + ExInitializeFastMutex(&ProcessesLock); + RtlInitializeGenericTableAvl(&Processes, ProcessCompare, TableAlloc, TableFree, this); + ImageBase = ExAllocatePool2(POOL_FLAG_PAGED, sizeof(PVOID), DRIVER_TAG); + return STATUS_SUCCESS; +} + +RTL_GENERIC_COMPARE_RESULTS PanoptesState::ProcessCompare(PRTL_AVL_TABLE Table, PVOID FirstStruct, PVOID SecondStruct) { + UNREFERENCED_PARAMETER(Table); + + auto p1 = (PPANO_PROCESS_INFO)FirstStruct; + auto p2 = (PPANO_PROCESS_INFO)SecondStruct; + if (p1->ProcessId == p2->ProcessId) + return GenericEqual; + + return p1->ProcessId > p2->ProcessId ? GenericGreaterThan : GenericLessThan; +} + +_Use_decl_annotations_ +PVOID PanoptesState::TableAlloc(_RTL_AVL_TABLE* Table, CLONG ByteSize) { + UNREFERENCED_PARAMETER(Table); + return ExAllocatePool2(POOL_FLAG_PAGED, ByteSize, DRIVER_TAG); +} + +_Use_decl_annotations_ +VOID PanoptesState::TableFree(_RTL_AVL_TABLE* Table, PVOID Buffer) { + UNREFERENCED_PARAMETER(Table); + ExFreePool(Buffer); +} + +void PanoptesState::Term() { + PVOID element; + while ((element = RtlEnumerateGenericTableAvl(&Processes, TRUE)) != nullptr) { + RtlDeleteElementGenericTableAvl(&Processes, element); + } + + ExFreePool(ImageBase, DRIVER_TAG); +} \ No newline at end of file diff --git a/src/driver/src/utils.cpp b/src/driver/src/utils.cpp new file mode 100644 index 0000000..c801047 --- /dev/null +++ b/src/driver/src/utils.cpp @@ -0,0 +1,206 @@ +#include "utils.h" + +BOOLEAN Is64BitProcess(PEPROCESS targetProcess) { + UINT64* processAsUint64 = reinterpret_cast(targetProcess); + PVOID* wow64ProcessPtr = reinterpret_cast(processAsUint64 + 0x580 / sizeof(UINT64)); + if (*wow64ProcessPtr == NULL) + { + return TRUE; + } + return FALSE; +} + +NTSTATUS GetFileNameFromPath(PUNICODE_STRING FullPath, PUNICODE_STRING FileName) { + USHORT i; + USHORT lengthInChars; + + if (!FullPath || !FileName || !FullPath->Buffer || FullPath->Length == 0) { + return STATUS_INVALID_PARAMETER; + } + + lengthInChars = FullPath->Length / sizeof(WCHAR); + + // Search backwards for the last backslash + for (i = lengthInChars; i > 0; i--) { + if (FullPath->Buffer[i - 1] == L'\\') { + break; + } + } + + // Set up the filename UNICODE_STRING (points to existing buffer) + FileName->Buffer = &FullPath->Buffer[i]; + FileName->Length = (lengthInChars - i) * sizeof(WCHAR); + FileName->MaximumLength = FileName->Length; + + return STATUS_SUCCESS; +} + +NTSTATUS QueryProcessMitigationPolicy(HANDLE ProcessId, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo) { + UNREFERENCED_PARAMETER(policyInfo); + HANDLE hProcess; + PEPROCESS eProcess; + + if (ProcessId == NULL) { + DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Invalid ProcessId\n"); + return STATUS_INVALID_PARAMETER; //0xC000000D + } + + NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &eProcess); + if (!NT_SUCCESS(status)) { + DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: PsLookupProcessByProcessId failed with status 0x%X\n", status); + return status; + } + + status = ObOpenObjectByPointer( + eProcess, + OBJ_KERNEL_HANDLE, + NULL, + 0x1000,//PROCESS_QUERY_LIMITED_INFORMATION, + *PsProcessType, + KernelMode, + &hProcess); + + ObDereferenceObject(eProcess); + + if (!NT_SUCCESS(status)) { + DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: ObOpenObjectByPointer failed with status 0x%X\n", status); + return status; + } + + PROCESS_MITIGATION_POLICY_INFORMATION policyInfoLocal; + policyInfoLocal.Policy = ProcessSignaturePolicy; + status = ZwQueryInformationProcess(hProcess, ProcessMitigationPolicy, &policyInfoLocal, sizeof(policyInfoLocal), nullptr); + if (!NT_SUCCESS(status)) { + DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: ZwQueryInformationProcess failed with status 0x%X\n", status); + } + + if (&policyInfoLocal != NULL) { + if (policyInfoLocal.Data.SignaturePolicy.MicrosoftSignedOnly != 0) { + DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Process with MicrosoftOnly"); + } + } + + ZwClose(hProcess); + + return STATUS_SUCCESS; +} + +PVOID NTAPI RtlxFindExportedRoutineByName(_In_ PVOID DllBase, _In_ PANSI_STRING ExportName) { + // + // RtlFindExportedRoutineByName is not exported by ntoskrnl until Win10. + // Following code is borrowed from ReactOS. + // + + PULONG NameTable; + PUSHORT OrdinalTable; + PIMAGE_EXPORT_DIRECTORY ExportDirectory; + LONG Low = 0, Mid = 0, High, Ret; + USHORT Ordinal; + PVOID Function; + ULONG ExportSize; + PULONG ExportTable; + + // + // Get the export directory. + // + + ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(DllBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportSize); + + if (!ExportDirectory) + { + return NULL; + } + + // + // Setup name tables. + // + + NameTable = (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfNames); + OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase + ExportDirectory->AddressOfNameOrdinals); + + // + // Do a binary search. + // + + High = ExportDirectory->NumberOfNames - 1; + while (High >= Low) + { + // + // Get new middle value. + // + + Mid = (Low + High) >> 1; + + // + // Compare name. + // + + Ret = strcmp(ExportName->Buffer, (PCHAR)DllBase + NameTable[Mid]); + if (Ret < 0) + { + // + // Update high. + // + High = Mid - 1; + } + else if (Ret > 0) + { + // + // Update low. + // + Low = Mid + 1; + } + else + { + // + // We got it. + // + break; + } + } + + // + // Check if we couldn't find it. + // + + if (High < Low) + { + return NULL; + } + + // + // Otherwise, this is the ordinal. + // + + Ordinal = OrdinalTable[Mid]; + + // + // Validate the ordinal. + // + + if (Ordinal >= ExportDirectory->NumberOfFunctions) + { + return NULL; + } + + // + // Resolve the address and write it. + // + + ExportTable = (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfFunctions); + Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]); + + // + // We found it! + // + + NT_ASSERT( + (Function < (PVOID)ExportDirectory) || + (Function > (PVOID)((ULONG_PTR)ExportDirectory + ExportSize)) + ); + + return Function; +} From e2a4eb06e8dbc27ee1b64283208725cdd630fcbf Mon Sep 17 00:00:00 2001 From: Ap3x Date: Tue, 25 Nov 2025 22:57:50 -0700 Subject: [PATCH 03/16] fix spacing and uncomment filter driver --- src/driver/src/callbacks.cpp | 3 +-- src/driver/src/driver.cpp | 16 ++++++++-------- src/driver/src/inject.cpp | 27 +++++++++++++-------------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/driver/src/callbacks.cpp b/src/driver/src/callbacks.cpp index e18cbef..af29429 100644 --- a/src/driver/src/callbacks.cpp +++ b/src/driver/src/callbacks.cpp @@ -5,8 +5,7 @@ PanoptesState g_State{}; -PPANO_PROCESS_INFO GetProcessInfo(HANDLE ProcessId) -{ +PPANO_PROCESS_INFO GetProcessInfo(HANDLE ProcessId) { auto pi = (PPANO_PROCESS_INFO)RtlLookupElementGenericTableAvl(&g_State.Processes, &ProcessId); if (pi != nullptr) { return pi; diff --git a/src/driver/src/driver.cpp b/src/driver/src/driver.cpp index 45d652a..c6bb93d 100644 --- a/src/driver/src/driver.cpp +++ b/src/driver/src/driver.cpp @@ -12,7 +12,7 @@ UNICODE_STRING g_SymbolicLinkName; void UnloadPanoptes(PDRIVER_OBJECT DriverObject) { PAGED_CODE(); KdPrint(( PANOPTES_PREFIX_SUCCESS "Driver Exit\n")); - //Log_DriverExit(DriverObject); + Log_DriverExit(DriverObject); //IoDeleteDevice(driver_object); //IoDeleteSymbolicLink(&g_symLink); RemoveCallbacks(); @@ -22,15 +22,15 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) PAGED_CODE(); DriverObject->DriverUnload = UnloadPanoptes; - //TraceInitialize(); + TraceInitialize(); - //Log_DriverEntry(DriverObject, RegistryPath); + Log_DriverEntry(DriverObject, RegistryPath); - //NTSTATUS status = FilterInit(&DriverObject); - //if (!NT_SUCCESS(status)) { - // KdPrint(( PANOPTES_PREFIX_ERROR "An error occured when attempting to initialized filter\n")); - // return status; - //} + NTSTATUS status = FilterInit(&DriverObject); + if (!NT_SUCCESS(status)) { + KdPrint(( PANOPTES_PREFIX_ERROR "An error occured when attempting to initialized filter\n")); + return status; + } //status = InitializeDriverLink(driver_object); //if (!NT_SUCCESS(status)) diff --git a/src/driver/src/inject.cpp b/src/driver/src/inject.cpp index 79e09c1..8e841b2 100644 --- a/src/driver/src/inject.cpp +++ b/src/driver/src/inject.cpp @@ -29,23 +29,22 @@ VOID KernelAPCRoutine(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemAr } #ifdef _DEBUG - PUNICODE_STRING processPath{}; - status = SeLocateProcessImageName(targetProcess, &processPath); - if (!NT_SUCCESS(status)) { - return; - } - - UNICODE_STRING onlyProc{}; - RtlInitUnicodeString(&onlyProc, L"die.exe"); - if (wcsstr(processPath->Buffer, onlyProc.Buffer) == NULL) { - return; - } + //PUNICODE_STRING processPath{}; + //status = SeLocateProcessImageName(targetProcess, &processPath); + //if (!NT_SUCCESS(status)) { + // return; + //} + + //UNICODE_STRING onlyProc{}; + //RtlInitUnicodeString(&onlyProc, L"die.exe"); + //if (wcsstr(processPath->Buffer, onlyProc.Buffer) == NULL) { + // return; + //} #endif ANSI_STRING loadDllRoutineName = RTL_CONSTANT_STRING("LoadLibraryExW"); - PVOID testVal2 = SystemArgument1; - PVOID testVal3 = *static_cast(testVal2); - PVOID functionAddress = RtlxFindExportedRoutineByName(testVal3, &loadDllRoutineName); + PVOID rawImageBaseAddress = *static_cast(SystemArgument1); + PVOID functionAddress = RtlxFindExportedRoutineByName(rawImageBaseAddress, &loadDllRoutineName); if (functionAddress == nullptr) { KdPrint((PANOPTES_PREFIX_ERROR "Unable to find LoadLibraryExW in target process (%u)\n", processId)); return; From d211eebb40a70a2164984ceb1712766c360054db Mon Sep 17 00:00:00 2001 From: Ap3x Date: Tue, 2 Dec 2025 17:30:47 -0700 Subject: [PATCH 04/16] Major overhaul --- src/dll/CMakeLists.txt | 13 ++ src/driver/include/callbacks.h | 3 +- src/driver/include/filter.h | 15 +- src/driver/include/inject.h | 2 +- src/driver/include/state.h | 15 +- src/driver/include/trace.h | 3 +- src/driver/include/utils.h | 17 +- src/driver/src/callbacks.cpp | 206 +++++++++++++------ src/driver/src/driver.cpp | 33 ++- src/driver/src/filter.cpp | 355 ++++++++++++++++++++------------- src/driver/src/inject.cpp | 92 ++++++--- src/driver/src/state.cpp | 9 +- src/driver/src/trace.cpp | 11 +- src/driver/src/utils.cpp | 173 +--------------- 14 files changed, 528 insertions(+), 419 deletions(-) diff --git a/src/dll/CMakeLists.txt b/src/dll/CMakeLists.txt index 7cd0e50..80ff973 100644 --- a/src/dll/CMakeLists.txt +++ b/src/dll/CMakeLists.txt @@ -81,6 +81,19 @@ function(configure_target TARGET_NAME ARCH) $<$:/DEBUG:NONE> ) endif() + + # Sign DLL using the same certificate as the Driver + if(ARCH STREQUAL "x64") + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + COMMAND "${x64_BUILD_TOOLS_PATH}/signtool.exe" sign /a /v /fd sha256 /s PanoptesCertStore /n "Panoptes" /t http://timestamp.digicert.com "$" + COMMENT "Signing the DLL" + ) + else() + add_custom_command(TARGET ${TARGET_NAME} POST_BUILD + COMMAND "${x86_BUILD_TOOLS_PATH}signtool.exe" sign /a /v /fd sha256 /s PanoptesCertStore /n "Panoptes" /t http://timestamp.digicert.com "$" + COMMENT "Signing the DLL" + ) + endif() endfunction() # Create x64 and x86 targets diff --git a/src/driver/include/callbacks.h b/src/driver/include/callbacks.h index 6b8f1b3..4ad6a0d 100644 --- a/src/driver/include/callbacks.h +++ b/src/driver/include/callbacks.h @@ -1,7 +1,8 @@ #pragma once #include "pch.h" +#include "state.h" EXTERN_C BOOLEAN NTAPI PsIsProtectedProcess(_In_ PEPROCESS Process); VOID RemoveCallbacks(); -NTSTATUS InitializeKernelCallbacks(); +NTSTATUS InitializeKernelCallbacks(PanoptesState* State); diff --git a/src/driver/include/filter.h b/src/driver/include/filter.h index 28c76fd..cf8e441 100644 --- a/src/driver/include/filter.h +++ b/src/driver/include/filter.h @@ -1,4 +1,17 @@ #pragma once #include +#include "state.h" + +NTSTATUS FilterInitialize(PDRIVER_OBJECT DriverObject, PanoptesState* State); +FLT_POSTOP_CALLBACK_STATUS PostOperationCallback(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID CompletionContext, FLT_POST_OPERATION_FLAGS Flags); +NTSTATUS FilterUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags); + +const FLT_OPERATION_REGISTRATION Callbacks[] = { + { IRP_MJ_CREATE,0,NULL,PostOperationCallback }, + { IRP_MJ_READ, 0,NULL, PostOperationCallback }, + { IRP_MJ_WRITE, 0, NULL, PostOperationCallback }, + { IRP_MJ_CREATE_NAMED_PIPE, 0, NULL, PostOperationCallback}, + { IRP_MJ_CREATE_MAILSLOT, 0, NULL, PostOperationCallback }, + { IRP_MJ_OPERATION_END} +}; -NTSTATUS FilterInit(PDRIVER_OBJECT* DriverObject); diff --git a/src/driver/include/inject.h b/src/driver/include/inject.h index eaacd8e..74ecd89 100644 --- a/src/driver/include/inject.h +++ b/src/driver/include/inject.h @@ -261,4 +261,4 @@ EXTERN_C BOOLEAN NTAPI KeTestAlertThread( IN KPROCESSOR_MODE AlertMode ); -NTSTATUS InstallKernelModeApcToInjectDll(HANDLE ProcessId, PVOID ImageBase); +NTSTATUS InstallKernelModeApcToInjectDll(HANDLE ProcessId, PVOID ImageBase, BOOLEAN is64Bit); diff --git a/src/driver/include/state.h b/src/driver/include/state.h index 21b1d74..f310794 100644 --- a/src/driver/include/state.h +++ b/src/driver/include/state.h @@ -1,14 +1,17 @@ #pragma once +#include #include typedef struct _PANO_PROCESS_INFO { ULONG ProcessId; - BOOLEAN is64Bit; BOOLEAN Injected; - BOOLEAN kernel32Loaded; - BOOLEAN kernelBaseLoaded; - BOOLEAN ntdllLoaded; + BOOLEAN Kernel32Loaded; + BOOLEAN KernelBaseLoaded; + BOOLEAN NtdllLoaded; + BOOLEAN Wow64Loaded; + BOOLEAN MitigationPolicyBan; + PVOID Kernel32ImageBase; } PANO_PROCESS_INFO, * PPANO_PROCESS_INFO; struct PanoptesState { @@ -16,7 +19,9 @@ struct PanoptesState { RTL_AVL_TABLE Processes; FAST_MUTEX ProcessesLock; PCALLBACK_OBJECT ProcessCreateCallback; - PVOID ImageBase; + PFLT_FILTER FilterHandle; + UNICODE_STRING g_symLink; + UNICODE_STRING g_SymbolicLinkName; NTSTATUS Init(); void Term(); diff --git a/src/driver/include/trace.h b/src/driver/include/trace.h index e0cdc3a..a12081a 100644 --- a/src/driver/include/trace.h +++ b/src/driver/include/trace.h @@ -3,7 +3,8 @@ #include #pragma region TraceLogging Initialization -void TraceInitialize(BOOLEAN initialize = true); +void TraceInitialize(); +void TraceTerminate(); #pragma endregion #pragma region Driver Operations diff --git a/src/driver/include/utils.h b/src/driver/include/utils.h index 150e729..5c15e1f 100644 --- a/src/driver/include/utils.h +++ b/src/driver/include/utils.h @@ -36,16 +36,15 @@ EXTERN_C NTSTATUS NTAPI ZwQueryInformationProcess( SIZE_T* /*PULONG*/ returnLength ); -EXTERN_C PVOID NTAPI RtlImageDirectoryEntryToData( - _In_ PVOID BaseOfImage, - _In_ BOOLEAN MappedAsImage, - _In_ USHORT DirectoryEntry, - _Out_ PULONG Size +EXTERN_C NTSTATUS NTAPI ZwQueryInformationToken( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation OPTIONAL, + IN ULONG TokenInformationLength, + OUT PULONG ReturnLength ); -BOOLEAN Is64BitProcess(PEPROCESS targetProcess); NTSTATUS GetFileNameFromPath(PUNICODE_STRING FullPath, PUNICODE_STRING FileName); -NTSTATUS QueryProcessMitigationPolicy(HANDLE ProcessId, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo); +NTSTATUS QueryProcessMitigationPolicy(PEPROCESS ProcessId, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo); -PVOID NTAPI RtlxFindExportedRoutineByName(_In_ PVOID DllBase, _In_ PANSI_STRING ExportName); -EXTERN_C PVOID RtlImageDirectoryEntryToData(IN PVOID Base, IN BOOLEAN MappedAsImage, IN USHORT DirectoryEntry, OUT PULONG Size); +EXTERN_C PVOID NTAPI RtlFindExportedRoutineByName(_In_ PVOID DllBase, _In_ PCSTR RoutineName); diff --git a/src/driver/src/callbacks.cpp b/src/driver/src/callbacks.cpp index af29429..16cd8a4 100644 --- a/src/driver/src/callbacks.cpp +++ b/src/driver/src/callbacks.cpp @@ -1,113 +1,209 @@ #include "callbacks.h" -#include "state.h" #include "inject.h" #include "utils.h" - -PanoptesState g_State{}; +#include +PanoptesState* g_pState = nullptr; PPANO_PROCESS_INFO GetProcessInfo(HANDLE ProcessId) { - auto pi = (PPANO_PROCESS_INFO)RtlLookupElementGenericTableAvl(&g_State.Processes, &ProcessId); + ULONG id = HandleToUlong(ProcessId); + auto pi = (PPANO_PROCESS_INFO)RtlLookupElementGenericTableAvl(&g_pState->Processes, &id); if (pi != nullptr) { return pi; } return nullptr; } -VOID RemoveProcessInfo(HANDLE ProcessId) { - ExAcquireFastMutex(&g_State.ProcessesLock); - PANO_PROCESS_INFO pi; - pi.ProcessId = HandleToUlong(ProcessId); - RtlDeleteElementGenericTableAvl(&g_State.Processes, &pi); - KdPrint((PANOPTES_PREFIX_SUCCESS "Process %u deleted from table\n", pi.ProcessId)); - ExReleaseFastMutex(&g_State.ProcessesLock); - return; -} - // https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/windows-kernel-mode-process-and-thread-manager#best // This callback is ran in PASSIVE_LEVEL IRQL, but with safe mode enabled so no actions that would lock this function and prevent the image from loading like mutexes VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo) { UNREFERENCED_PARAMETER(ImageInfo); ULONG id = HandleToUlong(ProcessId); - if (PsIsProtectedProcess(PsGetCurrentProcess())){ - KdPrint((PANOPTES_PREFIX_WARNING "Skipping protected process %u\n", id)); - RemoveProcessInfo(ProcessId); + PPANO_PROCESS_INFO pi = GetProcessInfo(ProcessId); + if (pi == nullptr) { + return; + } + + if (pi->Injected || pi->MitigationPolicyBan) { return; } UNICODE_STRING loadedImageName{}; GetFileNameFromPath(FullImageName, &loadedImageName); - auto pi = GetProcessInfo(ProcessId); - if (pi == nullptr) { - return; + // NTDLL must be loaded for the hooks to work + if (!pi->NtdllLoaded) { + UNICODE_STRING ntdllLoadImage; + RtlInitUnicodeString(&ntdllLoadImage, L"ntdll.dll"); + if (RtlCompareUnicodeString(&ntdllLoadImage, &loadedImageName, TRUE) == 0) { + pi->NtdllLoaded = TRUE; + + PEPROCESS targetProcess{}; + NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &targetProcess); + if (!NT_SUCCESS(status)) { + return; + } + + PROCESS_MITIGATION_POLICY_INFORMATION policyInfo; + policyInfo.Policy = ProcessSignaturePolicy; + + status = QueryProcessMitigationPolicy(targetProcess, &policyInfo); + if (!NT_SUCCESS(status)) { + ObDereferenceObject(targetProcess); + return; + } + + if (policyInfo.Data.SignaturePolicy.MicrosoftSignedOnly != 0 || + policyInfo.Data.SignaturePolicy.StoreSignedOnly != 0 || + policyInfo.Data.SignaturePolicy.MitigationOptIn != 0) { + pi->MitigationPolicyBan = TRUE; + ObDereferenceObject(targetProcess); + return; + } + + ObDereferenceObject(targetProcess); + } } - - if (pi->kernel32Loaded && pi->kernelBaseLoaded && pi->ntdllLoaded) { - if (pi->Injected) { + + if (!pi->Wow64Loaded) { + //Check if x86 process and ensure that it will be ready to be injected into + UNICODE_STRING ntdllLoadImage; + RtlInitUnicodeString(&ntdllLoadImage, L"wow64.dll"); + if (RtlCompareUnicodeString(&ntdllLoadImage, &loadedImageName, TRUE) == 0) { + pi->Wow64Loaded = TRUE; return; } - KdPrint((PANOPTES_PREFIX_SUCCESS "All required images loaded for process %u, attempting injection\n", id)); - auto test = g_State.ImageBase; - InstallKernelModeApcToInjectDll(ProcessId, test); - pi->Injected = TRUE; - return; } - - UNICODE_STRING ntdllLoadImage; - RtlInitUnicodeString(&ntdllLoadImage, L"ntdll.dll"); - if (RtlCompareUnicodeString(&ntdllLoadImage, &loadedImageName, TRUE) == 0) { - pi->ntdllLoaded = TRUE; + + if (!pi->Kernel32Loaded) { + // Kernel32 and KernelBase must be loaded for the inject to work + UNICODE_STRING kernel32LoadImage; + RtlInitUnicodeString(&kernel32LoadImage, L"kernel32.dll"); + if (RtlCompareUnicodeString(&kernel32LoadImage, &loadedImageName, TRUE) == 0) { + pi->Kernel32Loaded = TRUE; + pi->Kernel32ImageBase = ImageInfo->ImageBase; + return; + } } - UNICODE_STRING kernel32LoadImage; - RtlInitUnicodeString(&kernel32LoadImage, L"kernel32.dll"); - if (RtlCompareUnicodeString(&kernel32LoadImage, &loadedImageName, TRUE) == 0) { - PVOID ImageBaseValue = g_State.ImageBase; - if (ImageBaseValue == nullptr) { + if (!pi->KernelBaseLoaded) { + // Kernel32 and KernelBase must be loaded for the inject to work + UNICODE_STRING kernelbaseLoadImage; + RtlInitUnicodeString(&kernelbaseLoadImage, L"kernelbase.dll"); + if (RtlCompareUnicodeString(&kernelbaseLoadImage, &loadedImageName, TRUE) == 0) { + pi->KernelBaseLoaded = TRUE; return; } - RtlCopyMemory(g_State.ImageBase, &ImageInfo->ImageBase, sizeof(PVOID)); - pi->kernel32Loaded = TRUE; } - UNICODE_STRING kernelbaseLoadImage; - RtlInitUnicodeString(&kernel32LoadImage, L"kernelbase.dll"); - if (RtlCompareUnicodeString(&kernel32LoadImage, &loadedImageName, TRUE) == 0) { - KdPrint((PANOPTES_PREFIX_SUCCESS "Attempting to injected Into %u\n", id)); - pi->kernelBaseLoaded = TRUE; + if (pi->Kernel32Loaded && pi->KernelBaseLoaded) { + if (pi->Kernel32ImageBase != nullptr) { + pi->Injected = TRUE; + InstallKernelModeApcToInjectDll(ProcessId, &pi->Kernel32ImageBase, pi->Wow64Loaded); + } } return; } +NTSTATUS IsIgnoredExecutable(ULONG* ProcessId, BOOLEAN* result) { + PEPROCESS targetProcess{}; + NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &targetProcess); + if (!NT_SUCCESS(status)) { + return status; + } + + PUNICODE_STRING processPath = NULL; + status = SeLocateProcessImageName(targetProcess, &processPath); + if (!NT_SUCCESS(status)) { + ObDereferenceObject(targetProcess); + return status; + } + + UNICODE_STRING processPathFile{}; + GetFileNameFromPath(processPath, &processPathFile); + + UNICODE_STRING ignore1; + UNICODE_STRING ignore2; + UNICODE_STRING ignore3; + UNICODE_STRING ignore4; + UNICODE_STRING ignore5; + UNICODE_STRING ignore6; + UNICODE_STRING ignore7; + RtlInitUnicodeString(&ignore1, L"\\Device\\HarddiskVolume3\\Windows\\System32\\dllhost.exe"); + // Windows Update Binary + RtlInitUnicodeString(&ignore2, L"\\Device\\HarddiskVolume3\\Windows\\System32\\mousocoreworker.exe"); + RtlInitUnicodeString(&ignore3, L"\\Device\\HarddiskVolume3\\Windows\\System32\\USOCoreWorker.exe"); + RtlInitUnicodeString(&ignore4, L"\\Device\\HarddiskVolume3\\Windows\\System32\\USOClient.exe"); + + RtlInitUnicodeString(&ignore5, L"msedgewebview2.exe"); + RtlInitUnicodeString(&ignore6, L"\\Device\\HarddiskVolume3\\Windows\\SysWOW64\\WerFault.exe"); + RtlInitUnicodeString(&ignore7, L"\\Device\\HarddiskVolume3\\Windows\\System32\\WerFault.exe"); + + if (RtlEqualUnicodeString(&processPathFile, &ignore5, TRUE)) { + ExFreePool(processPath); + ObDereferenceObject(targetProcess); + return STATUS_UNSUCCESSFUL; + } + + if (RtlEqualUnicodeString(processPath, &ignore1, TRUE) || + RtlEqualUnicodeString(processPath, &ignore2, TRUE) || + RtlEqualUnicodeString(processPath, &ignore3, TRUE) || + RtlEqualUnicodeString(processPath, &ignore4, TRUE) || + RtlEqualUnicodeString(processPath, &ignore6, TRUE) || + RtlEqualUnicodeString(processPath, &ignore7, TRUE) + ) { + ExFreePool(processPath); + ObDereferenceObject(targetProcess); + *result = true; + return STATUS_SUCCESS; + } + + ObDereferenceObject(targetProcess); + *result = false ; + return STATUS_SUCCESS; +} + _Use_decl_annotations_ VOID ProcessCreateCallback(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo) { UNREFERENCED_PARAMETER(Process); ULONG id = HandleToUlong(ProcessId); if (CreateInfo != NULL) { - ExAcquireFastMutex(&g_State.ProcessesLock); - //Check if process info already exists - auto pi = (PPANO_PROCESS_INFO)RtlLookupElementGenericTableAvl(&g_State.Processes, &id); + if (PsIsProtectedProcess(PsGetCurrentProcess())) { + return; + } + + ExAcquireFastMutex(&g_pState->ProcessesLock); + auto pi = (PPANO_PROCESS_INFO)RtlLookupElementGenericTableAvl(&g_pState->Processes, &id); if (pi == nullptr) { + BOOLEAN ignored = false; + IsIgnoredExecutable(&id, &ignored); + PANO_PROCESS_INFO newProcessEntry{}; newProcessEntry.ProcessId = id; - pi = (PPANO_PROCESS_INFO)RtlInsertElementGenericTableAvl(&g_State.Processes, &newProcessEntry, sizeof(newProcessEntry), nullptr); - KdPrint((PANOPTES_PREFIX_SUCCESS "Process %u added to table\n", id)); + BOOLEAN successInsert = false; + + pi = (PPANO_PROCESS_INFO)RtlInsertElementGenericTableAvl(&g_pState->Processes, &newProcessEntry, sizeof(newProcessEntry), &successInsert); + if (!successInsert) { + KdPrint((PANOPTES_PREFIX_ERROR "Error inserting process into AVL tree\n")); + } } - ExReleaseFastMutex(&g_State.ProcessesLock); + ExReleaseFastMutex(&g_pState->ProcessesLock); } else { - RemoveProcessInfo(&id); - KdPrint((PANOPTES_PREFIX_SUCCESS "Process %u terminated and removed from table\n", id)); + ExAcquireFastMutex(&g_pState->ProcessesLock); + RtlDeleteElementGenericTableAvl(&g_pState->Processes, &id); + ExReleaseFastMutex(&g_pState->ProcessesLock); } } -NTSTATUS InitializeKernelCallbacks() { +NTSTATUS InitializeKernelCallbacks(PanoptesState* State) { PAGED_CODE(); NTSTATUS status; + g_pState = State; + status = PsSetCreateProcessNotifyRoutineEx(ProcessCreateCallback, FALSE); if (!NT_SUCCESS(status)) { KdPrint((PANOPTES_PREFIX_ERROR "Driver Failed to Set Process Creation Notify Routine Notify Routine - Ensure /INTEGRITYCHECK is added to the linker options\n")); @@ -129,7 +225,6 @@ NTSTATUS InitializeKernelCallbacks() { } KdPrint((PANOPTES_PREFIX_SUCCESS "Set Image Load Notify Callbacks\n")); - status = g_State.Init(); return STATUS_SUCCESS; } @@ -137,6 +232,5 @@ NTSTATUS InitializeKernelCallbacks() { VOID RemoveCallbacks() { PsSetCreateProcessNotifyRoutineEx(ProcessCreateCallback, TRUE); PsRemoveLoadImageNotifyRoutine(LoadImageNotifyRoutine); - g_State.Term(); return; } diff --git a/src/driver/src/driver.cpp b/src/driver/src/driver.cpp index c6bb93d..b126b03 100644 --- a/src/driver/src/driver.cpp +++ b/src/driver/src/driver.cpp @@ -4,42 +4,53 @@ #include "filter.h" #include "state.h" -UNICODE_STRING g_deviceName; -UNICODE_STRING g_symLink; -PDEVICE_OBJECT g_deviceObject; -UNICODE_STRING g_SymbolicLinkName; +PanoptesState g_State{}; void UnloadPanoptes(PDRIVER_OBJECT DriverObject) { PAGED_CODE(); - KdPrint(( PANOPTES_PREFIX_SUCCESS "Driver Exit\n")); - Log_DriverExit(DriverObject); - //IoDeleteDevice(driver_object); - //IoDeleteSymbolicLink(&g_symLink); + + // Remove callbacks first to prevent new accesses to state RemoveCallbacks(); + + FltUnregisterFilter(g_State.FilterHandle); + + // Now safe to clean up state - no callbacks can access it + g_State.Term(); + + Log_DriverExit(DriverObject); + + TraceTerminate(); } NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) { PAGED_CODE(); + NTSTATUS status = NULL; DriverObject->DriverUnload = UnloadPanoptes; + + status = g_State.Init(); + if (!NT_SUCCESS(status)) { + KdPrint(( PANOPTES_PREFIX_ERROR "An error occured when attempting to initialize global state\n")); + return status; + } TraceInitialize(); Log_DriverEntry(DriverObject, RegistryPath); - NTSTATUS status = FilterInit(&DriverObject); + status = FilterInitialize(DriverObject, &g_State); if (!NT_SUCCESS(status)) { KdPrint(( PANOPTES_PREFIX_ERROR "An error occured when attempting to initialized filter\n")); return status; } - //status = InitializeDriverLink(driver_object); + //status = InitializeDriverLink(DriverObject); //if (!NT_SUCCESS(status)) //{ // KdPrint(( PANOPTES_PREFIX_ERROR "An error occured when attempting to initialized device pipe\n")); // return status; //} - NTSTATUS status = InitializeKernelCallbacks(); + status = InitializeKernelCallbacks(&g_State); if (!NT_SUCCESS(status)) { KdPrint(( PANOPTES_PREFIX_ERROR "An error occured when attempting to initialized kernel callbacks\n")); diff --git a/src/driver/src/filter.cpp b/src/driver/src/filter.cpp index 908fef1..6d5ff7f 100644 --- a/src/driver/src/filter.cpp +++ b/src/driver/src/filter.cpp @@ -1,57 +1,168 @@ #include "filter.h" #include "trace.h" +#include "state.h" -PFLT_FILTER g_FilterHandle; +PFLT_FILTER FilterHandle{}; -PWCH GetFileInfo(PFLT_CALLBACK_DATA Data) { - PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; - NTSTATUS status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_FILESYSTEM_ONLY | FLT_FILE_NAME_DO_NOT_CACHE, &fileNameInfo); + +NTSTATUS FilterUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags) { + PAGED_CODE(); + NTSTATUS status; + + if (FilterHandle == nullptr) { + status = STATUS_SUCCESS; + } + else { + if (Flags == FLTFL_FILTER_UNLOAD_MANDATORY) { + FltUnregisterFilter(FilterHandle); + status = STATUS_SUCCESS; + } + else { + status = STATUS_FLT_DO_NOT_DETACH; + } + } + + return status; +} + +const FLT_REGISTRATION FilterRegistration = { + sizeof(FLT_REGISTRATION), // Size + FLT_REGISTRATION_VERSION, // Version + 0, // Flags + NULL, // Context Registration. + Callbacks, // Operation callbacks + FilterUnload, // FilterUnload + NULL, // InstanceSetup + NULL, // InstanceQueryTeardown + NULL, // InstanceTeardownStart + NULL, // InstanceTeardownComplete + NULL // GenerateFileName +}; + +NTSTATUS FilterInitialize(PDRIVER_OBJECT DriverObject, PanoptesState* State) { + FilterHandle = State->FilterHandle; + + NTSTATUS status = FltRegisterFilter(DriverObject, &FilterRegistration, &State->FilterHandle); if (!NT_SUCCESS(status)) { - DbgPrint("Error getting file info\n"); + switch (status) + { + case STATUS_INSUFFICIENT_RESOURCES: + KdPrint((PANOPTES_PREFIX_ERROR "Filter Registration Error:STATUS_INSUFFICIENT_RESOURCES\n")); + break; + case STATUS_INVALID_PARAMETER: + KdPrint((PANOPTES_PREFIX_ERROR "Filter Registration Error: STATUS_INVALID_PARAMETER\n")); + break; + case STATUS_FLT_NOT_INITIALIZED: + KdPrint((PANOPTES_PREFIX_ERROR "Filter Registration Error: STATUS_FLT_NOT_INITIALIZED\n")); + break; + case STATUS_OBJECT_NAME_NOT_FOUND: + KdPrint((PANOPTES_PREFIX_ERROR "Filter Registration Error: STATUS_OBJECT_NAME_NOT_FOUND\n")); + break; + default: + KdPrint((PANOPTES_PREFIX_ERROR "Filter Registration Error: UNKNOWN\n")); + break; + } + return status; } - if (fileNameInfo == NULL) { - return Data->Iopb->TargetFileObject->FileName.Buffer; + status = FltStartFiltering(State->FilterHandle); + if (!NT_SUCCESS(status)) { + KdPrint((PANOPTES_PREFIX_ERROR "Failed to start filtering\n")); + FltUnregisterFilter(State->FilterHandle); + State->FilterHandle = nullptr; + return status; } - else { - return fileNameInfo->Name.Buffer; + + return status; +} + +NTSTATUS GetFileInfo(PFLT_CALLBACK_DATA Data, PUNICODE_STRING* OutFileName) { + PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; + NTSTATUS status = FltGetFileNameInformation(Data, + FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_FILESYSTEM_ONLY | FLT_FILE_NAME_DO_NOT_CACHE, + &fileNameInfo); + if (!NT_SUCCESS(status)) { + return status; + } + + SIZE_T totalSize = sizeof(UNICODE_STRING) + fileNameInfo->Name.Length + sizeof(WCHAR); + PUNICODE_STRING result = (PUNICODE_STRING)ExAllocatePoolWithTag(PagedPool, totalSize, DRIVER_TAG); + if (!result) { + FltReleaseFileNameInformation(fileNameInfo); + return STATUS_INSUFFICIENT_RESOURCES; } + + result->Buffer = (PWCH)(result + 1); + result->Length = fileNameInfo->Name.Length; + result->MaximumLength = fileNameInfo->Name.Length + sizeof(WCHAR); + + RtlCopyMemory(result->Buffer, fileNameInfo->Name.Buffer, fileNameInfo->Name.Length); + result->Buffer[fileNameInfo->Name.Length / sizeof(WCHAR)] = L'\0'; + + *OutFileName = result; + FltReleaseFileNameInformation(fileNameInfo); + return STATUS_SUCCESS; } void MailSlotStatus(PFLT_CALLBACK_DATA Data) { - PWCH fileName = GetFileInfo(Data); + PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; + NTSTATUS status = FltGetFileNameInformation(Data, + FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_FILESYSTEM_ONLY | FLT_FILE_NAME_DO_NOT_CACHE, + &fileNameInfo); + if (!NT_SUCCESS(status)) { + return; + } + HANDLE sourceProcessId = PsGetCurrentProcessId(); HANDLE sourceThreadId = PsGetThreadId(Data->Thread); switch (Data->IoStatus.Information) { case FILE_CREATED: - Log_MailSlotCreate(sourceProcessId, sourceThreadId, fileName); + Log_MailSlotCreate(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); break; case FILE_OPENED: - Log_MailSlotOpen(sourceProcessId, sourceThreadId, fileName); + Log_MailSlotOpen(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); break; } + + FltReleaseFileNameInformation(fileNameInfo); } void NamedPipeStatus(PFLT_CALLBACK_DATA Data) { - PWCH fileName = GetFileInfo(Data); + PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; + NTSTATUS status = FltGetFileNameInformation(Data, + FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_FILESYSTEM_ONLY | FLT_FILE_NAME_DO_NOT_CACHE, + &fileNameInfo); + if (!NT_SUCCESS(status)) { + return; + } + HANDLE sourceProcessId = PsGetCurrentProcessId(); HANDLE sourceThreadId = PsGetThreadId(Data->Thread); switch (Data->IoStatus.Information) { case FILE_CREATED: - Log_NamedPipeCreate(sourceProcessId, sourceThreadId, fileName); + Log_NamedPipeCreate(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); break; case FILE_OPENED: - Log_NamedPipeOpen(sourceProcessId, sourceThreadId, fileName); + Log_NamedPipeOpen(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); break; } + + FltReleaseFileNameInformation(fileNameInfo); } void FileWriteStatus(PFLT_CALLBACK_DATA Data) { - PWCH fileName = GetFileInfo(Data); + PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; + NTSTATUS status = FltGetFileNameInformation(Data, + FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_FILESYSTEM_ONLY | FLT_FILE_NAME_DO_NOT_CACHE, + &fileNameInfo); + if (!NT_SUCCESS(status)) { + return; + } + HANDLE sourceProcessId = PsGetCurrentProcessId(); HANDLE sourceThreadId = PsGetThreadId(Data->Thread); ULONG writeLength = Data->Iopb->Parameters.Write.Length; @@ -60,16 +171,24 @@ void FileWriteStatus(PFLT_CALLBACK_DATA Data) { switch (Data->Iopb->MinorFunction) { case IRP_MN_NORMAL: - Log_FileWrite(sourceProcessId, sourceThreadId, fileName, fileOffset, writeLength, FALSE); + Log_FileWrite(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, fileOffset, writeLength, FALSE); break; case IRP_MN_COMPRESSED: - Log_FileWrite(sourceProcessId, sourceThreadId, fileName, fileOffset, writeLength, TRUE); + Log_FileWrite(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, fileOffset, writeLength, TRUE); break; } + + FltReleaseFileNameInformation(fileNameInfo); } void FileReadStatus(PFLT_CALLBACK_DATA Data) { - PWCH fileName = GetFileInfo(Data); + PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; + NTSTATUS status = FltGetFileNameInformation(Data, + FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_FILESYSTEM_ONLY | FLT_FILE_NAME_DO_NOT_CACHE, + &fileNameInfo); + if (!NT_SUCCESS(status)) { + return; + } HANDLE sourceProcessId = PsGetCurrentProcessId(); HANDLE sourceThreadId = PsGetThreadId(Data->Thread); @@ -79,39 +198,112 @@ void FileReadStatus(PFLT_CALLBACK_DATA Data) { switch (Data->Iopb->MinorFunction) { case IRP_MN_NORMAL: - Log_FileRead(sourceProcessId, sourceThreadId, fileName, fileOffset, readLength, FALSE); + Log_FileRead(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, fileOffset, readLength, FALSE); break; case IRP_MN_COMPRESSED: - Log_FileRead(sourceProcessId, sourceThreadId, fileName, fileOffset, readLength, TRUE); + Log_FileRead(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, fileOffset, readLength, TRUE); break; } + + FltReleaseFileNameInformation(fileNameInfo); +} + +BOOLEAN FilterNoise(UNICODE_STRING filePath, HANDLE SourceProcess) { + PEPROCESS targetProcess = NULL; + PUNICODE_STRING processPath = NULL; + BOOLEAN result = FALSE; + + NTSTATUS status = PsLookupProcessByProcessId(SourceProcess, &targetProcess); + if (!NT_SUCCESS(status)) { + goto FileCheck; + } + + status = SeLocateProcessImageName(targetProcess, &processPath); + if (!NT_SUCCESS(status)) { + goto Cleanup; + } + + UNICODE_STRING proc1; + RtlInitUnicodeString(&proc1, L"VMware"); + if (RtlCompareUnicodeString(&proc1, processPath, TRUE) == 0) { + result = TRUE; + goto Cleanup; + } + +Cleanup: + if (processPath) { + ExFreePool(processPath); + } + if (targetProcess) { + ObDereferenceObject(targetProcess); + } + +FileCheck: + + //"\Device\HarddiskVolume3\Program Files\VMware\VMware Tools\plugins\vmusr\vmtray.dll" + UNICODE_STRING ignore1; + RtlInitUnicodeString(&ignore1, L"\\ProgramData\\VMware\\"); + UNICODE_STRING ignore2; + RtlInitUnicodeString(&ignore2, L"\\Device\\HarddiskVolume1\\"); + UNICODE_STRING ignore3; + RtlInitUnicodeString(&ignore3, L"\\Device\\HarddiskVolume3\\"); + UNICODE_STRING ignore4; + RtlInitUnicodeString(&ignore4, L"\\pagefile.sys"); + UNICODE_STRING ignore5; + RtlInitUnicodeString(&ignore5, L"\\Device\\HarddiskVolume3\\Windows\\System32\\"); + UNICODE_STRING ignore6; + RtlInitUnicodeString(&ignore6, L"\\Windows\\System32\\"); + + if (RtlPrefixUnicodeString(&ignore1, &filePath, TRUE) || + RtlEqualUnicodeString(&ignore2, &filePath, TRUE) || + RtlEqualUnicodeString(&ignore3, &filePath, TRUE) || + RtlEqualUnicodeString(&ignore4, &filePath, TRUE) || + RtlPrefixUnicodeString(&ignore5, &filePath, TRUE) || + RtlPrefixUnicodeString(&ignore6, &filePath, TRUE) + ) + { + return true; + } + + return false; } void FileCreationStatus(PFLT_CALLBACK_DATA Data) { - PWCH fileName = GetFileInfo(Data); + PFLT_FILE_NAME_INFORMATION fileNameInfo = NULL; + NTSTATUS status = FltGetFileNameInformation(Data, + FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_FILESYSTEM_ONLY | FLT_FILE_NAME_DO_NOT_CACHE, + &fileNameInfo); + if (!NT_SUCCESS(status)) { + return; + } HANDLE sourceProcessId = PsGetCurrentProcessId(); HANDLE sourceThreadId = PsGetThreadId(Data->Thread); - //ULONG createOptions = Data->Iopb->Parameters.Create.Options & 0x00FFFFFF; - //ULONG disposition = (Data->Iopb->Parameters.Create.Options >> 24) & 0xFF; - //LONG status = Data->IoStatus.Status; + + if (FilterNoise(fileNameInfo->Name, sourceProcessId)) { + FltReleaseFileNameInformation(fileNameInfo); + return; + } BOOLEAN completeIfOplocked = (Data->Iopb->Parameters.Create.Options & FILE_COMPLETE_IF_OPLOCKED) != 0;; + switch (Data->IoStatus.Information) { case FILE_CREATED: - Log_FileCreated(sourceProcessId, sourceThreadId, fileName, completeIfOplocked); + Log_FileCreated(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, completeIfOplocked); break; case FILE_OPENED: - Log_FileOpen(sourceProcessId, sourceThreadId, fileName, completeIfOplocked); + Log_FileOpen(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, completeIfOplocked); break; case FILE_OVERWRITTEN: - Log_FileOverwritten(sourceProcessId, sourceThreadId, fileName); + Log_FileOverwritten(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); break; case FILE_SUPERSEDED: - Log_FileSuperseded(sourceProcessId, sourceThreadId, fileName); + Log_FileSuperseded(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); break; } + + FltReleaseFileNameInformation(fileNameInfo); } FLT_POSTOP_CALLBACK_STATUS PostOperationCallback(PFLT_CALLBACK_DATA Data,PCFLT_RELATED_OBJECTS FltObjects,PVOID CompletionContext,FLT_POST_OPERATION_FLAGS Flags) { @@ -123,131 +315,26 @@ FLT_POSTOP_CALLBACK_STATUS PostOperationCallback(PFLT_CALLBACK_DATA Data,PCFLT_R { //https://learn.microsoft.com/en-us/previous-versions/windows/drivers/ifs/irp-mj-read case IRP_MJ_READ: - DbgPrint("IRP_MJ_READ\n"); FileReadStatus(Data); break; //https://learn.microsoft.com/en-us/previous-versions/windows/drivers/ifs/irp-mj-create case IRP_MJ_CREATE: - DbgPrint("IRP_MJ_CREATE\n"); FileCreationStatus(Data); break; //https://learn.microsoft.com/en-us/previous-versions/windows/drivers/ifs/irp-mj-write case IRP_MJ_WRITE: - DbgPrint("IRP_MJ_WRITE\n"); FileWriteStatus(Data); break; //https://learn.microsoft.com/en-us/previous-versions/windows/drivers/ifs/irp-mj-create-named-pipe case IRP_MJ_CREATE_NAMED_PIPE: - DbgPrint("IRP_MJ_CREATE_NAMED_PIPE\n"); NamedPipeStatus(Data); break; //https://learn.microsoft.com/en-us/previous-versions/windows/drivers/ifs/irp-mj-create-mailslot case IRP_MJ_CREATE_MAILSLOT: - DbgPrint("IRP_MJ_CREATE_MAILSLOT\n"); MailSlotStatus(Data); break; } return FLT_POSTOP_FINISHED_PROCESSING; } -NTSTATUS PanoptesFilterUnload(_In_ FLT_FILTER_UNLOAD_FLAGS Flags) { - PAGED_CODE(); - NTSTATUS status; - if (Flags == FLTFL_FILTER_UNLOAD_MANDATORY) { - FltUnregisterFilter(g_FilterHandle); - status = STATUS_SUCCESS; - } - else { - status = STATUS_FLT_DO_NOT_DETACH; - } - return status; -} - -#pragma region FilterRegistration - -const FLT_OPERATION_REGISTRATION Callbacks[] = { - - { IRP_MJ_CREATE, - 0, - NULL, - PostOperationCallback - }, - { - IRP_MJ_READ, - 0, - NULL, - PostOperationCallback - }, - { IRP_MJ_WRITE, - 0, - NULL, - PostOperationCallback - }, - { IRP_MJ_CREATE_NAMED_PIPE, - 0, - NULL, - PostOperationCallback - }, - { - IRP_MJ_CREATE_MAILSLOT, - 0, - NULL, - PostOperationCallback - }, - { IRP_MJ_OPERATION_END} -}; - -const FLT_REGISTRATION FilterRegistration = { - sizeof(FLT_REGISTRATION), // Size - FLT_REGISTRATION_VERSION, // Version - 0, // Flags - NULL, // Context Registration. - Callbacks, // Operation callbacks - PanoptesFilterUnload, // FilterUnload - NULL, // InstanceSetup - NULL, // InstanceQueryTeardown - NULL, // InstanceTeardownStart - NULL, // InstanceTeardownComplete - NULL // GenerateFileName -}; -#pragma endregion - -NTSTATUS FilterInit(PDRIVER_OBJECT* DriverObject) { - NTSTATUS status = FltRegisterFilter( - *DriverObject, //Driver - &FilterRegistration, //Registration - &g_FilterHandle); //RetFilter - if (!NT_SUCCESS(status)) { - DbgPrint("Failed FltRegisterFilter\n"); - switch (status) - { - case STATUS_INSUFFICIENT_RESOURCES: - DbgPrint("STATUS_INSUFFICIENT_RESOURCES\n"); - break; - case STATUS_INVALID_PARAMETER: - DbgPrint("STATUS_INVALID_PARAMETER\n"); - break; - case STATUS_FLT_NOT_INITIALIZED: - DbgPrint("STATUS_FLT_NOT_INITIALIZED\n"); - break; - case STATUS_OBJECT_NAME_NOT_FOUND: - DbgPrint("STATUS_OBJECT_NAME_NOT_FOUND\n"); - break; - default: - DbgPrint("UNKNOWN\n"); - break; - } - return status; - } - - status = FltStartFiltering(g_FilterHandle); - if (!NT_SUCCESS(status)) { - DbgPrint("Failed FltStartFiltering\n"); - FltUnregisterFilter(g_FilterHandle); - g_FilterHandle = nullptr; - return status; - } - - return status; -} diff --git a/src/driver/src/inject.cpp b/src/driver/src/inject.cpp index 8e841b2..aa36c8d 100644 --- a/src/driver/src/inject.cpp +++ b/src/driver/src/inject.cpp @@ -13,10 +13,15 @@ void NTAPI KernelRundown(PKAPC apc, PKNORMAL_ROUTINE* NormalRoutine, PVOID* Norm VOID KernelAPCRoutine(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2) { - UNREFERENCED_PARAMETER(SystemArgument2); + PUNICODE_STRING dllToInject = reinterpret_cast(SystemArgument2); + + if (dllToInject == nullptr) { + return; + } if (NormalContext == nullptr) { - KdPrint(("InjectDll - processId is null")); + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); return; } @@ -25,6 +30,8 @@ VOID KernelAPCRoutine(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemAr PEPROCESS targetProcess{}; NTSTATUS status = PsLookupProcessByProcessId(NormalContext, &targetProcess); if (!NT_SUCCESS(status)) { + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); return; } @@ -42,37 +49,30 @@ VOID KernelAPCRoutine(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemAr //} #endif - ANSI_STRING loadDllRoutineName = RTL_CONSTANT_STRING("LoadLibraryExW"); PVOID rawImageBaseAddress = *static_cast(SystemArgument1); - PVOID functionAddress = RtlxFindExportedRoutineByName(rawImageBaseAddress, &loadDllRoutineName); + PVOID functionAddress = RtlFindExportedRoutineByName(rawImageBaseAddress, "LoadLibraryExW"); if (functionAddress == nullptr) { - KdPrint((PANOPTES_PREFIX_ERROR "Unable to find LoadLibraryExW in target process (%u)\n", processId)); + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); return; } - UNICODE_STRING dllToInject; - UNICODE_STRING dllFullPathx64; - UNICODE_STRING dllFullPathx86; - RtlInitUnicodeString(&dllFullPathx64, L"C:\\Program Files\\Panoptes\\PanoptesDLLx64.dll"); - RtlInitUnicodeString(&dllFullPathx86, L"C:\\Program Files\\Panoptes\\PanoptesDLLx86.dll"); - - if (Is64BitProcess(targetProcess)) - dllToInject = dllFullPathx64; - else - dllToInject = dllFullPathx86; - PVOID allocatedAddressContainingDllFullPath = nullptr; - status = ZwAllocateVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, 0, (PSIZE_T)&dllToInject.Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + status = ZwAllocateVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, 0, (PSIZE_T)&dllToInject->Length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!NT_SUCCESS(status)) { KdPrint((PANOPTES_PREFIX_ERROR "Unable to allocate memory for the absolute DLL path in the target process (%u)\n", processId)); + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); return; } - RtlCopyMemory(allocatedAddressContainingDllFullPath, dllToInject.Buffer, dllToInject.Length); + RtlCopyMemory(allocatedAddressContainingDllFullPath, dllToInject->Buffer, dllToInject->Length); PKAPC pKapc = (PKAPC)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KAPC), DRIVER_TAG); if (!pKapc) { KdPrint((PANOPTES_PREFIX_ERROR "Unable to allocate the KAPC object (%u)\n", processId)); - ZwFreeVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, (PSIZE_T)&dllToInject.Length, MEM_RELEASE); // Free the allocated memory + ZwFreeVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, (PSIZE_T)&dllToInject->Length, MEM_RELEASE); // Free the allocated memory + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); return; } @@ -80,33 +80,71 @@ VOID KernelAPCRoutine(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemAr if (!KeInsertQueueApc(pKapc, NULL, NULL, IO_NO_INCREMENT)) { KdPrint((PANOPTES_PREFIX_ERROR "Unable to insert the KAPC object into target process(%u)\n", processId)); - ZwFreeVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, (PSIZE_T)&dllToInject.Length, MEM_RELEASE); // Free the allocated memory + ZwFreeVirtualMemory(NtCurrentProcess(), &allocatedAddressContainingDllFullPath, (PSIZE_T)&dllToInject->Length, MEM_RELEASE); // Free the allocated memory ExFreePool(pKapc); // Free the APC object + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); return; } + KdPrint((PANOPTES_PREFIX_SUCCESS "Injecting into %u - %wZ \n", NormalContext)); + + // Free the allocated DLL path memory - no longer needed after successful APC queue + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); + KeTestAlertThread(UserMode); } -NTSTATUS InstallKernelModeApcToInjectDll(HANDLE ProcessId, PVOID ImageBase) +NTSTATUS InstallKernelModeApcToInjectDll(HANDLE ProcessId, PVOID ImageBase, BOOLEAN is64Bit) { PRKAPC pKapc = nullptr; + PCWSTR dllPath = nullptr; + SIZE_T dllPathLength = 0; + + // Select the appropriate DLL path + dllPath = is64Bit + ? L"C:\\Program Files\\Panoptes\\PanoptesDLLx64.dll" + : L"C:\\Program Files\\Panoptes\\PanoptesDLLx86.dll"; + dllPathLength = (wcslen(dllPath) + 1) * sizeof(WCHAR); + + // Allocate memory for the UNICODE_STRING structure + PUNICODE_STRING pDllToInject = (PUNICODE_STRING)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(UNICODE_STRING), DRIVER_TAG); + if (nullptr == pDllToInject) { + KdPrint((PANOPTES_PREFIX_ERROR "InstallKernelModeApcToInjectDll Failed to allocate memory for UNICODE_STRING\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // Allocate memory for the DLL path buffer + PWCH pDllPathBuffer = (PWCH)ExAllocatePool2(POOL_FLAG_NON_PAGED, dllPathLength, DRIVER_TAG); + if (nullptr == pDllPathBuffer) { + KdPrint((PANOPTES_PREFIX_ERROR "InstallKernelModeApcToInjectDll Failed to allocate memory for DLL path buffer\n")); + ExFreePool(pDllToInject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // Copy the DLL path and initialize the UNICODE_STRING + RtlCopyMemory(pDllPathBuffer, dllPath, dllPathLength); + pDllToInject->Buffer = pDllPathBuffer; + pDllToInject->Length = (USHORT)(dllPathLength - sizeof(WCHAR)); // Exclude null terminator + pDllToInject->MaximumLength = (USHORT)dllPathLength; pKapc = (PKAPC)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(KAPC), DRIVER_TAG); // Allocate the APC object if (nullptr == pKapc) { - KdPrint((PANOPTES_PREFIX_ERROR "InstallKernelModeApcToInjectDll Failed to allocate memory for the APC")); + KdPrint((PANOPTES_PREFIX_ERROR "InstallKernelModeApcToInjectDll Failed to allocate memory for the APC\n")); + ExFreePool(pDllPathBuffer); + ExFreePool(pDllToInject); return STATUS_INSUFFICIENT_RESOURCES; } KeInitializeApc(pKapc, KeGetCurrentThread(),OriginalApcEnvironment,KernelRundown, NULL,(PKNORMAL_ROUTINE)KernelAPCRoutine,KernelMode, (PVOID)ProcessId); - if (!KeInsertQueueApc(pKapc, ImageBase, NULL, IO_NO_INCREMENT)) { - KdPrint((PANOPTES_PREFIX_ERROR "InstallKernelModeApcToInjectDll Failed to insert APC")); + if (!KeInsertQueueApc(pKapc, ImageBase, pDllToInject, IO_NO_INCREMENT)) { + KdPrint((PANOPTES_PREFIX_ERROR "InstallKernelModeApcToInjectDll Failed to insert APC\n")); ExFreePool(pKapc); // Free the APC object + ExFreePool(pDllPathBuffer); + ExFreePool(pDllToInject); return STATUS_UNSUCCESSFUL; } - else { - KdPrint((PANOPTES_PREFIX_SUCCESS "InstallKernelModeApcToInjectDll APC delivered")); - } return STATUS_SUCCESS; } \ No newline at end of file diff --git a/src/driver/src/state.cpp b/src/driver/src/state.cpp index a0ab97d..ce814e5 100644 --- a/src/driver/src/state.cpp +++ b/src/driver/src/state.cpp @@ -4,7 +4,6 @@ NTSTATUS PanoptesState::Init() { ExInitializeFastMutex(&ProcessesLock); RtlInitializeGenericTableAvl(&Processes, ProcessCompare, TableAlloc, TableFree, this); - ImageBase = ExAllocatePool2(POOL_FLAG_PAGED, sizeof(PVOID), DRIVER_TAG); return STATUS_SUCCESS; } @@ -22,20 +21,20 @@ RTL_GENERIC_COMPARE_RESULTS PanoptesState::ProcessCompare(PRTL_AVL_TABLE Table, _Use_decl_annotations_ PVOID PanoptesState::TableAlloc(_RTL_AVL_TABLE* Table, CLONG ByteSize) { UNREFERENCED_PARAMETER(Table); - return ExAllocatePool2(POOL_FLAG_PAGED, ByteSize, DRIVER_TAG); + return ExAllocatePool2(POOL_FLAG_PAGED, ByteSize, 'stky'); } _Use_decl_annotations_ VOID PanoptesState::TableFree(_RTL_AVL_TABLE* Table, PVOID Buffer) { UNREFERENCED_PARAMETER(Table); - ExFreePool(Buffer); + ExFreePoolWithTag(Buffer, 'stky'); } void PanoptesState::Term() { + // Delete all elements by repeatedly deleting the first element until table is empty + // This is safer than enumerating and deleting, as deletion may invalidate enumeration state PVOID element; while ((element = RtlEnumerateGenericTableAvl(&Processes, TRUE)) != nullptr) { RtlDeleteElementGenericTableAvl(&Processes, element); } - - ExFreePool(ImageBase, DRIVER_TAG); } \ No newline at end of file diff --git a/src/driver/src/trace.cpp b/src/driver/src/trace.cpp index efaf3f4..ddee958 100644 --- a/src/driver/src/trace.cpp +++ b/src/driver/src/trace.cpp @@ -7,14 +7,15 @@ PDRIVER_OBJECT g_DriverObject; TRACELOGGING_DEFINE_PROVIDER(g_hPanoProvider, "Panoptes", (0x7036af95, 0x9daf, 0x4486, 0x8d, 0x93, 0x70, 0x5, 0xd4, 0x5a, 0x6a, 0x6)); -void TraceInitialize(BOOLEAN initialize) +void TraceInitialize() { - if (!initialize) { - TraceLoggingUnregister(g_hPanoProvider); - } - TraceLoggingRegister(g_hPanoProvider); } + +void TraceTerminate() +{ + TraceLoggingUnregister(g_hPanoProvider); +} #pragma endregion #pragma region Driver Operations diff --git a/src/driver/src/utils.cpp b/src/driver/src/utils.cpp index c801047..8e54075 100644 --- a/src/driver/src/utils.cpp +++ b/src/driver/src/utils.cpp @@ -1,15 +1,5 @@ #include "utils.h" -BOOLEAN Is64BitProcess(PEPROCESS targetProcess) { - UINT64* processAsUint64 = reinterpret_cast(targetProcess); - PVOID* wow64ProcessPtr = reinterpret_cast(processAsUint64 + 0x580 / sizeof(UINT64)); - if (*wow64ProcessPtr == NULL) - { - return TRUE; - } - return FALSE; -} - NTSTATUS GetFileNameFromPath(PUNICODE_STRING FullPath, PUNICODE_STRING FileName) { USHORT i; USHORT lengthInChars; @@ -35,172 +25,29 @@ NTSTATUS GetFileNameFromPath(PUNICODE_STRING FullPath, PUNICODE_STRING FileName) return STATUS_SUCCESS; } -NTSTATUS QueryProcessMitigationPolicy(HANDLE ProcessId, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo) { - UNREFERENCED_PARAMETER(policyInfo); +NTSTATUS QueryProcessMitigationPolicy(PEPROCESS Process, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo) { HANDLE hProcess; - PEPROCESS eProcess; - if (ProcessId == NULL) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Invalid ProcessId\n"); - return STATUS_INVALID_PARAMETER; //0xC000000D - } - - NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &eProcess); - if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: PsLookupProcessByProcessId failed with status 0x%X\n", status); - return status; - } - - status = ObOpenObjectByPointer( - eProcess, + NTSTATUS status = ObOpenObjectByPointer( + Process, OBJ_KERNEL_HANDLE, NULL, 0x1000,//PROCESS_QUERY_LIMITED_INFORMATION, *PsProcessType, KernelMode, &hProcess); - - ObDereferenceObject(eProcess); - if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: ObOpenObjectByPointer failed with status 0x%X\n", status); return status; } - PROCESS_MITIGATION_POLICY_INFORMATION policyInfoLocal; - policyInfoLocal.Policy = ProcessSignaturePolicy; - status = ZwQueryInformationProcess(hProcess, ProcessMitigationPolicy, &policyInfoLocal, sizeof(policyInfoLocal), nullptr); - if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: ZwQueryInformationProcess failed with status 0x%X\n", status); - } - - if (&policyInfoLocal != NULL) { - if (policyInfoLocal.Data.SignaturePolicy.MicrosoftSignedOnly != 0) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: Process with MicrosoftOnly"); - } - } - + status = ZwQueryInformationProcess( + hProcess, + ProcessMitigationPolicy, + policyInfo, + sizeof(PROCESS_MITIGATION_POLICY_INFORMATION), + nullptr); ZwClose(hProcess); - return STATUS_SUCCESS; + return status; } -PVOID NTAPI RtlxFindExportedRoutineByName(_In_ PVOID DllBase, _In_ PANSI_STRING ExportName) { - // - // RtlFindExportedRoutineByName is not exported by ntoskrnl until Win10. - // Following code is borrowed from ReactOS. - // - - PULONG NameTable; - PUSHORT OrdinalTable; - PIMAGE_EXPORT_DIRECTORY ExportDirectory; - LONG Low = 0, Mid = 0, High, Ret; - USHORT Ordinal; - PVOID Function; - ULONG ExportSize; - PULONG ExportTable; - - // - // Get the export directory. - // - - ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(DllBase, - TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, - &ExportSize); - - if (!ExportDirectory) - { - return NULL; - } - - // - // Setup name tables. - // - - NameTable = (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfNames); - OrdinalTable = (PUSHORT)((ULONG_PTR)DllBase + ExportDirectory->AddressOfNameOrdinals); - - // - // Do a binary search. - // - - High = ExportDirectory->NumberOfNames - 1; - while (High >= Low) - { - // - // Get new middle value. - // - - Mid = (Low + High) >> 1; - - // - // Compare name. - // - - Ret = strcmp(ExportName->Buffer, (PCHAR)DllBase + NameTable[Mid]); - if (Ret < 0) - { - // - // Update high. - // - High = Mid - 1; - } - else if (Ret > 0) - { - // - // Update low. - // - Low = Mid + 1; - } - else - { - // - // We got it. - // - break; - } - } - - // - // Check if we couldn't find it. - // - - if (High < Low) - { - return NULL; - } - - // - // Otherwise, this is the ordinal. - // - - Ordinal = OrdinalTable[Mid]; - - // - // Validate the ordinal. - // - - if (Ordinal >= ExportDirectory->NumberOfFunctions) - { - return NULL; - } - - // - // Resolve the address and write it. - // - - ExportTable = (PULONG)((ULONG_PTR)DllBase + ExportDirectory->AddressOfFunctions); - Function = (PVOID)((ULONG_PTR)DllBase + ExportTable[Ordinal]); - - // - // We found it! - // - - NT_ASSERT( - (Function < (PVOID)ExportDirectory) || - (Function > (PVOID)((ULONG_PTR)ExportDirectory + ExportSize)) - ); - - return Function; -} From 9f122b4ba2444d31e6bc0dde088ef3d084586f0d Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 20:24:25 -0700 Subject: [PATCH 05/16] cleaned up all the cmakes to easily handle presets --- CMakeLists.txt | 16 +-- CMakePresets.json | 3 + README.md | 113 ++++++++++++++++-- src/container/CMakeLists.txt | 79 +++++++----- src/dll/CMakeLists.txt | 4 +- src/driver/CMakeLists.txt | 12 +- src/extensibility/PanoptesAMSI/CMakeLists.txt | 91 ++++++++------ .../PanoptesAMSI/test/CMakeLists.txt | 95 ++++++++++----- src/extensibility/PanoptesPE/CMakeLists.txt | 89 ++++++++------ .../PanoptesPE/test/CMakeLists.txt | 21 ++-- src/extensibility/PanoptesYara/CMakeLists.txt | 89 ++++++++------ .../PanoptesYara/test/CMakeLists.txt | 33 +++-- src/libraries/ResourceCore/CMakeLists.txt | 9 +- .../TrayNotificationsCore/CMakeLists.txt | 6 +- src/linter/CMakeLists.txt | 6 +- src/scanner/PanoptesScan/CMakeLists.txt | 77 ++++++++---- src/scanner/PanoptesScanCLI/CMakeLists.txt | 77 +++++++----- src/service/CMakeLists.txt | 85 ++++++++----- src/testing/KernelTestHost/CMakeLists.txt | 12 +- 19 files changed, 610 insertions(+), 307 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9733b42..2ad1c68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,14 +28,14 @@ elseif(DOXYGEN_FOUND AND NOT BUILD_DOC) endif(DOXYGEN_FOUND AND BUILD_DOC) -add_subdirectory(src/service) -add_subdirectory(src/libraries) - -add_subdirectory(src/extensibility) -add_subdirectory(src/container) -add_subdirectory(src/dll) -add_subdirectory(src/linter) -add_subdirectory(src/scanner) +#add_subdirectory(src/service) +#add_subdirectory(src/libraries) + +#add_subdirectory(src/extensibility) +#add_subdirectory(src/container) +#add_subdirectory(src/dll) +#add_subdirectory(src/linter) +#add_subdirectory(src/scanner) add_subdirectory(src/testing) if(BUILD_DRIVER) diff --git a/CMakePresets.json b/CMakePresets.json index 9342094..34087af 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -16,6 +16,7 @@ "gRPC_DIR": "vcpkg_installed/x64-windows-static/share/grpc", "nlohmann_json_DIR": "vcpkg_installed/x64-windows-static/share/nlohmann_json", "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDebug", + "PRESET_NAME": "Debug", "x86_BUILD_TOOLS_PATH": "C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x86/", "x64_BUILD_TOOLS_PATH": "C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x64" } @@ -34,6 +35,8 @@ "Protobuf_PROTOC_EXECUTABLE": "vcpkg_installed/x64-windows-static/tools/protobuf/protoc.exe", "gRPC_DIR": "vcpkg_installed/x64-windows-static/share/grpc", "nlohmann_json_DIR": "vcpkg_installed/x64-windows-static/share/nlohmann_json", + "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded", + "PRESET_NAME": "Release", "x86_BUILD_TOOLS_PATH": "C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x86/", "x64_BUILD_TOOLS_PATH": "C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x64" } diff --git a/README.md b/README.md index 9e36655..dbab62c 100644 --- a/README.md +++ b/README.md @@ -145,22 +145,119 @@ For kernel development environment setup, see: - [Ap3x/Windows-Kernel-Development-Infrastructure](https://github.com/Ap3x/Windows-Kernel-Development-Infrastructure) - [Microsoft WDK Installation Guide](https://learn.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) -### CMake Build Options +### Building Panoptes + +#### Prerequisites + +Ensure you have the following installed: +- Visual Studio 2022 with C++ workload +- Windows Driver Kit (WDK) +- Vcpkg (with `VCPKG_ROOT` environment variable set) +- CMake 3.15 or higher + +#### CMake Build Options The following CMake options are available during configuration: - `BUILD_DOC` (OFF by default): Build Doxygen documentation - `BUILD_WIX_INSTALLER` (OFF by default): Build the Wix MSI installer package - `BUILD_DRIVER` (OFF by default): Build the kernel driver package -- `BUILD_GRPC` (OFF by default): Generate gRPC code from protobuf definitions +- `BUILD_GRPC` (ON by default): Generate gRPC code from protobuf definitions + +#### Building with CMake Presets (Recommended) + +##### Debug Build + +```powershell +# Configure for Debug +cmake --preset debug -DBUILD_GRPC=ON + +# Build using CMake +cmake --build build/debug --config Debug + +# Or build using MSBuild directly +msbuild build/debug/Panoptes.sln /p:Configuration=Debug /p:Platform=x64 /m +``` + +Output: `./bin/Debug/` + +##### Release Build + +```powershell +# Configure for Release +cmake --preset release -DBUILD_GRPC=ON + +# Build using CMake +cmake --build build/release --config Release + +# Or build using MSBuild directly +msbuild build/release/Panoptes.sln /p:Configuration=Release /p:Platform=x64 /m +``` + +Output: `./bin/Release/` + +#### Building Specific Projects + +To build only the main service: + +**Debug:** +```powershell +msbuild build/debug/src/service/PanoptesService.vcxproj /p:Configuration=Debug /p:Platform=x64 +``` + +**Release:** +```powershell +msbuild build/release/src/service/PanoptesService.vcxproj /p:Configuration=Release /p:Platform=x64 +``` + +#### Building with Additional Options + +Enable all optional components: + +```powershell +# Debug with all options +cmake --preset debug -DBUILD_GRPC=ON -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=ON -DBUILD_DOC=ON +cmake --build build/debug --config Debug + +# Release with all options +cmake --preset release -DBUILD_GRPC=ON -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=ON -DBUILD_DOC=ON +cmake --build build/release --config Release +``` + +#### Clean Build + +```powershell +# Remove previous build artifacts +Remove-Item -Recurse -Force build/debug +Remove-Item -Recurse -Force build/release + +# Then configure and build as usual +cmake --preset debug -DBUILD_GRPC=ON +cmake --build build/debug --config Debug +``` + +#### Build Outputs + +| Configuration | Location | Executable | PDB | +|---|---|---|---| +| Debug | `./bin/Debug/` | PanoptesService.exe (71 MB) | PanoptesService.pdb | +| Release | `./bin/Release/` | PanoptesService.exe | (embedded or separate) | + +#### MSBuild Command Reference + +Common MSBuild parameters: + +- `/p:Configuration=` - Build configuration (Debug, Release) +- `/p:Platform=x64` - Platform architecture (x64, Win32) +- `/m` - Build in parallel using all available cores +- `/v:n` - Verbosity (q=quiet, m=minimal, n=normal, d=detailed) +- `/t:Rebuild` - Clean and rebuild (instead of incremental) +- `/t:Clean` - Clean build artifacts only + +Example with verbose output and parallel build: -Example CMake configuration: ```powershell -mkdir build -cd build -cmake --preset debug -DBUILD_DOC=ON -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=ON .. -cd debug -msbuild /p:Configuration=Debug Panoptes.sln +msbuild build/debug/Panoptes.sln /p:Configuration=Debug /p:Platform=x64 /m /v:normal ``` ## Screenshots of Panoptes Features diff --git a/src/container/CMakeLists.txt b/src/container/CMakeLists.txt index c0ff8dd..bb7a65b 100644 --- a/src/container/CMakeLists.txt +++ b/src/container/CMakeLists.txt @@ -28,45 +28,66 @@ set(HEADERS add_executable(${PROJECT_NAME} WIN32 ${SOURCES} ${HEADERS}) if(BUILD_GRPC) + find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) # Set proto file path - set(PROTO_FILE_DIR "${CMAKE_SOURCE_DIR}/proto/src/") - set(PROTO_BUILD_DIR "${CMAKE_SOURCE_DIR}/proto/build") + set(PROTO_SRC "${CMAKE_SOURCE_DIR}/proto/src") + set(PROTO_FILE "${PROTO_SRC}/panoptes.proto") + set(PROTO_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") - # Create build directory if it doesn't exist - file(MAKE_DIRECTORY ${PROTO_BUILD_DIR}) + # Generated file paths + set(PROTO_PB_CC "${PROTO_OUT_DIR}/panoptes.pb.cc") + set(PROTO_PB_H "${PROTO_OUT_DIR}/panoptes.pb.h") + set(PROTO_GRPC_CC "${PROTO_OUT_DIR}/panoptes.grpc.pb.cc") + set(PROTO_GRPC_H "${PROTO_OUT_DIR}/panoptes.grpc.pb.h") + + # Find protoc executable + find_program(PROTOC_EXECUTABLE protoc REQUIRED) message(" --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}") message(" --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}") message(" --> PROTOBUF VERSION: ${Protobuf_VERSION}") message(" --> PROTOBUF Found: ${Protobuf_FOUND}") - message(" --> PROTOBUF SRC: ${PROTO_SRC}") - message(" --> PROTOBUF HEADER: ${PROTO_HEADER}") - message(" --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto") - - #target_link_libraries(${PROJECT_NAME} PUBLIC protobuf::libprotobuf gRPC::grpc++) - - set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") - - target_include_directories(${PROJECT_NAME} PUBLIC "$") - - protobuf_generate( - TARGET ${PROJECT_NAME} - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + message(" --> PROTO_FILE: ${PROTO_FILE}") + message(" --> Protobuf Compiler: ${PROTOC_EXECUTABLE}") + + # Create custom command for protobuf generation + add_custom_command( + OUTPUT ${PROTO_PB_CC} ${PROTO_PB_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --cpp_out=${PROTO_OUT_DIR} + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} + COMMENT "Running protobuf compiler on ${PROTO_FILE}" + VERBATIM + ) + + # Create custom command for gRPC generation + add_custom_command( + OUTPUT ${PROTO_GRPC_CC} ${PROTO_GRPC_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --grpc_out=${PROTO_OUT_DIR} + --plugin=protoc-gen-grpc=$ + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} ${PROTO_PB_CC} gRPC::grpc_cpp_plugin + COMMENT "Running gRPC compiler on ${PROTO_FILE}" + VERBATIM ) - - protobuf_generate( - TARGET ${PROJECT_NAME} - LANGUAGE grpc - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc - PLUGIN "protoc-gen-grpc=\$" - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + + # Add generated files as source to the target + target_sources(${PROJECT_NAME} PRIVATE + ${PROTO_PB_CC} + ${PROTO_GRPC_CC} ) + + # Add include directory for generated files + target_include_directories(${PROJECT_NAME} PUBLIC "$") + + # Link protobuf and gRPC libraries + target_link_libraries(${PROJECT_NAME} PRIVATE protobuf::libprotobuf) endif() # Include directories @@ -91,7 +112,7 @@ endif() # Set output directories to match Visual Studio structure set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) # Set static runtime for MSVC diff --git a/src/dll/CMakeLists.txt b/src/dll/CMakeLists.txt index 80ff973..13485ec 100644 --- a/src/dll/CMakeLists.txt +++ b/src/dll/CMakeLists.txt @@ -44,9 +44,9 @@ function(configure_target TARGET_NAME ARCH) ) # Set output names and directories - set_target_properties(${TARGET_NAME} PROPERTIES + set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}${OUTPUT_SUFFIX}" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}") + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$") # Include directories target_include_directories(${TARGET_NAME} PRIVATE diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index f93a353..e1f0e43 100644 --- a/src/driver/CMakeLists.txt +++ b/src/driver/CMakeLists.txt @@ -54,7 +54,7 @@ set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "Panoptes") # Set output directory to match MSVC project structure set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}/driver" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$/driver" ) target_link_libraries(${PROJECT_NAME} WDK::FLTMGR) @@ -66,25 +66,25 @@ set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/ENTRY:DriverEntry add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/driver-files/Panoptes.inf - ${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}/driver/${CMAKE_BUILD_TYPE}/Panoptes.inf + "${CMAKE_SOURCE_DIR}/bin/$/driver/Panoptes.inf" COMMENT "Copying INF file to output directory" ) # Run Inf2Cat to create catalog file add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND "${x86_BUILD_TOOLS_PATH}Inf2Cat.exe" /driver:${CMAKE_SOURCE_DIR}/bin/driver/${CMAKE_BUILD_TYPE} /os:10_x64 /verbose - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/driver/${CMAKE_BUILD_TYPE}" + COMMAND "${x86_BUILD_TOOLS_PATH}Inf2Cat.exe" /driver:"${CMAKE_SOURCE_DIR}/bin/$/driver" /os:10_x64 /verbose + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$/driver" COMMENT "Running Inf2Cat to create catalog file" ) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND "${x64_BUILD_TOOLS_PATH}/makecert.exe" -r -pe -ss PanoptesCertStore -n "CN=Panoptes" "${CMAKE_SOURCE_DIR}/bin/driver/${CMAKE_BUILD_TYPE}/Panoptes.cer" + COMMAND "${x64_BUILD_TOOLS_PATH}/makecert.exe" -r -pe -ss PanoptesCertStore -n "CN=Panoptes" "${CMAKE_SOURCE_DIR}/bin/$/driver/Panoptes.cer" COMMENT "Generating a driver certificate" AUTO ) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND "${x64_BUILD_TOOLS_PATH}/signtool.exe" sign /a /v /fd sha256 /s PanoptesCertStore /n "Panoptes" /t http://timestamp.digicert.com "${CMAKE_SOURCE_DIR}/bin/driver/${CMAKE_BUILD_TYPE}/Panoptes.sys" + COMMAND "${x64_BUILD_TOOLS_PATH}/signtool.exe" sign /a /v /fd sha256 /s PanoptesCertStore /n "Panoptes" /t http://timestamp.digicert.com "${CMAKE_SOURCE_DIR}/bin/$/driver/Panoptes.sys" COMMENT "Signing the driver" ) diff --git a/src/extensibility/PanoptesAMSI/CMakeLists.txt b/src/extensibility/PanoptesAMSI/CMakeLists.txt index d36367f..c12bc30 100644 --- a/src/extensibility/PanoptesAMSI/CMakeLists.txt +++ b/src/extensibility/PanoptesAMSI/CMakeLists.txt @@ -30,45 +30,66 @@ file(GLOB HEADERS add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) if(BUILD_GRPC) + find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) # Set proto file path - set(PROTO_FILE_DIR "${CMAKE_SOURCE_DIR}/proto/src/") - set(PROTO_BUILD_DIR "${CMAKE_SOURCE_DIR}/proto/build") + set(PROTO_SRC "${CMAKE_SOURCE_DIR}/proto/src") + set(PROTO_FILE "${PROTO_SRC}/panoptes.proto") + set(PROTO_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") - # Create build directory if it doesn't exist - file(MAKE_DIRECTORY ${PROTO_BUILD_DIR}) + # Generated file paths + set(PROTO_PB_CC "${PROTO_OUT_DIR}/panoptes.pb.cc") + set(PROTO_PB_H "${PROTO_OUT_DIR}/panoptes.pb.h") + set(PROTO_GRPC_CC "${PROTO_OUT_DIR}/panoptes.grpc.pb.cc") + set(PROTO_GRPC_H "${PROTO_OUT_DIR}/panoptes.grpc.pb.h") + + # Find protoc executable + find_program(PROTOC_EXECUTABLE protoc REQUIRED) message(" --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}") message(" --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}") message(" --> PROTOBUF VERSION: ${Protobuf_VERSION}") message(" --> PROTOBUF Found: ${Protobuf_FOUND}") - message(" --> PROTOBUF SRC: ${PROTO_SRC}") - message(" --> PROTOBUF HEADER: ${PROTO_HEADER}") - message(" --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto") - - #target_link_libraries(${PROJECT_NAME} PUBLIC protobuf::libprotobuf gRPC::grpc++) - - set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") - - target_include_directories(${PROJECT_NAME} PUBLIC "$") + message(" --> PROTO_FILE: ${PROTO_FILE}") + message(" --> Protobuf Compiler: ${PROTOC_EXECUTABLE}") + + # Create custom command for protobuf generation + add_custom_command( + OUTPUT ${PROTO_PB_CC} ${PROTO_PB_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --cpp_out=${PROTO_OUT_DIR} + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} + COMMENT "Running protobuf compiler on ${PROTO_FILE}" + VERBATIM + ) - protobuf_generate( - TARGET ${PROJECT_NAME} - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + # Create custom command for gRPC generation + add_custom_command( + OUTPUT ${PROTO_GRPC_CC} ${PROTO_GRPC_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --grpc_out=${PROTO_OUT_DIR} + --plugin=protoc-gen-grpc=$ + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} ${PROTO_PB_CC} gRPC::grpc_cpp_plugin + COMMENT "Running gRPC compiler on ${PROTO_FILE}" + VERBATIM ) - - protobuf_generate( - TARGET ${PROJECT_NAME} - LANGUAGE grpc - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc - PLUGIN "protoc-gen-grpc=\$" - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + + # Add generated files as source to the target + target_sources(${PROJECT_NAME} PRIVATE + ${PROTO_PB_CC} + ${PROTO_GRPC_CC} ) + + # Add include directory for generated files + target_include_directories(${PROJECT_NAME} PUBLIC "$") + + # Link protobuf and gRPC libraries + target_link_libraries(${PROJECT_NAME} PRIVATE protobuf::libprotobuf) endif() # Add include directories @@ -83,9 +104,9 @@ target_link_libraries(${PROJECT_NAME} PRIVATE amsi Shlwapi Crypt32) # Set output directories set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) # Windows-specific configurations @@ -118,14 +139,14 @@ if(MSVC) ) endif() -# Add post-build command to copy DLL to ext directory for Debug configuration +# Add post-build command to copy DLL to ext directory add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/Debug/ext" + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/$/ext" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/ext/$" + "${CMAKE_SOURCE_DIR}/bin/$/ext/$" COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/ext/$" + "$" + "${CMAKE_SOURCE_DIR}/bin/$/ext/$" COMMENT "Copying ${PROJECT_NAME} DLL and PDB to ext directory" ) \ No newline at end of file diff --git a/src/extensibility/PanoptesAMSI/test/CMakeLists.txt b/src/extensibility/PanoptesAMSI/test/CMakeLists.txt index 87bd82a..0e365e3 100644 --- a/src/extensibility/PanoptesAMSI/test/CMakeLists.txt +++ b/src/extensibility/PanoptesAMSI/test/CMakeLists.txt @@ -4,6 +4,11 @@ project(Test_PanoptesAMSI) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +# Set static runtime for MSVC - MUST BE SET BEFORE ANY TARGETS +if(MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +endif() + find_package(gRPC CONFIG REQUIRED) include(FetchContent) @@ -11,8 +16,8 @@ FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Use static CRT to match the rest of the project +set(gtest_force_shared_crt OFF CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) enable_testing() @@ -34,43 +39,66 @@ set(HEADERS add_executable(Test_PanoptesAMSI ${SOURCES} ${HEADERS}) if(BUILD_GRPC) + find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) # Set proto file path - set(PROTO_FILE_DIR "${CMAKE_SOURCE_DIR}/proto/src/") - set(PROTO_BUILD_DIR "${CMAKE_SOURCE_DIR}/proto/build") + set(PROTO_SRC "${CMAKE_SOURCE_DIR}/proto/src") + set(PROTO_FILE "${PROTO_SRC}/panoptes.proto") + set(PROTO_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") + + # Generated file paths + set(PROTO_PB_CC "${PROTO_OUT_DIR}/panoptes.pb.cc") + set(PROTO_PB_H "${PROTO_OUT_DIR}/panoptes.pb.h") + set(PROTO_GRPC_CC "${PROTO_OUT_DIR}/panoptes.grpc.pb.cc") + set(PROTO_GRPC_H "${PROTO_OUT_DIR}/panoptes.grpc.pb.h") - # Create build directory if it doesn't exist - file(MAKE_DIRECTORY ${PROTO_BUILD_DIR}) + # Find protoc executable + find_program(PROTOC_EXECUTABLE protoc REQUIRED) message(" --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}") message(" --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}") message(" --> PROTOBUF VERSION: ${Protobuf_VERSION}") message(" --> PROTOBUF Found: ${Protobuf_FOUND}") - message(" --> PROTOBUF SRC: ${PROTO_SRC}") - message(" --> PROTOBUF HEADER: ${PROTO_HEADER}") - message(" --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto") - - target_link_libraries(${PROJECT_NAME} PUBLIC protobuf::libprotobuf gRPC::grpc++) - - set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") - - protobuf_generate( - TARGET ${PROJECT_NAME} - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + message(" --> PROTO_FILE: ${PROTO_FILE}") + message(" --> Protobuf Compiler: ${PROTOC_EXECUTABLE}") + + # Create custom command for protobuf generation + add_custom_command( + OUTPUT ${PROTO_PB_CC} ${PROTO_PB_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --cpp_out=${PROTO_OUT_DIR} + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} + COMMENT "Running protobuf compiler on ${PROTO_FILE}" + VERBATIM ) - - protobuf_generate( - TARGET ${PROJECT_NAME} - LANGUAGE grpc - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc - PLUGIN "protoc-gen-grpc=\$" - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + + # Create custom command for gRPC generation + add_custom_command( + OUTPUT ${PROTO_GRPC_CC} ${PROTO_GRPC_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --grpc_out=${PROTO_OUT_DIR} + --plugin=protoc-gen-grpc=$ + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} ${PROTO_PB_CC} gRPC::grpc_cpp_plugin + COMMENT "Running gRPC compiler on ${PROTO_FILE}" + VERBATIM + ) + + # Add generated files as source to the target + target_sources(${PROJECT_NAME} PRIVATE + ${PROTO_PB_CC} + ${PROTO_GRPC_CC} ) + + # Add include directory for generated files + target_include_directories(${PROJECT_NAME} PUBLIC "$") + + # Link protobuf and gRPC libraries + target_link_libraries(${PROJECT_NAME} PRIVATE protobuf::libprotobuf gRPC::grpc++) endif() target_include_directories(${PROJECT_NAME} @@ -84,21 +112,24 @@ target_link_libraries(${PROJECT_NAME} PRIVATE gRPC::gpr gRPC::grpc gRPC::grpc++ target_link_libraries(${PROJECT_NAME} PRIVATE amsi Shlwapi Crypt32) set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}/tests" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}/tests" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}/tests" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests/$" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests/$" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests/$" ) if(MSVC) # Set static runtime library for all configurations set_property(TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - + # Additional MSVC-specific flags for static linking target_compile_options(${PROJECT_NAME} PRIVATE $<$:/MT> $<$:/MTd> ) + + # Add linker flags to handle symbol issues with vcpkg libraries + target_link_options(${PROJECT_NAME} PRIVATE /FORCE:MULTIPLE) endif() include(GoogleTest) diff --git a/src/extensibility/PanoptesPE/CMakeLists.txt b/src/extensibility/PanoptesPE/CMakeLists.txt index 06b112b..63ddb3d 100644 --- a/src/extensibility/PanoptesPE/CMakeLists.txt +++ b/src/extensibility/PanoptesPE/CMakeLists.txt @@ -69,45 +69,66 @@ file(GLOB HEADERS add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) if(BUILD_GRPC) + find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) # Set proto file path - set(PROTO_FILE_DIR "${CMAKE_SOURCE_DIR}/proto/src/") - set(PROTO_BUILD_DIR "${CMAKE_SOURCE_DIR}/proto/build") + set(PROTO_SRC "${CMAKE_SOURCE_DIR}/proto/src") + set(PROTO_FILE "${PROTO_SRC}/panoptes.proto") + set(PROTO_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") - # Create build directory if it doesn't exist - file(MAKE_DIRECTORY ${PROTO_BUILD_DIR}) + # Generated file paths + set(PROTO_PB_CC "${PROTO_OUT_DIR}/panoptes.pb.cc") + set(PROTO_PB_H "${PROTO_OUT_DIR}/panoptes.pb.h") + set(PROTO_GRPC_CC "${PROTO_OUT_DIR}/panoptes.grpc.pb.cc") + set(PROTO_GRPC_H "${PROTO_OUT_DIR}/panoptes.grpc.pb.h") + + # Find protoc executable + find_program(PROTOC_EXECUTABLE protoc REQUIRED) message(" --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}") message(" --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}") message(" --> PROTOBUF VERSION: ${Protobuf_VERSION}") message(" --> PROTOBUF Found: ${Protobuf_FOUND}") - message(" --> PROTOBUF SRC: ${PROTO_SRC}") - message(" --> PROTOBUF HEADER: ${PROTO_HEADER}") - message(" --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto") - - #target_link_libraries(${PROJECT_NAME} PUBLIC protobuf::libprotobuf gRPC::grpc++) - - set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") - - target_include_directories(${PROJECT_NAME} PUBLIC "$") + message(" --> PROTO_FILE: ${PROTO_FILE}") + message(" --> Protobuf Compiler: ${PROTOC_EXECUTABLE}") + + # Create custom command for protobuf generation + add_custom_command( + OUTPUT ${PROTO_PB_CC} ${PROTO_PB_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --cpp_out=${PROTO_OUT_DIR} + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} + COMMENT "Running protobuf compiler on ${PROTO_FILE}" + VERBATIM + ) - protobuf_generate( - TARGET ${PROJECT_NAME} - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + # Create custom command for gRPC generation + add_custom_command( + OUTPUT ${PROTO_GRPC_CC} ${PROTO_GRPC_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --grpc_out=${PROTO_OUT_DIR} + --plugin=protoc-gen-grpc=$ + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} ${PROTO_PB_CC} gRPC::grpc_cpp_plugin + COMMENT "Running gRPC compiler on ${PROTO_FILE}" + VERBATIM ) - - protobuf_generate( - TARGET ${PROJECT_NAME} - LANGUAGE grpc - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc - PLUGIN "protoc-gen-grpc=\$" - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + + # Add generated files as source to the target + target_sources(${PROJECT_NAME} PRIVATE + ${PROTO_PB_CC} + ${PROTO_GRPC_CC} ) + + # Add include directory for generated files + target_include_directories(${PROJECT_NAME} PUBLIC "$") + + # Link protobuf and gRPC libraries + target_link_libraries(${PROJECT_NAME} PRIVATE protobuf::libprotobuf) endif() # Add include directories @@ -122,9 +143,9 @@ target_link_libraries(${PROJECT_NAME} PRIVATE gRPC::gpr gRPC::grpc gRPC::grpc++ # Set output directories set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) @@ -158,14 +179,14 @@ if(MSVC) ) endif() -# Add post-build command to copy DLL to ext directory for Debug configuration +# Add post-build command to copy DLL to ext directory add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/Debug/ext" + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/$/ext" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/ext/$" + "${CMAKE_SOURCE_DIR}/bin/$/ext/$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/ext/$" + "${CMAKE_SOURCE_DIR}/bin/$/ext/$" COMMENT "Copying ${PROJECT_NAME} DLL and PDB to ext directory" ) \ No newline at end of file diff --git a/src/extensibility/PanoptesPE/test/CMakeLists.txt b/src/extensibility/PanoptesPE/test/CMakeLists.txt index 1bbabbd..a2c146f 100644 --- a/src/extensibility/PanoptesPE/test/CMakeLists.txt +++ b/src/extensibility/PanoptesPE/test/CMakeLists.txt @@ -5,6 +5,11 @@ project(Test_PanoptesPE) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) +# Set static runtime for MSVC - MUST BE SET BEFORE ANY TARGETS +if(MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +endif() + # LIEF build config. Set the default options for LIEF's project setup option(LIEF_DOC "Build LIEF docs" OFF) option(LIEF_PYTHON_API "Build LIEF Python API" OFF) @@ -29,8 +34,8 @@ FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Use static CRT to match the rest of the project +set(gtest_force_shared_crt OFF CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) enable_testing() @@ -70,14 +75,16 @@ target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest_main LIEF::LIEF Crypt # Set output directories set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}/tests" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}/tests" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}/tests" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests/$" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests/$" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests/$" ) if(MSVC) - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" CACHE STRING "CRT option") - + set_target_properties(${PROJECT_NAME} PROPERTIES + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" + ) + target_compile_options(${PROJECT_NAME} PRIVATE $<$:/MT> $<$:/MTd> diff --git a/src/extensibility/PanoptesYara/CMakeLists.txt b/src/extensibility/PanoptesYara/CMakeLists.txt index 6bb9bcf..dad29f1 100644 --- a/src/extensibility/PanoptesYara/CMakeLists.txt +++ b/src/extensibility/PanoptesYara/CMakeLists.txt @@ -41,45 +41,66 @@ set(HEADERS add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) if(BUILD_GRPC) + find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) # Set proto file path - set(PROTO_FILE_DIR "${CMAKE_SOURCE_DIR}/proto/src/") - set(PROTO_BUILD_DIR "${CMAKE_SOURCE_DIR}/proto/build") + set(PROTO_SRC "${CMAKE_SOURCE_DIR}/proto/src") + set(PROTO_FILE "${PROTO_SRC}/panoptes.proto") + set(PROTO_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") - # Create build directory if it doesn't exist - file(MAKE_DIRECTORY ${PROTO_BUILD_DIR}) + # Generated file paths + set(PROTO_PB_CC "${PROTO_OUT_DIR}/panoptes.pb.cc") + set(PROTO_PB_H "${PROTO_OUT_DIR}/panoptes.pb.h") + set(PROTO_GRPC_CC "${PROTO_OUT_DIR}/panoptes.grpc.pb.cc") + set(PROTO_GRPC_H "${PROTO_OUT_DIR}/panoptes.grpc.pb.h") + + # Find protoc executable + find_program(PROTOC_EXECUTABLE protoc REQUIRED) message(" --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}") message(" --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}") message(" --> PROTOBUF VERSION: ${Protobuf_VERSION}") message(" --> PROTOBUF Found: ${Protobuf_FOUND}") - message(" --> PROTOBUF SRC: ${PROTO_SRC}") - message(" --> PROTOBUF HEADER: ${PROTO_HEADER}") - message(" --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto") - - #target_link_libraries(${PROJECT_NAME} PUBLIC protobuf::libprotobuf gRPC::grpc++) - - set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") - - target_include_directories(${PROJECT_NAME} PUBLIC "$") + message(" --> PROTO_FILE: ${PROTO_FILE}") + message(" --> Protobuf Compiler: ${PROTOC_EXECUTABLE}") + + # Create custom command for protobuf generation + add_custom_command( + OUTPUT ${PROTO_PB_CC} ${PROTO_PB_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --cpp_out=${PROTO_OUT_DIR} + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} + COMMENT "Running protobuf compiler on ${PROTO_FILE}" + VERBATIM + ) - protobuf_generate( - TARGET ${PROJECT_NAME} - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + # Create custom command for gRPC generation + add_custom_command( + OUTPUT ${PROTO_GRPC_CC} ${PROTO_GRPC_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --grpc_out=${PROTO_OUT_DIR} + --plugin=protoc-gen-grpc=$ + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} ${PROTO_PB_CC} gRPC::grpc_cpp_plugin + COMMENT "Running gRPC compiler on ${PROTO_FILE}" + VERBATIM ) - - protobuf_generate( - TARGET ${PROJECT_NAME} - LANGUAGE grpc - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc - PLUGIN "protoc-gen-grpc=\$" - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + + # Add generated files as source to the target + target_sources(${PROJECT_NAME} PRIVATE + ${PROTO_PB_CC} + ${PROTO_GRPC_CC} ) + + # Add include directory for generated files + target_include_directories(${PROJECT_NAME} PUBLIC "$") + + # Link protobuf and gRPC libraries + target_link_libraries(${PROJECT_NAME} PRIVATE protobuf::libprotobuf) endif() @@ -127,19 +148,19 @@ target_link_libraries(${PROJECT_NAME} # Set output directories set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) -# Add post-build command to copy DLL to ext directory for Debug configuration +# Add post-build command to copy DLL to ext directory add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/Debug/ext" + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/$/ext" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/ext/$" + "${CMAKE_SOURCE_DIR}/bin/$/ext/$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/ext/$" + "${CMAKE_SOURCE_DIR}/bin/$/ext/$" COMMENT "Copying ${PROJECT_NAME} DLL and PDB to ext directory" ) \ No newline at end of file diff --git a/src/extensibility/PanoptesYara/test/CMakeLists.txt b/src/extensibility/PanoptesYara/test/CMakeLists.txt index adae7e9..99c2ff3 100644 --- a/src/extensibility/PanoptesYara/test/CMakeLists.txt +++ b/src/extensibility/PanoptesYara/test/CMakeLists.txt @@ -4,11 +4,9 @@ project(Test_PanoptesYara) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +# Set static runtime for MSVC - MUST BE SET BEFORE ANY TARGETS if(MSVC) - # Set compiler flags to match msbuild configuration - # set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") - # set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") - + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") # Set linker flags # /MANIFEST - Enables manifest generation for the executable # /NXCOMPAT - Enables Data Execution Prevention (DEP) compatibility @@ -27,8 +25,8 @@ FetchContent_Declare( URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) -# For Windows: Prevent overriding the parent project's compiler/linker settings -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Use static CRT to match the rest of the project +set(gtest_force_shared_crt OFF CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) enable_testing() @@ -69,10 +67,21 @@ target_link_libraries(${PROJECT_NAME} PRIVATE target_link_libraries(${PROJECT_NAME} PUBLIC ${YARA_DIR}/yara_x_capi.lib) set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests" -) + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests/$" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests/$" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/tests/$" +) + +if(MSVC) + set_target_properties(${PROJECT_NAME} PROPERTIES + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" + ) + + target_compile_options(${PROJECT_NAME} PRIVATE + $<$:/MT> + $<$:/MTd> + ) +endif() include(GoogleTest) gtest_discover_tests(Test_PanoptesYara) @@ -81,10 +90,10 @@ gtest_discover_tests(Test_PanoptesYara) add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/assets/yara/rules.pkg" - "${CMAKE_SOURCE_DIR}/bin/tests/${CMAKE_BUILD_TYPE}/rules.pkg" + "${CMAKE_SOURCE_DIR}/bin/tests/$/rules.pkg" COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/assets/yara/eicarcom2.zip" - "${CMAKE_SOURCE_DIR}/bin/tests/${CMAKE_BUILD_TYPE}/eicarcom2.zip" + "${CMAKE_SOURCE_DIR}/bin/tests/$/eicarcom2.zip" ) # Update link directories diff --git a/src/libraries/ResourceCore/CMakeLists.txt b/src/libraries/ResourceCore/CMakeLists.txt index 012a46e..56f2750 100644 --- a/src/libraries/ResourceCore/CMakeLists.txt +++ b/src/libraries/ResourceCore/CMakeLists.txt @@ -25,9 +25,10 @@ target_include_directories(${PROJECT_NAME} # Set Windows specific properties if(MSVC) - # Set properties for MSVC + # Set properties for MSVC - DLLs should use dynamic runtime set_target_properties(${PROJECT_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" ) endif() @@ -46,8 +47,8 @@ install(FILES # Set output directories set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) diff --git a/src/libraries/TrayNotificationsCore/CMakeLists.txt b/src/libraries/TrayNotificationsCore/CMakeLists.txt index 9bac53f..75238f3 100644 --- a/src/libraries/TrayNotificationsCore/CMakeLists.txt +++ b/src/libraries/TrayNotificationsCore/CMakeLists.txt @@ -24,10 +24,9 @@ target_include_directories(${PROJECT_NAME} if(MSVC) # Enable static runtime linking - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") - + # Additional static runtime settings foreach(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE @@ -36,10 +35,11 @@ if(MSVC) string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") endif() endforeach() - + # Set properties for MSVC set_target_properties(${PROJECT_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" ) endif() diff --git a/src/linter/CMakeLists.txt b/src/linter/CMakeLists.txt index 007e796..d1aaabe 100644 --- a/src/linter/CMakeLists.txt +++ b/src/linter/CMakeLists.txt @@ -64,7 +64,7 @@ endif() # Set output directories set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) \ No newline at end of file diff --git a/src/scanner/PanoptesScan/CMakeLists.txt b/src/scanner/PanoptesScan/CMakeLists.txt index 8286ab6..4768f2c 100644 --- a/src/scanner/PanoptesScan/CMakeLists.txt +++ b/src/scanner/PanoptesScan/CMakeLists.txt @@ -28,41 +28,66 @@ set(HEADERS add_executable(${PROJECT_NAME} WIN32 ${SOURCES} ${HEADERS} ) if(BUILD_GRPC) + find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) # Set proto file path - set(PROTO_FILE_DIR "${CMAKE_SOURCE_DIR}/proto/src/") - set(PROTO_BUILD_DIR "${CMAKE_SOURCE_DIR}/proto/build") + set(PROTO_SRC "${CMAKE_SOURCE_DIR}/proto/src") + set(PROTO_FILE "${PROTO_SRC}/panoptes.proto") + set(PROTO_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") - # Create build directory if it doesn't exist - file(MAKE_DIRECTORY ${PROTO_BUILD_DIR}) + # Generated file paths + set(PROTO_PB_CC "${PROTO_OUT_DIR}/panoptes.pb.cc") + set(PROTO_PB_H "${PROTO_OUT_DIR}/panoptes.pb.h") + set(PROTO_GRPC_CC "${PROTO_OUT_DIR}/panoptes.grpc.pb.cc") + set(PROTO_GRPC_H "${PROTO_OUT_DIR}/panoptes.grpc.pb.h") + + # Find protoc executable + find_program(PROTOC_EXECUTABLE protoc REQUIRED) message(" --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}") message(" --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}") message(" --> PROTOBUF VERSION: ${Protobuf_VERSION}") message(" --> PROTOBUF Found: ${Protobuf_FOUND}") - message(" --> PROTOBUF SRC: ${PROTO_SRC}") - message(" --> PROTOBUF HEADER: ${PROTO_HEADER}") - message(" --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto") - - #target_link_libraries(${PROJECT_NAME} PUBLIC protobuf::libprotobuf gRPC::grpc++) - - set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") - - target_include_directories(${PROJECT_NAME} PUBLIC "$") + message(" --> PROTO_FILE: ${PROTO_FILE}") + message(" --> Protobuf Compiler: ${PROTOC_EXECUTABLE}") + + # Create custom command for protobuf generation + add_custom_command( + OUTPUT ${PROTO_PB_CC} ${PROTO_PB_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --cpp_out=${PROTO_OUT_DIR} + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} + COMMENT "Running protobuf compiler on ${PROTO_FILE}" + VERBATIM + ) - protobuf_generate( - TARGET ${PROJECT_NAME} - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}") - - protobuf_generate( - TARGET ${PROJECT_NAME} - LANGUAGE grpc - GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc - PLUGIN "protoc-gen-grpc=\$" - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}") + # Create custom command for gRPC generation + add_custom_command( + OUTPUT ${PROTO_GRPC_CC} ${PROTO_GRPC_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --grpc_out=${PROTO_OUT_DIR} + --plugin=protoc-gen-grpc=$ + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} ${PROTO_PB_CC} gRPC::grpc_cpp_plugin + COMMENT "Running gRPC compiler on ${PROTO_FILE}" + VERBATIM + ) + + # Add generated files as source to the target + target_sources(${PROJECT_NAME} PRIVATE + ${PROTO_PB_CC} + ${PROTO_GRPC_CC} + ) + + # Add include directory for generated files + target_include_directories(${PROJECT_NAME} PUBLIC "$") + + # Link protobuf and gRPC libraries + target_link_libraries(${PROJECT_NAME} PRIVATE protobuf::libprotobuf) endif() # Include directories @@ -82,7 +107,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE # Set output directories to match the vcxproj configuration set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) # Add icon resource diff --git a/src/scanner/PanoptesScanCLI/CMakeLists.txt b/src/scanner/PanoptesScanCLI/CMakeLists.txt index e4c6894..4b53819 100644 --- a/src/scanner/PanoptesScanCLI/CMakeLists.txt +++ b/src/scanner/PanoptesScanCLI/CMakeLists.txt @@ -26,45 +26,66 @@ set(HEADERS add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS}) if(BUILD_GRPC) + find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) # Set proto file path - set(PROTO_FILE_DIR "${CMAKE_SOURCE_DIR}/proto/src/") - set(PROTO_BUILD_DIR "${CMAKE_SOURCE_DIR}/proto/build") + set(PROTO_SRC "${CMAKE_SOURCE_DIR}/proto/src") + set(PROTO_FILE "${PROTO_SRC}/panoptes.proto") + set(PROTO_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") - # Create build directory if it doesn't exist - file(MAKE_DIRECTORY ${PROTO_BUILD_DIR}) + # Generated file paths + set(PROTO_PB_CC "${PROTO_OUT_DIR}/panoptes.pb.cc") + set(PROTO_PB_H "${PROTO_OUT_DIR}/panoptes.pb.h") + set(PROTO_GRPC_CC "${PROTO_OUT_DIR}/panoptes.grpc.pb.cc") + set(PROTO_GRPC_H "${PROTO_OUT_DIR}/panoptes.grpc.pb.h") + + # Find protoc executable + find_program(PROTOC_EXECUTABLE protoc REQUIRED) message(" --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}") message(" --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}") message(" --> PROTOBUF VERSION: ${Protobuf_VERSION}") message(" --> PROTOBUF Found: ${Protobuf_FOUND}") - message(" --> PROTOBUF SRC: ${PROTO_SRC}") - message(" --> PROTOBUF HEADER: ${PROTO_HEADER}") - message(" --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto") - - #target_link_libraries(${PROJECT_NAME} PUBLIC protobuf::libprotobuf gRPC::grpc++) - - set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") - - target_include_directories(${PROJECT_NAME} PUBLIC "$") + message(" --> PROTO_FILE: ${PROTO_FILE}") + message(" --> Protobuf Compiler: ${PROTOC_EXECUTABLE}") + + # Create custom command for protobuf generation + add_custom_command( + OUTPUT ${PROTO_PB_CC} ${PROTO_PB_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --cpp_out=${PROTO_OUT_DIR} + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} + COMMENT "Running protobuf compiler on ${PROTO_FILE}" + VERBATIM + ) - protobuf_generate( - TARGET ${PROJECT_NAME} - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + # Create custom command for gRPC generation + add_custom_command( + OUTPUT ${PROTO_GRPC_CC} ${PROTO_GRPC_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --grpc_out=${PROTO_OUT_DIR} + --plugin=protoc-gen-grpc=$ + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} ${PROTO_PB_CC} gRPC::grpc_cpp_plugin + COMMENT "Running gRPC compiler on ${PROTO_FILE}" + VERBATIM ) - - protobuf_generate( - TARGET ${PROJECT_NAME} - LANGUAGE grpc - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc - PLUGIN "protoc-gen-grpc=\$" - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + + # Add generated files as source to the target + target_sources(${PROJECT_NAME} PRIVATE + ${PROTO_PB_CC} + ${PROTO_GRPC_CC} ) + + # Add include directory for generated files + target_include_directories(${PROJECT_NAME} PUBLIC "$") + + # Link protobuf and gRPC libraries + target_link_libraries(${PROJECT_NAME} PRIVATE protobuf::libprotobuf) endif() # Include directories @@ -86,7 +107,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE # Set output directories to match the vcxproj configuration set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) # Add icon resource diff --git a/src/service/CMakeLists.txt b/src/service/CMakeLists.txt index c6a4f17..7506052 100644 --- a/src/service/CMakeLists.txt +++ b/src/service/CMakeLists.txt @@ -50,45 +50,66 @@ set(HEADERS add_executable(${PROJECT_NAME} WIN32 ${SOURCES} ${HEADERS}) if(BUILD_GRPC) + find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) # Set proto file path - set(PROTO_FILE_DIR "${CMAKE_SOURCE_DIR}/proto/src/") - set(PROTO_BUILD_DIR "${CMAKE_SOURCE_DIR}/proto/build") + set(PROTO_SRC "${CMAKE_SOURCE_DIR}/proto/src") + set(PROTO_FILE "${PROTO_SRC}/panoptes.proto") + set(PROTO_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") - # Create build directory if it doesn't exist - file(MAKE_DIRECTORY ${PROTO_BUILD_DIR}) + # Generated file paths + set(PROTO_PB_CC "${PROTO_OUT_DIR}/panoptes.pb.cc") + set(PROTO_PB_H "${PROTO_OUT_DIR}/panoptes.pb.h") + set(PROTO_GRPC_CC "${PROTO_OUT_DIR}/panoptes.grpc.pb.cc") + set(PROTO_GRPC_H "${PROTO_OUT_DIR}/panoptes.grpc.pb.h") + + # Find protoc executable + find_program(PROTOC_EXECUTABLE protoc REQUIRED) message(" --> PROTOBUF LIB: ${PROTOBUF_LIBRARIES}") message(" --> PROTOBUF INCLUDE: ${Protobuf_INCLUDE_DIRS}") message(" --> PROTOBUF VERSION: ${Protobuf_VERSION}") message(" --> PROTOBUF Found: ${Protobuf_FOUND}") - message(" --> PROTOBUF SRC: ${PROTO_SRC}") - message(" --> PROTOBUF HEADER: ${PROTO_HEADER}") - message(" --> PROTOBUF Folder: ${CMAKE_BINARY_DIR}/proto") - - #target_link_libraries(${PROJECT_NAME} PUBLIC protobuf::libprotobuf gRPC::grpc++) - - set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") - - target_include_directories(${PROJECT_NAME} PUBLIC "$") - - protobuf_generate( - TARGET ${PROJECT_NAME} - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + message(" --> PROTO_FILE: ${PROTO_FILE}") + message(" --> Protobuf Compiler: ${PROTOC_EXECUTABLE}") + + # Create custom command for protobuf generation + add_custom_command( + OUTPUT ${PROTO_PB_CC} ${PROTO_PB_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --cpp_out=${PROTO_OUT_DIR} + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} + COMMENT "Running protobuf compiler on ${PROTO_FILE}" + VERBATIM + ) + + # Create custom command for gRPC generation + add_custom_command( + OUTPUT ${PROTO_GRPC_CC} ${PROTO_GRPC_H} + COMMAND ${PROTOC_EXECUTABLE} + ARGS --grpc_out=${PROTO_OUT_DIR} + --plugin=protoc-gen-grpc=$ + -I${PROTO_SRC} + ${PROTO_FILE} + DEPENDS ${PROTO_FILE} ${PROTO_PB_CC} gRPC::grpc_cpp_plugin + COMMENT "Running gRPC compiler on ${PROTO_FILE}" + VERBATIM ) - - protobuf_generate( - TARGET ${PROJECT_NAME} - LANGUAGE grpc - PROTOC_EXE "${CMAKE_BINARY_DIR}/${Protobuf_PROTOC_EXECUTABLE}" - GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc - PLUGIN "protoc-gen-grpc=\$" - IMPORT_DIRS ${PROTO_FILE_DIR} - PROTOC_OUT_DIR "${PROTO_BINARY_DIR}" + + # Add generated files as source to the target + target_sources(${PROJECT_NAME} PRIVATE + ${PROTO_PB_CC} + ${PROTO_GRPC_CC} ) + + # Add include directory for generated files + target_include_directories(${PROJECT_NAME} PUBLIC "$") + + # Link protobuf and gRPC libraries + target_link_libraries(${PROJECT_NAME} PRIVATE protobuf::libprotobuf) endif() # Add include directories @@ -141,13 +162,11 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE NOMINMAX ) -# Set output directories - # Set output directories set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) # Post-build command to copy config file diff --git a/src/testing/KernelTestHost/CMakeLists.txt b/src/testing/KernelTestHost/CMakeLists.txt index 41e9ba9..d885a59 100644 --- a/src/testing/KernelTestHost/CMakeLists.txt +++ b/src/testing/KernelTestHost/CMakeLists.txt @@ -1,7 +1,12 @@ cmake_minimum_required(VERSION 4.0) +# Only build KernelTestHost in Debug mode +if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + return() +endif() + # Project name and language -project(KernelTestHost +project(KernelTestHost VERSION 1.0 LANGUAGES CXX) @@ -28,8 +33,9 @@ target_include_directories(${PROJECT_NAME} PRIVATE ) # Set output directories to match the MSVC structure -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin/$/testing) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/$/testing) +set_target_properties(${PROJECT_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$/testing" +) # Windows-specific settings if(WIN32) From 7b9c46b30dd97f79a4da411884eaa666b566c692 Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 21:46:58 -0700 Subject: [PATCH 06/16] Release now builds easily --- CMakeLists.txt | 17 +++++++++-------- CMakePresets.json | 2 ++ installer/Setup/CMakeLists.txt | 2 +- installer/Wix/CMakeLists.txt | 3 +-- installer/Wix/WixInstaller.wixproj | 2 +- src/extensibility/PanoptesAMSI/CMakeLists.txt | 12 +----------- src/extensibility/PanoptesPE/CMakeLists.txt | 12 +----------- src/extensibility/PanoptesYara/CMakeLists.txt | 12 +----------- 8 files changed, 17 insertions(+), 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ad1c68..ac8a974 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,14 +28,14 @@ elseif(DOXYGEN_FOUND AND NOT BUILD_DOC) endif(DOXYGEN_FOUND AND BUILD_DOC) -#add_subdirectory(src/service) -#add_subdirectory(src/libraries) - -#add_subdirectory(src/extensibility) -#add_subdirectory(src/container) -#add_subdirectory(src/dll) -#add_subdirectory(src/linter) -#add_subdirectory(src/scanner) +add_subdirectory(src/service) +add_subdirectory(src/libraries) + +add_subdirectory(src/extensibility) +add_subdirectory(src/container) +add_subdirectory(src/dll) +add_subdirectory(src/linter) +add_subdirectory(src/scanner) add_subdirectory(src/testing) if(BUILD_DRIVER) @@ -43,6 +43,7 @@ if(BUILD_DRIVER) endif() if(BUILD_WIX_INSTALLER) + add_subdirectory(src/driver) add_subdirectory(installer/Setup) add_subdirectory(installer/Wix) endif() diff --git a/CMakePresets.json b/CMakePresets.json index 34087af..0e5f288 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -16,6 +16,7 @@ "gRPC_DIR": "vcpkg_installed/x64-windows-static/share/grpc", "nlohmann_json_DIR": "vcpkg_installed/x64-windows-static/share/nlohmann_json", "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreadedDebug", + "VCPKG_APPLOCAL_DEPS": "OFF", "PRESET_NAME": "Debug", "x86_BUILD_TOOLS_PATH": "C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x86/", "x64_BUILD_TOOLS_PATH": "C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x64" @@ -36,6 +37,7 @@ "gRPC_DIR": "vcpkg_installed/x64-windows-static/share/grpc", "nlohmann_json_DIR": "vcpkg_installed/x64-windows-static/share/nlohmann_json", "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded", + "VCPKG_APPLOCAL_DEPS": "OFF", "PRESET_NAME": "Release", "x86_BUILD_TOOLS_PATH": "C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x86/", "x64_BUILD_TOOLS_PATH": "C:/Program Files (x86)/Windows Kits/10/bin/10.0.26100.0/x64" diff --git a/installer/Setup/CMakeLists.txt b/installer/Setup/CMakeLists.txt index 397a8c9..ee53132 100644 --- a/installer/Setup/CMakeLists.txt +++ b/installer/Setup/CMakeLists.txt @@ -35,7 +35,7 @@ endif() target_include_directories(PanoptesSetup PRIVATE ${CATCH_INCLUDE_DIR}) set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/${PRESET_NAME}" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) # Configure specific settings for different configurations diff --git a/installer/Wix/CMakeLists.txt b/installer/Wix/CMakeLists.txt index 3cda5c8..fc76e7e 100644 --- a/installer/Wix/CMakeLists.txt +++ b/installer/Wix/CMakeLists.txt @@ -32,8 +32,7 @@ add_custom_command( -bindpath "${CMAKE_SOURCE_DIR}/assets/yara" -bindpath "${CMAKE_SOURCE_DIR}/assets" -bindpath "${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}" - -bindpath "${CMAKE_SOURCE_DIR}/bin/driver/${CMAKE_BUILD_TYPE}" - -bindpath "${CMAKE_SOURCE_DIR}/bin/driver" + -bindpath "${CMAKE_SOURCE_DIR}/bin/Release/driver" -bindpath "${CMAKE_SOURCE_DIR}/assets/icons" -bindpath "${CMAKE_CURRENT_SOURCE_DIR}/assets" ${WIX_SOURCES} diff --git a/installer/Wix/WixInstaller.wixproj b/installer/Wix/WixInstaller.wixproj index 9738e2e..ab57ef4 100644 --- a/installer/Wix/WixInstaller.wixproj +++ b/installer/Wix/WixInstaller.wixproj @@ -24,7 +24,7 @@ - + diff --git a/src/extensibility/PanoptesAMSI/CMakeLists.txt b/src/extensibility/PanoptesAMSI/CMakeLists.txt index c12bc30..c562056 100644 --- a/src/extensibility/PanoptesAMSI/CMakeLists.txt +++ b/src/extensibility/PanoptesAMSI/CMakeLists.txt @@ -139,14 +139,4 @@ if(MSVC) ) endif() -# Add post-build command to copy DLL to ext directory -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/$/ext" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/$/ext/$" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/$/ext/$" - COMMENT "Copying ${PROJECT_NAME} DLL and PDB to ext directory" -) \ No newline at end of file + \ No newline at end of file diff --git a/src/extensibility/PanoptesPE/CMakeLists.txt b/src/extensibility/PanoptesPE/CMakeLists.txt index 63ddb3d..3d7b573 100644 --- a/src/extensibility/PanoptesPE/CMakeLists.txt +++ b/src/extensibility/PanoptesPE/CMakeLists.txt @@ -179,14 +179,4 @@ if(MSVC) ) endif() -# Add post-build command to copy DLL to ext directory -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/$/ext" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/$/ext/$" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/$/ext/$" - COMMENT "Copying ${PROJECT_NAME} DLL and PDB to ext directory" -) \ No newline at end of file + \ No newline at end of file diff --git a/src/extensibility/PanoptesYara/CMakeLists.txt b/src/extensibility/PanoptesYara/CMakeLists.txt index dad29f1..ac6d8d9 100644 --- a/src/extensibility/PanoptesYara/CMakeLists.txt +++ b/src/extensibility/PanoptesYara/CMakeLists.txt @@ -153,14 +153,4 @@ set_target_properties(${PROJECT_NAME} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin/$" ) -# Add post-build command to copy DLL to ext directory -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/$/ext" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/$/ext/$" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/$/ext/$" - COMMENT "Copying ${PROJECT_NAME} DLL and PDB to ext directory" -) \ No newline at end of file + \ No newline at end of file From 0aba766a08c3ad6d39a4ec534ed6869ad0959d89 Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 21:52:34 -0700 Subject: [PATCH 07/16] Pull latest .github/workflows from main Syncs the build.yml workflow with the latest changes from the main branch. Co-Authored-By: Claude Haiku 4.5 --- .github/workflows/build.yml | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..7b85d44 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,43 @@ +name: Build Panoptes + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: [self-hosted, DESKTOP-N792BI5] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup vcpkg + uses: lukka/run-vcpkg@v11 + with: + vcpkgJsonGlob: 'vcpkg.json' + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Configure CMake (Debug) + run: cmake --preset debug -G "Visual Studio 17 2022" -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON + env: + VCPKG_ROOT: ${{ github.workspace }}/vcpkg + + - name: Build (Debug) + run: msbuild build/debug/Panoptes.sln /p:Configuration=Debug /p:Platform=x64 /m + + - name: Upload Debug Artifacts + uses: actions/upload-artifact@v4 + with: + name: panoptes-debug + path: | + build/debug/**/*.dll + build/debug/**/*.exe + build/debug/**/*.pdb + if-no-files-found: warn From e72b65f59e2a7c19b2f7e9281436b8a9b14010b3 Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 21:53:50 -0700 Subject: [PATCH 08/16] Update GitHub workflow to properly build Debug and Release - Split workflow into separate debug and release jobs for parallel builds - Use CMake presets instead of manual generator flags - Update artifact paths to use bin/ directory structure - Include test executables (KernelTestHost for Debug) - Remove unnecessary generator flag (-G "Visual Studio 17 2022") Co-Authored-By: Claude Haiku 4.5 --- .github/workflows/build.yml | 51 ++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7b85d44..511db7e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,9 +9,10 @@ on: - main jobs: - build: + build-debug: + name: Build Debug runs-on: [self-hosted, DESKTOP-N792BI5] - + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -25,7 +26,7 @@ jobs: uses: microsoft/setup-msbuild@v2 - name: Configure CMake (Debug) - run: cmake --preset debug -G "Visual Studio 17 2022" -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON + run: cmake --preset debug -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg @@ -37,7 +38,45 @@ jobs: with: name: panoptes-debug path: | - build/debug/**/*.dll - build/debug/**/*.exe - build/debug/**/*.pdb + bin/Debug/**/*.dll + bin/Debug/**/*.exe + bin/Debug/**/*.pdb + bin/tests/Debug/**/*.exe + bin/tests/Debug/**/*.pdb + if-no-files-found: warn + + build-release: + name: Build Release + runs-on: [self-hosted, DESKTOP-N792BI5] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup vcpkg + uses: lukka/run-vcpkg@v11 + with: + vcpkgJsonGlob: 'vcpkg.json' + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Configure CMake (Release) + run: cmake --preset release -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON + env: + VCPKG_ROOT: ${{ github.workspace }}/vcpkg + + - name: Build (Release) + run: msbuild build/release/Panoptes.sln /p:Configuration=Release /p:Platform=x64 /m + + - name: Upload Release Artifacts + uses: actions/upload-artifact@v4 + with: + name: panoptes-release + path: | + bin/Release/**/*.dll + bin/Release/**/*.exe + bin/Release/**/*.pdb + bin/tests/Release/**/*.exe + bin/tests/Release/**/*.pdb if-no-files-found: warn From 68bad96c3de7cb7c885d4734b482d6f8825980b1 Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 22:09:57 -0700 Subject: [PATCH 09/16] Setup Microsoft Detours as git submodule for DLL - Add Detours as git submodule from https://github.com/microsoft/detours.git - Create Detours-build/CMakeLists.txt to build lib_detours static library - Update src/dll/CMakeLists.txt to link against locally built Detours - Remove dependency on vcpkg for Detours (fixes GitHub Actions build) - Initialize submodule with git submodule update --init --recursive This allows the DLL component to be built with Detours without relying on vcpkg's problematic build of the detours package. Co-Authored-By: Claude Haiku 4.5 --- .gitmodules | 3 +++ src/dll/CMakeLists.txt | 13 +++++------ src/dll/Detours | 1 + src/dll/Detours-build/CMakeLists.txt | 33 ++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 .gitmodules create mode 160000 src/dll/Detours create mode 100644 src/dll/Detours-build/CMakeLists.txt diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..51533c4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/dll/Detours"] + path = src/dll/Detours + url = https://github.com/microsoft/detours.git diff --git a/src/dll/CMakeLists.txt b/src/dll/CMakeLists.txt index 13485ec..b34f181 100644 --- a/src/dll/CMakeLists.txt +++ b/src/dll/CMakeLists.txt @@ -10,6 +10,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # Enable static linking for both architectures set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +# Build Detours library from source +add_subdirectory(Detours-build) + # Source files set(SOURCES src/dllmain.cpp @@ -32,10 +35,6 @@ function(configure_target TARGET_NAME ARCH) set(OUTPUT_SUFFIX "x86") endif() - # Set Detours paths for this architecture - find_path(DETOURS_INCLUDE_DIRS "detours/detours.h") - find_library(DETOURS_LIBRARY detours REQUIRED) - # Create target add_library(${TARGET_NAME} SHARED ${SOURCES} @@ -51,11 +50,11 @@ function(configure_target TARGET_NAME ARCH) # Include directories target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include - ${DETOURS_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR}/Detours/src ) - # Link dependencies - target_link_libraries(${TARGET_NAME} PRIVATE ${DETOURS_LIBRARY}) + # Link dependencies against locally built Detours library + target_link_libraries(${TARGET_NAME} PRIVATE lib_detours) # Compiler definitions target_compile_definitions(${TARGET_NAME} PRIVATE diff --git a/src/dll/Detours b/src/dll/Detours new file mode 160000 index 0000000..9764ceb --- /dev/null +++ b/src/dll/Detours @@ -0,0 +1 @@ +Subproject commit 9764cebcb1a75940e68fa83d6730ffaf0f669401 diff --git a/src/dll/Detours-build/CMakeLists.txt b/src/dll/Detours-build/CMakeLists.txt new file mode 100644 index 0000000..0fb328d --- /dev/null +++ b/src/dll/Detours-build/CMakeLists.txt @@ -0,0 +1,33 @@ +# Detours Library Build +set(TARGET lib_detours) +set(DETOURS_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/../Detours/src) + +add_library(${TARGET} STATIC + ${DETOURS_SOURCE}/creatwth.cpp + ${DETOURS_SOURCE}/detours.cpp + ${DETOURS_SOURCE}/detours.h + ${DETOURS_SOURCE}/detver.h + ${DETOURS_SOURCE}/disasm.cpp + ${DETOURS_SOURCE}/disolarm.cpp + ${DETOURS_SOURCE}/disolarm64.cpp + ${DETOURS_SOURCE}/disolia64.cpp + ${DETOURS_SOURCE}/disolx64.cpp + ${DETOURS_SOURCE}/disolx86.cpp + ${DETOURS_SOURCE}/image.cpp + ${DETOURS_SOURCE}/modules.cpp + ${DETOURS_SOURCE}/uimports.cpp +) + +# This file is included and not compiled on its own +set_property( + SOURCE ${DETOURS_SOURCE}/uimports.cpp + APPEND PROPERTY HEADER_FILE_ONLY true +) + +if(MSVC) + target_compile_options(${TARGET} PRIVATE /W4 /WX /Zi /MT /Gy /Gm- /Zl /Od) +else() + target_compile_options(${TARGET} PRIVATE -Wall -Wextra -g -O0) +endif() + +target_include_directories(${TARGET} PUBLIC ${DETOURS_SOURCE}) From b5494b0695c809b0edc1e7a89b45ddff0deca466 Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 22:10:24 -0700 Subject: [PATCH 10/16] Remove detours from vcpkg dependencies Since Detours is now built locally as a git submodule, it's no longer needed as a vcpkg dependency. This resolves the GitHub Actions build failure related to detours compilation. Co-Authored-By: Claude Haiku 4.5 --- vcpkg.json | 1 - 1 file changed, 1 deletion(-) diff --git a/vcpkg.json b/vcpkg.json index 6a6969f..1146d06 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,5 @@ { "dependencies": [ - "detours", { "name": "grpc", "version>=": "1.71.0" From 5ae1f7ef3ad50a40b1ae69e01ce6d30ee0522d78 Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 22:14:01 -0700 Subject: [PATCH 11/16] Configure GitHub workflow to avoid ninja, use MSBuild instead - Add CMAKE_GENERATOR environment variable set to "Visual Studio 17 2022" - Add submodules: recursive to checkout step for Detours submodule - Ensures vcpkg uses MSBuild for building dependencies, not Ninja - Resolves issues with ninja-based vcpkg builds in CI/CD Co-Authored-By: Claude Haiku 4.5 --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 511db7e..e2b43d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,6 +16,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + submodules: recursive - name: Setup vcpkg uses: lukka/run-vcpkg@v11 @@ -29,6 +31,7 @@ jobs: run: cmake --preset debug -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg + CMAKE_GENERATOR: "Visual Studio 17 2022" - name: Build (Debug) run: msbuild build/debug/Panoptes.sln /p:Configuration=Debug /p:Platform=x64 /m @@ -52,6 +55,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + submodules: recursive - name: Setup vcpkg uses: lukka/run-vcpkg@v11 @@ -65,6 +70,7 @@ jobs: run: cmake --preset release -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg + CMAKE_GENERATOR: "Visual Studio 17 2022" - name: Build (Release) run: msbuild build/release/Panoptes.sln /p:Configuration=Release /p:Platform=x64 /m From 11d0231859397189be9727ad486b30a6d933839c Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 22:17:06 -0700 Subject: [PATCH 12/16] Clean up GitHub workflow - remove redundant CMAKE_GENERATOR variable The CMakePresets.json already specifies 'Visual Studio 17 2022' as the generator for both debug and release presets, so the CMAKE_GENERATOR environment variable was redundant. Removing it keeps the workflow clean and ensures all configuration comes from the presets. Workflow now: - Uses cmake --preset debug and cmake --preset release - Properly initializes git submodules (for Detours) - Builds with MSBuild using the generated solutions - Uploads artifacts to GitHub Co-Authored-By: Claude Haiku 4.5 --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e2b43d1..de0cd22 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,7 +31,6 @@ jobs: run: cmake --preset debug -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg - CMAKE_GENERATOR: "Visual Studio 17 2022" - name: Build (Debug) run: msbuild build/debug/Panoptes.sln /p:Configuration=Debug /p:Platform=x64 /m @@ -70,7 +69,6 @@ jobs: run: cmake --preset release -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg - CMAKE_GENERATOR: "Visual Studio 17 2022" - name: Build (Release) run: msbuild build/release/Panoptes.sln /p:Configuration=Release /p:Platform=x64 /m From 0f418020267ec1fdf8fbb2b16265bce53ceefa2c Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 22:21:45 -0700 Subject: [PATCH 13/16] Fix GitHub workflow to ensure vcpkg uses MSBuild not Ninja - Add CMAKE_GENERATOR env variable to vcpkg setup step - Add CMAKE_GENERATOR env variable to cmake configuration steps - Ensures vcpkg builds its dependencies (zlib, grpc, etc) with MSBuild instead of Ninja, which was causing resource compiler failures The CMAKE_GENERATOR environment variable set during vcpkg step tells vcpkg which generator to use when building its own dependencies, preventing Ninja from being used and avoiding linker/RC compiler errors. Co-Authored-By: Claude Haiku 4.5 --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index de0cd22..5596adf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,6 +23,8 @@ jobs: uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: 'vcpkg.json' + env: + CMAKE_GENERATOR: "Visual Studio 17 2022" - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 @@ -31,6 +33,7 @@ jobs: run: cmake --preset debug -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg + CMAKE_GENERATOR: "Visual Studio 17 2022" - name: Build (Debug) run: msbuild build/debug/Panoptes.sln /p:Configuration=Debug /p:Platform=x64 /m @@ -61,6 +64,8 @@ jobs: uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: 'vcpkg.json' + env: + CMAKE_GENERATOR: "Visual Studio 17 2022" - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 @@ -69,6 +74,7 @@ jobs: run: cmake --preset release -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg + CMAKE_GENERATOR: "Visual Studio 17 2022" - name: Build (Release) run: msbuild build/release/Panoptes.sln /p:Configuration=Release /p:Platform=x64 /m From 07e00ab22b881c26305882e76f5dc99fbacbab30 Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 22:31:28 -0700 Subject: [PATCH 14/16] Fix RC.exe not found error in GitHub Actions workflow Add Windows SDK tools to PATH before vcpkg runs. The resource compiler (RC.exe) was failing during vcpkg's compiler detection when building dependencies with Ninja. This step ensures RC.exe is available in the environment by adding the Windows SDK bin directory to PATH. Co-Authored-By: Claude Haiku 4.5 --- .github/workflows/build.yml | 39 ++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5596adf..fd3400d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,12 +19,27 @@ jobs: with: submodules: recursive + - name: Add Windows SDK tools to PATH + shell: pwsh + run: | + $sdkPaths = @( + "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64", + "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64", + "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64" + ) + foreach ($path in $sdkPaths) { + if (Test-Path $path) { + echo "$path" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + Write-Host "Added to PATH: $path" + break + } + } + - name: Setup vcpkg uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: 'vcpkg.json' - env: - CMAKE_GENERATOR: "Visual Studio 17 2022" + useVcpkgInstallArtifactCaching: true - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 @@ -33,7 +48,6 @@ jobs: run: cmake --preset debug -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg - CMAKE_GENERATOR: "Visual Studio 17 2022" - name: Build (Debug) run: msbuild build/debug/Panoptes.sln /p:Configuration=Debug /p:Platform=x64 /m @@ -60,12 +74,27 @@ jobs: with: submodules: recursive + - name: Add Windows SDK tools to PATH + shell: pwsh + run: | + $sdkPaths = @( + "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64", + "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64", + "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64" + ) + foreach ($path in $sdkPaths) { + if (Test-Path $path) { + echo "$path" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + Write-Host "Added to PATH: $path" + break + } + } + - name: Setup vcpkg uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: 'vcpkg.json' - env: - CMAKE_GENERATOR: "Visual Studio 17 2022" + useVcpkgInstallArtifactCaching: true - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 From 20bd0d212aff38f9e162425258193882062cd03e Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 22:33:56 -0700 Subject: [PATCH 15/16] test --- .github/workflows/build.yml | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd3400d..fa773a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,27 +19,11 @@ jobs: with: submodules: recursive - - name: Add Windows SDK tools to PATH - shell: pwsh - run: | - $sdkPaths = @( - "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64", - "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64", - "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64" - ) - foreach ($path in $sdkPaths) { - if (Test-Path $path) { - echo "$path" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - Write-Host "Added to PATH: $path" - break - } - } - - name: Setup vcpkg uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: 'vcpkg.json' - useVcpkgInstallArtifactCaching: true + buildPreset: debug - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 @@ -74,27 +58,11 @@ jobs: with: submodules: recursive - - name: Add Windows SDK tools to PATH - shell: pwsh - run: | - $sdkPaths = @( - "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64", - "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64", - "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64" - ) - foreach ($path in $sdkPaths) { - if (Test-Path $path) { - echo "$path" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - Write-Host "Added to PATH: $path" - break - } - } - - name: Setup vcpkg uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: 'vcpkg.json' - useVcpkgInstallArtifactCaching: true + buildPreset: release - name: Setup MSBuild uses: microsoft/setup-msbuild@v2 From cee247232d030b5748d6f340ee2bb24cab3d9267 Mon Sep 17 00:00:00 2001 From: Ap3x Date: Sun, 18 Jan 2026 22:36:03 -0700 Subject: [PATCH 16/16] lets try this --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fa773a7..06d6636 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: uses: microsoft/setup-msbuild@v2 - name: Configure CMake (Debug) - run: cmake --preset debug -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON + run: cmake --preset debug -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON -G "Visual Studio 17 2022" env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg @@ -68,7 +68,7 @@ jobs: uses: microsoft/setup-msbuild@v2 - name: Configure CMake (Release) - run: cmake --preset release -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON + run: cmake --preset release -DBUILD_DOC=OFF -DBUILD_DRIVER=ON -DBUILD_WIX_INSTALLER=OFF -DBUILD_GRPC=ON -G "Visual Studio 17 2022" env: VCPKG_ROOT: ${{ github.workspace }}/vcpkg CMAKE_GENERATOR: "Visual Studio 17 2022"