diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7b85d44..06d6636 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,23 +9,27 @@ on: - main jobs: - build: + build-debug: + name: Build Debug runs-on: [self-hosted, DESKTOP-N792BI5] - + steps: - name: Checkout repository uses: actions/checkout@v4 + with: + submodules: recursive - name: Setup vcpkg uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: 'vcpkg.json' + buildPreset: debug - 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 + 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 @@ -37,7 +41,49 @@ 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 + with: + submodules: recursive + + - name: Setup vcpkg + uses: lukka/run-vcpkg@v11 + with: + vcpkgJsonGlob: 'vcpkg.json' + buildPreset: release + + - 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 -G "Visual Studio 17 2022" + 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 + + - 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 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/CMakeLists.txt b/CMakeLists.txt index 9bdcf59..39716a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,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 9342094..0e5f288 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -16,6 +16,8 @@ "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" } @@ -34,6 +36,9 @@ "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", + "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/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/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/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/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 7cd0e50..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} @@ -44,18 +43,18 @@ 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 ${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 @@ -81,6 +80,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/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}) diff --git a/src/driver/CMakeLists.txt b/src/driver/CMakeLists.txt index 1ff7304..e1f0e43 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 @@ -55,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) @@ -67,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/driver/include/callbacks.h b/src/driver/include/callbacks.h index b4794a6..4ad6a0d 100644 --- a/src/driver/include/callbacks.h +++ b/src/driver/include/callbacks.h @@ -1,46 +1,8 @@ #pragma once -#include "structs.h" -#include -#include +#include "pch.h" +#include "state.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 RtlFindExportedRoutineByName(PVOID DllBase,PCHAR RoutineName); -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(); +NTSTATUS InitializeKernelCallbacks(PanoptesState* State); diff --git a/src/driver/include/driver_constants.h b/src/driver/include/driver_constants.h deleted file mode 100644 index 1024da7..0000000 --- a/src/driver/include/driver_constants.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -#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 diff --git a/src/driver/include/filter.h b/src/driver/include/filter.h new file mode 100644 index 0000000..cf8e441 --- /dev/null +++ b/src/driver/include/filter.h @@ -0,0 +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} +}; + diff --git a/src/driver/include/inject.h b/src/driver/include/inject.h index a19e0be..74ecd89 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 @@ -229,26 +231,34 @@ 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, - _In_ PKKERNEL_ROUTINE KernelRoutine, + _In_ PKKERNEL_ROUTINE KernelRundown, _In_opt_ PKRUNDOWN_ROUTINE RundownRoutine, _In_opt_ PKNORMAL_ROUTINE NormalRoutine, _In_opt_ KPROCESSOR_MODE ProcessorMode, _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, _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, BOOLEAN is64Bit); 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/pano_filter.h b/src/driver/include/pano_filter.h deleted file mode 100644 index 28c76fd..0000000 --- a/src/driver/include/pano_filter.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include - -NTSTATUS FilterInit(PDRIVER_OBJECT* DriverObject); diff --git a/src/driver/include/pch.h b/src/driver/include/pch.h new file mode 100644 index 0000000..83f49c5 --- /dev/null +++ b/src/driver/include/pch.h @@ -0,0 +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: " +#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..f310794 --- /dev/null +++ b/src/driver/include/state.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include + +typedef struct _PANO_PROCESS_INFO +{ + ULONG ProcessId; + BOOLEAN Injected; + BOOLEAN Kernel32Loaded; + BOOLEAN KernelBaseLoaded; + BOOLEAN NtdllLoaded; + BOOLEAN Wow64Loaded; + BOOLEAN MitigationPolicyBan; + PVOID Kernel32ImageBase; +} PANO_PROCESS_INFO, * PPANO_PROCESS_INFO; + +struct PanoptesState { + LARGE_INTEGER RegistryCookie; + RTL_AVL_TABLE Processes; + FAST_MUTEX ProcessesLock; + PCALLBACK_OBJECT ProcessCreateCallback; + PFLT_FILTER FilterHandle; + UNICODE_STRING g_symLink; + UNICODE_STRING g_SymbolicLinkName; + + 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 f752996..a12081a 100644 --- a/src/driver/include/trace.h +++ b/src/driver/include/trace.h @@ -1,95 +1,41 @@ #pragma once -#include +#include "pch.h" #include #pragma region TraceLogging Initialization -void TraceInit(); - -void TraceUninit(); +void TraceInitialize(); +void TraceTerminate(); #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/include/pano_query.h b/src/driver/include/utils.h similarity index 66% rename from src/driver/include/pano_query.h rename to src/driver/include/utils.h index c6f7298..5c15e1f 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,25 @@ 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, +EXTERN_C NTSTATUS NTAPI ZwQueryInformationProcess( + HANDLE hProcess, + PROCESSINFOCLASS infoType, + /*out*/ PVOID pBuf, + /*sizeof pBuf*/ ULONG lenBuf, SIZE_T* /*PULONG*/ returnLength ); -#pragma endregion +EXTERN_C NTSTATUS NTAPI ZwQueryInformationToken( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation OPTIONAL, + IN ULONG TokenInformationLength, + OUT PULONG ReturnLength +); + +NTSTATUS GetFileNameFromPath(PUNICODE_STRING FullPath, PUNICODE_STRING FileName); +NTSTATUS QueryProcessMitigationPolicy(PEPROCESS ProcessId, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo); -NTSTATUS QueryProcessMitigationPolicy(HANDLE ProcessId, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo); +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 b8d8cdc..16cd8a4 100644 --- a/src/driver/src/callbacks.cpp +++ b/src/driver/src/callbacks.cpp @@ -1,618 +1,235 @@ #include "callbacks.h" #include "inject.h" -#include "pano_query.h" -#include -#include "shellcode.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; -} - -//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; - //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; - } - //ExReleaseSpinLock(&g_ProcessListLock, NULL); - return NULL; -} - -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; - } - 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); -} +#include "utils.h" +#include +PanoptesState* g_pState = nullptr; -struct InjectArgs { - PUNICODE_STRING DLLPath; - PUNICODE_STRING DllName; - PVOID DllHandle; -}; - -BOOLEAN CanInject(PPANO_PROCESS_INFO processInfo) -{ - if (processInfo->ntdllLoaded && processInfo->kernel32Loaded && processInfo->kernelBaseLoaded) - { - return TRUE; +PPANO_PROCESS_INFO GetProcessInfo(HANDLE ProcessId) { + ULONG id = HandleToUlong(ProcessId); + auto pi = (PPANO_PROCESS_INFO)RtlLookupElementGenericTableAvl(&g_pState->Processes, &id); + if (pi != nullptr) { + return pi; } - return FALSE; + return nullptr; } -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 + PPANO_PROCESS_INFO pi = GetProcessInfo(ProcessId); + if (pi == nullptr) { return; } - KeInitializeApc(pKapc, KeGetCurrentThread(), OriginalApcEnvironment, KernelRoutine, NULL, (PKNORMAL_ROUTINE)(shellcodeAddress), UserMode, allocatedAddressContainingDllFullPath); // Initialize the APC - - 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 + if (pi->Injected || pi->MitigationPolicyBan) { return; } - KeTestAlertThread(UserMode); - - DbgPrint("InjectDllKernelApc exiting"); -} - -NTSTATUS InstallKernelModeApcToInjectDll(HANDLE ProcessId) -{ - PRKAPC pKapc = nullptr; - PETHREAD pThread = nullptr; + UNICODE_STRING loadedImageName{}; + GetFileNameFromPath(FullImageName, &loadedImageName); - 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"); - } + // 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; - return STATUS_SUCCESS; -} + PEPROCESS targetProcess{}; + NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &targetProcess); + if (!NT_SUCCESS(status)) { + return; + } -BOOLEAN Is64BitProcess(PEPROCESS targetProcess) { - UINT64* processAsUint64 = reinterpret_cast(targetProcess); - PVOID* wow64ProcessPtr = reinterpret_cast(processAsUint64 + 0x580 / sizeof(UINT64)); - if (*wow64ProcessPtr == NULL) - { - return TRUE; - } - return FALSE; -} + PROCESS_MITIGATION_POLICY_INFORMATION policyInfo; + policyInfo.Policy = ProcessSignaturePolicy; -VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo) -{ - PAGED_CODE(); - UNREFERENCED_PARAMETER(ImageInfo); + status = QueryProcessMitigationPolicy(targetProcess, &policyInfo); + if (!NT_SUCCESS(status)) { + ObDereferenceObject(targetProcess); + return; + } - PPANO_PROCESS_INFO processInfo = GetProcessInfo(ProcessId); - if (!processInfo || processInfo->Injected) - { - return; - } + if (policyInfo.Data.SignaturePolicy.MicrosoftSignedOnly != 0 || + policyInfo.Data.SignaturePolicy.StoreSignedOnly != 0 || + policyInfo.Data.SignaturePolicy.MitigationOptIn != 0) { + pi->MitigationPolicyBan = TRUE; + ObDereferenceObject(targetProcess); + return; + } - if (PsIsProtectedProcess(PsGetCurrentProcess())) - { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Skipping protected process %llu", (ULONG64)ProcessId); - RemoveProcessInfo(ProcessId); - return; + ObDereferenceObject(targetProcess); + } } - - if (!CanInject(processInfo)) - { + + if (!pi->Wow64Loaded) { + //Check if x86 process and ensure that it will be ready to be injected into 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; + RtlInitUnicodeString(&ntdllLoadImage, L"wow64.dll"); + if (RtlCompareUnicodeString(&ntdllLoadImage, &loadedImageName, TRUE) == 0) { + pi->Wow64Loaded = TRUE; return; } - + } + + if (!pi->Kernel32Loaded) { + // Kernel32 and KernelBase must be loaded for the inject to work 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; + if (RtlCompareUnicodeString(&kernel32LoadImage, &loadedImageName, TRUE) == 0) { + pi->Kernel32Loaded = TRUE; + pi->Kernel32ImageBase = ImageInfo->ImageBase; return; } + } + if (!pi->KernelBaseLoaded) { + // Kernel32 and KernelBase must be loaded for the inject to work 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; + RtlInitUnicodeString(&kernelbaseLoadImage, L"kernelbase.dll"); + if (RtlCompareUnicodeString(&kernelbaseLoadImage, &loadedImageName, TRUE) == 0) { + pi->KernelBaseLoaded = TRUE; return; } } - 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)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] Panoptes: Failed to get process name, status: 0x%X\n", status); - return; + if (pi->Kernel32Loaded && pi->KernelBaseLoaded) { + if (pi->Kernel32ImageBase != nullptr) { + pi->Injected = TRUE; + InstallKernelModeApcToInjectDll(ProcessId, &pi->Kernel32ImageBase, pi->Wow64Loaded); } + } - processInfo->is64Bit = Is64BitProcess(targetProcess); - if (processInfo->is64Bit) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] Panoptes: 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); - } + return; +} + +NTSTATUS IsIgnoredExecutable(ULONG* ProcessId, BOOLEAN* result) { + PEPROCESS targetProcess{}; + NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &targetProcess); + if (!NT_SUCCESS(status)) { + return status; + } - InstallKernelModeApcToInjectDll(ProcessId); - processInfo->Injected = TRUE; + PUNICODE_STRING processPath = NULL; + status = SeLocateProcessImageName(targetProcess, &processPath); + if (!NT_SUCCESS(status)) { + ObDereferenceObject(targetProcess); + return status; } - //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); - //} + 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; + } - return; + 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; } -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) { - 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); - } + if (PsIsProtectedProcess(PsGetCurrentProcess())) { + return; + } - 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); + 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; + 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")); } } - - //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); - //} + ExReleaseFastMutex(&g_pState->ProcessesLock); } else { - RemoveProcessInfo(ProcessId); + ExAcquireFastMutex(&g_pState->ProcessesLock); + RtlDeleteElementGenericTableAvl(&g_pState->Processes, &id); + ExReleaseFastMutex(&g_pState->ProcessesLock); } } -NTSTATUS InitializeKernelCallbacks() -{ +NTSTATUS InitializeKernelCallbacks(PanoptesState* State) { 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); + + g_pState = State; + 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"); + KdPrint((PANOPTES_PREFIX_SUCCESS "Set Process Creation Notify Callbacks\n")); 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..b126b03 100644 --- a/src/driver/src/driver.cpp +++ b/src/driver/src/driver.cpp @@ -1,53 +1,59 @@ -#include "driver_constants.h" +#include "pch.h" #include "callbacks.h" -#include "pano_query.h" #include "trace.h" -#include "pano_filter.h" +#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) -{ +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(); + + // 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 -) -{ +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(); - TraceInit(); Log_DriverEntry(DriverObject, RegistryPath); - NTSTATUS status = FilterInit(&DriverObject); + status = FilterInitialize(DriverObject, &g_State); if (!NT_SUCCESS(status)) { - DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[!] Panoptes: An error occured when attempting to initialized filter\n"); + 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)) //{ - // 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(); + status = InitializeKernelCallbacks(&g_State); 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/filter.cpp b/src/driver/src/filter.cpp new file mode 100644 index 0000000..6d5ff7f --- /dev/null +++ b/src/driver/src/filter.cpp @@ -0,0 +1,340 @@ +#include "filter.h" +#include "trace.h" +#include "state.h" + +PFLT_FILTER FilterHandle{}; + + +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)) { + 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; + } + + 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; + } + + 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) { + 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, fileNameInfo->Name.Buffer); + break; + case FILE_OPENED: + Log_MailSlotOpen(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); + break; + } + + FltReleaseFileNameInformation(fileNameInfo); +} + +void NamedPipeStatus(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)) { + return; + } + + HANDLE sourceProcessId = PsGetCurrentProcessId(); + HANDLE sourceThreadId = PsGetThreadId(Data->Thread); + + switch (Data->IoStatus.Information) + { + case FILE_CREATED: + Log_NamedPipeCreate(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); + break; + case FILE_OPENED: + Log_NamedPipeOpen(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); + break; + } + + FltReleaseFileNameInformation(fileNameInfo); +} + +void FileWriteStatus(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)) { + return; + } + + HANDLE sourceProcessId = PsGetCurrentProcessId(); + HANDLE sourceThreadId = PsGetThreadId(Data->Thread); + ULONG writeLength = Data->Iopb->Parameters.Write.Length; + LARGE_INTEGER fileOffset = Data->Iopb->Parameters.Write.ByteOffset; + + switch (Data->Iopb->MinorFunction) + { + case IRP_MN_NORMAL: + Log_FileWrite(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, fileOffset, writeLength, FALSE); + break; + case IRP_MN_COMPRESSED: + Log_FileWrite(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, fileOffset, writeLength, TRUE); + break; + } + + FltReleaseFileNameInformation(fileNameInfo); +} + +void FileReadStatus(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)) { + return; + } + + HANDLE sourceProcessId = PsGetCurrentProcessId(); + HANDLE sourceThreadId = PsGetThreadId(Data->Thread); + ULONG readLength = Data->Iopb->Parameters.Read.Length; + LARGE_INTEGER fileOffset = Data->Iopb->Parameters.Read.ByteOffset; + + switch (Data->Iopb->MinorFunction) + { + case IRP_MN_NORMAL: + Log_FileRead(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, fileOffset, readLength, FALSE); + break; + case IRP_MN_COMPRESSED: + 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) { + 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); + + 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, fileNameInfo->Name.Buffer, completeIfOplocked); + break; + case FILE_OPENED: + Log_FileOpen(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer, completeIfOplocked); + break; + case FILE_OVERWRITTEN: + Log_FileOverwritten(sourceProcessId, sourceThreadId, fileNameInfo->Name.Buffer); + break; + case FILE_SUPERSEDED: + 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) { + UNREFERENCED_PARAMETER(FltObjects); + UNREFERENCED_PARAMETER(CompletionContext); + UNREFERENCED_PARAMETER(Flags); + + switch (Data->Iopb->MajorFunction) + { + //https://learn.microsoft.com/en-us/previous-versions/windows/drivers/ifs/irp-mj-read + case IRP_MJ_READ: + FileReadStatus(Data); + break; + //https://learn.microsoft.com/en-us/previous-versions/windows/drivers/ifs/irp-mj-create + case IRP_MJ_CREATE: + FileCreationStatus(Data); + break; + //https://learn.microsoft.com/en-us/previous-versions/windows/drivers/ifs/irp-mj-write + case IRP_MJ_WRITE: + 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: + NamedPipeStatus(Data); + break; + //https://learn.microsoft.com/en-us/previous-versions/windows/drivers/ifs/irp-mj-create-mailslot + case IRP_MJ_CREATE_MAILSLOT: + MailSlotStatus(Data); + break; + } + return FLT_POSTOP_FINISHED_PROCESSING; +} + + diff --git a/src/driver/src/inject.cpp b/src/driver/src/inject.cpp index 0dd323a..aa36c8d 100644 --- a/src/driver/src/inject.cpp +++ b/src/driver/src/inject.cpp @@ -1,211 +1,150 @@ -#include "structs.h" #include "inject.h" +#include "utils.h" -typedef NTSTATUS(NTAPI* PLDRLOADDLL)( - PWCHAR PathToFile, - ULONG Flags, - PUNICODE_STRING ModuleFileName, - PHANDLE ModuleHandle - ); +void NTAPI KernelRundown(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); +} -NTSTATUS WriteToTargetProcessMemory(PEPROCESS targetProcess, PVOID TargetAddress, SIZE_T Size, PVOID DataToWrite) +VOID KernelAPCRoutine(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(); - } + PUNICODE_STRING dllToInject = reinterpret_cast(SystemArgument2); + + if (dllToInject == nullptr) { + return; + } + + if (NormalContext == nullptr) { + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); + return; + } + + ULONG processId = HandleToUlong(NormalContext); + + PEPROCESS targetProcess{}; + NTSTATUS status = PsLookupProcessByProcessId(NormalContext, &targetProcess); + if (!NT_SUCCESS(status)) { + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); + return; + } + +#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; + //} +#endif + + PVOID rawImageBaseAddress = *static_cast(SystemArgument1); + PVOID functionAddress = RtlFindExportedRoutineByName(rawImageBaseAddress, "LoadLibraryExW"); + if (functionAddress == nullptr) { + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); + 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); + + 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)); + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); + 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 + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); + 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 + ExFreePool(dllToInject->Buffer); + ExFreePool(dllToInject); + return; } - return status; + 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 AllocateMemoryInUserProcess(PEPROCESS targetProcess, SIZE_T Size, PVOID* AllocatedAddress) +NTSTATUS InstallKernelModeApcToInjectDll(HANDLE ProcessId, PVOID ImageBase, BOOLEAN is64Bit) { - 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; + 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; } - // Dereference the process - ObDereferenceObject(targetProcess); + // 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; + } - return status; -} + // 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\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, 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; + } -//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; -//} + return STATUS_SUCCESS; +} \ No newline at end of file diff --git a/src/driver/src/pano_filter.cpp b/src/driver/src/pano_filter.cpp deleted file mode 100644 index 8dff8ec..0000000 --- a/src/driver/src/pano_filter.cpp +++ /dev/null @@ -1,282 +0,0 @@ -#include "pano_filter.h" -#include "trace.h" - -PFLT_FILTER g_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); - if (!NT_SUCCESS(status)) { - DbgPrint("Error getting file info\n"); - } - - if (fileNameInfo == NULL) { - return Data->Iopb->TargetFileObject->FileName.Buffer; - } - else { - return fileNameInfo->Name.Buffer; - } -} - -void MailSlotStatus( - PFLT_CALLBACK_DATA Data -) -{ - PWCH fileName = GetFileInfo(Data); - HANDLE sourceProcessId = PsGetCurrentProcessId(); - HANDLE sourceThreadId = PsGetThreadId(Data->Thread); - - switch (Data->IoStatus.Information) - { - case FILE_CREATED: - Log_MailSlotCreate(sourceProcessId, sourceThreadId, fileName); - break; - case FILE_OPENED: - Log_MailSlotOpen(sourceProcessId, sourceThreadId, fileName); - break; - } -} - -void NamedPipeStatus( - PFLT_CALLBACK_DATA Data -) -{ - PWCH fileName = GetFileInfo(Data); - HANDLE sourceProcessId = PsGetCurrentProcessId(); - HANDLE sourceThreadId = PsGetThreadId(Data->Thread); - - switch (Data->IoStatus.Information) - { - case FILE_CREATED: - Log_NamedPipeCreate(sourceProcessId, sourceThreadId, fileName); - break; - case FILE_OPENED: - Log_NamedPipeOpen(sourceProcessId, sourceThreadId, fileName); - break; - } -} - -void FileWriteStatus( - PFLT_CALLBACK_DATA Data -) -{ - PWCH fileName = GetFileInfo(Data); - HANDLE sourceProcessId = PsGetCurrentProcessId(); - HANDLE sourceThreadId = PsGetThreadId(Data->Thread); - ULONG writeLength = Data->Iopb->Parameters.Write.Length; - LARGE_INTEGER fileOffset = Data->Iopb->Parameters.Write.ByteOffset; - - switch (Data->Iopb->MinorFunction) - { - case IRP_MN_NORMAL: - Log_FileWrite(sourceProcessId, sourceThreadId, fileName, fileOffset, writeLength, FALSE); - break; - case IRP_MN_COMPRESSED: - Log_FileWrite(sourceProcessId, sourceThreadId, fileName, fileOffset, writeLength, TRUE); - break; - } -} - -void FileReadStatus( - PFLT_CALLBACK_DATA Data -) -{ - PWCH fileName = GetFileInfo(Data); - - HANDLE sourceProcessId = PsGetCurrentProcessId(); - HANDLE sourceThreadId = PsGetThreadId(Data->Thread); - ULONG readLength = Data->Iopb->Parameters.Read.Length; - LARGE_INTEGER fileOffset = Data->Iopb->Parameters.Read.ByteOffset; - - switch (Data->Iopb->MinorFunction) - { - case IRP_MN_NORMAL: - Log_FileRead(sourceProcessId, sourceThreadId, fileName, fileOffset, readLength, FALSE); - break; - case IRP_MN_COMPRESSED: - Log_FileRead(sourceProcessId, sourceThreadId, fileName, fileOffset, readLength, TRUE); - break; - } -} - -void FileCreationStatus( - PFLT_CALLBACK_DATA Data -) -{ - PWCH fileName = GetFileInfo(Data); - - 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; - - 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); - break; - case FILE_OPENED: - Log_FileOpen(sourceProcessId, sourceThreadId, fileName, completeIfOplocked); - break; - case FILE_OVERWRITTEN: - Log_FileOverwritten(sourceProcessId, sourceThreadId, fileName); - break; - case FILE_SUPERSEDED: - Log_FileSuperseded(sourceProcessId, sourceThreadId, fileName); - break; - } -} - -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); - - switch (Data->Iopb->MajorFunction) - { - //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/pano_query.cpp b/src/driver/src/pano_query.cpp deleted file mode 100644 index e34e3aa..0000000 --- a/src/driver/src/pano_query.cpp +++ /dev/null @@ -1,71 +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; -} - - -//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; -//} - - - - diff --git a/src/driver/src/state.cpp b/src/driver/src/state.cpp new file mode 100644 index 0000000..ce814e5 --- /dev/null +++ b/src/driver/src/state.cpp @@ -0,0 +1,40 @@ +#include "pch.h" +#include "state.h" + +NTSTATUS PanoptesState::Init() { + ExInitializeFastMutex(&ProcessesLock); + RtlInitializeGenericTableAvl(&Processes, ProcessCompare, TableAlloc, TableFree, this); + 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, 'stky'); +} + +_Use_decl_annotations_ +VOID PanoptesState::TableFree(_RTL_AVL_TABLE* Table, PVOID Buffer) { + UNREFERENCED_PARAMETER(Table); + 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); + } +} \ No newline at end of file diff --git a/src/driver/src/trace.cpp b/src/driver/src/trace.cpp index bd9efb5..ddee958 100644 --- a/src/driver/src/trace.cpp +++ b/src/driver/src/trace.cpp @@ -7,23 +7,19 @@ 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() { TraceLoggingRegister(g_hPanoProvider); } -void TraceUninit() +void TraceTerminate() { 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 +27,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 +50,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 +67,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 +75,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 +83,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 +100,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 +110,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"), diff --git a/src/driver/src/utils.cpp b/src/driver/src/utils.cpp new file mode 100644 index 0000000..8e54075 --- /dev/null +++ b/src/driver/src/utils.cpp @@ -0,0 +1,53 @@ +#include "utils.h" + +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(PEPROCESS Process, PROCESS_MITIGATION_POLICY_INFORMATION* policyInfo) { + HANDLE hProcess; + + NTSTATUS status = ObOpenObjectByPointer( + Process, + OBJ_KERNEL_HANDLE, + NULL, + 0x1000,//PROCESS_QUERY_LIMITED_INFORMATION, + *PsProcessType, + KernelMode, + &hProcess); + if (!NT_SUCCESS(status)) { + return status; + } + + status = ZwQueryInformationProcess( + hProcess, + ProcessMitigationPolicy, + policyInfo, + sizeof(PROCESS_MITIGATION_POLICY_INFORMATION), + nullptr); + ZwClose(hProcess); + + return status; +} + diff --git a/src/extensibility/PanoptesAMSI/CMakeLists.txt b/src/extensibility/PanoptesAMSI/CMakeLists.txt index d36367f..c562056 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,4 @@ if(MSVC) ) endif() -# Add post-build command to copy DLL to ext directory for Debug configuration -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/Debug/ext" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/ext/$" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/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/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..3d7b573 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,4 @@ if(MSVC) ) endif() -# Add post-build command to copy DLL to ext directory for Debug configuration -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/Debug/ext" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/ext/$" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/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/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..ac6d8d9 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,9 @@ 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_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/bin/Debug/ext" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/ext/$" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${CMAKE_SOURCE_DIR}/bin/Debug/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/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) 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"