diff --git a/plugins/apitracing/src/lib/ApiTracing.cpp b/plugins/apitracing/src/lib/ApiTracing.cpp index dea9769f..edb256a1 100644 --- a/plugins/apitracing/src/lib/ApiTracing.cpp +++ b/plugins/apitracing/src/lib/ApiTracing.cpp @@ -76,6 +76,13 @@ namespace ApiTracing throw std::runtime_error("Unknown operating system."); } } + + // Hook process if it's already running + auto runningProcesses = pluginInterface->getRunningProcesses(); + for (const auto& processInformation : *runningProcesses) + { + tracer->traceProcess(processInformation); + } } void ApiTracing::unload() diff --git a/plugins/apitracing/src/lib/CMakeLists.txt b/plugins/apitracing/src/lib/CMakeLists.txt index 850a05a3..613289a6 100644 --- a/plugins/apitracing/src/lib/CMakeLists.txt +++ b/plugins/apitracing/src/lib/CMakeLists.txt @@ -44,7 +44,20 @@ set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE TRUE) target_compile_definitions(apitracing-obj PUBLIC YAML_CPP_SUPPORT) target_link_libraries(apitracing-obj PUBLIC yaml-cpp) +# Setup json-cpp + +FetchContent_Declare( + jsoncpp + GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp.git + GIT_TAG 1.9.5 +) +FetchContent_MakeAvailable(jsoncpp) +set_property(TARGET jsoncpp_static PROPERTY POSITION_INDEPENDENT_CODE TRUE) +target_link_libraries(apitracing-obj PUBLIC jsoncpp_static) + # Add public vmicore headers add_subdirectory("${VMICORE_DIRECTORY_ROOT}/src/include" "${CMAKE_CURRENT_BINARY_DIR}/vmicore-public-headers") target_link_libraries(apitracing-obj PUBLIC vmicore-public-headers) + + diff --git a/plugins/apitracing/src/lib/FunctionHook.cpp b/plugins/apitracing/src/lib/FunctionHook.cpp index 5be009ee..394ffaac 100644 --- a/plugins/apitracing/src/lib/FunctionHook.cpp +++ b/plugins/apitracing/src/lib/FunctionHook.cpp @@ -1,5 +1,6 @@ #include "FunctionHook.h" #include "Filenames.h" +#include "json/writer.h" #include #include #include @@ -56,24 +57,62 @@ namespace ApiTracing } auto extractedParameters = extractor->extractParameters(event, parameterInformation); - logParameterList(extractedParameters); + + Json::Value root; + Json::FastWriter fast; + root["functionName"] = functionName; + auto json = getParameterListAsJson(extractedParameters, root); + std::string unformattedTraces = fast.write(json); + + logger->info("Monitored function parameters", + {{"ProcessDtb", event.getCr3()}, {"ThreadID", event.getGs()}, {"Traces", unformattedTraces}}); } return BpResponse::Continue; } + Json::Value + FunctionHook::getParameterListAsJson(const std::vector& extractedParameters, + Json::Value root) + { + for (const auto& extractedParameter : extractedParameters) + { + Json::Value parameter; + std::visit( + [¶meter = parameter, &extractedParameter = extractedParameter](auto&& arg) + { + parameter["name"] = extractedParameter.name; + parameter["value"] = std::forward>(arg); + }, + extractedParameter.data); + + if (!extractedParameter.backingParameters.empty()) + { + auto backingParameters = getParameterListAsJson(extractedParameter.backingParameters, parameter); + parameter["backingParameters"] = backingParameters; + } + // push_back here + root["parameters"].append(parameter); + } + return root; + } + void FunctionHook::logParameterList(const std::vector& extractedParameters) { for (const auto& extractedParameter : extractedParameters) { std::visit( - [&extractedParameter = extractedParameter, &logger = logger](auto&& arg) + [&functionName = functionName, &extractedParameter = extractedParameter, &logger = logger](auto&& arg) { logger->info("Parameter", - {{"Name", extractedParameter.name}, + {{"Function", functionName}, + {"Name", extractedParameter.name}, {"Value", std::forward>(arg)}}); }, extractedParameter.data); - // TODO: Log backing parameters + if (!extractedParameter.backingParameters.empty()) + { + logParameterList(extractedParameter.backingParameters); + } } } diff --git a/plugins/apitracing/src/lib/FunctionHook.h b/plugins/apitracing/src/lib/FunctionHook.h index 494533fe..98510d73 100644 --- a/plugins/apitracing/src/lib/FunctionHook.h +++ b/plugins/apitracing/src/lib/FunctionHook.h @@ -4,6 +4,7 @@ #include "ConstantDefinitions.h" #include "config/FunctionDefinitions.h" #include "os/Extractor.h" +#include "json/value.h" #include #include #include @@ -37,6 +38,9 @@ namespace ApiTracing VmiCore::Plugin::PluginInterface* pluginInterface; std::unique_ptr logger; + Json::Value getParameterListAsJson(const std::vector& extractedParameters, + Json::Value root); + void logParameterList(const std::vector& extractedParameters); }; } diff --git a/plugins/apitracing/test/FunctionHook_UnitTest.cpp b/plugins/apitracing/test/FunctionHook_UnitTest.cpp index 980e7956..0ca1df98 100644 --- a/plugins/apitracing/test/FunctionHook_UnitTest.cpp +++ b/plugins/apitracing/test/FunctionHook_UnitTest.cpp @@ -23,6 +23,11 @@ namespace ApiTracing std::shared_ptr introspectionAPI = std::make_shared>(); std::shared_ptr extractor = std::make_shared>(); std::shared_ptr interruptEvent = std::make_shared>(); + std::vector extractedParameterInformation{ + {.name = "TestInt0", .data = 0}, + {.name = "TestInt1", + .data = 3, + .backingParameters = {{.name = "TestInt2", .data = 4}, {.name = "TestString1", .data = "A"}}}}; static constexpr VmiCore::addr_t testModuleBase = 0x420; static constexpr VmiCore::addr_t testDtb = 0x1337; @@ -72,8 +77,23 @@ namespace ApiTracing std::make_shared>( std::vector{{.name = "TestParameter"}}), pluginInterface.get()}; + functionHook.hookFunction(testModuleBase, testDtb); + EXPECT_CALL(*extractor, extractParameters).Times(1); + functionHook.hookCallback(*interruptEvent); + } + + TEST_F(FunctionHookTestFixture, hookCallBack_functionHookWithParameters_logsParameters) + { + FunctionHook functionHook{"TestModule", + "TestFunction", + extractor, + introspectionAPI, + std::make_shared>( + std::vector{{.name = "TestParameter"}}), + pluginInterface.get()}; functionHook.hookFunction(testModuleBase, testDtb); + ON_CALL(*extractor, extractParameters).WillByDefault(Return(extractedParameterInformation)); EXPECT_CALL(*extractor, extractParameters).Times(1); functionHook.hookCallback(*interruptEvent);