From 529f9d32c3b068c110f491e041fa1e5b8e778d24 Mon Sep 17 00:00:00 2001 From: Dorian Eikenberg Date: Wed, 28 Feb 2024 11:03:46 +0100 Subject: [PATCH 1/3] Use process memory scan flag --- plugins/inmemoryscanner/src/lib/IYaraInterface.h | 3 +-- plugins/inmemoryscanner/src/lib/Scanner.cpp | 2 +- plugins/inmemoryscanner/src/lib/YaraInterface.cpp | 12 +++++++++--- plugins/inmemoryscanner/src/lib/YaraInterface.h | 3 +-- plugins/inmemoryscanner/test/FakeYaraInterface.cpp | 3 +-- plugins/inmemoryscanner/test/FakeYaraInterface.h | 3 +-- plugins/inmemoryscanner/test/Scanner_unittest.cpp | 4 ++-- .../inmemoryscanner/test/YaraInterface_unittest.cpp | 12 ++++++------ plugins/inmemoryscanner/test/mock_YaraInterface.h | 5 +---- 9 files changed, 23 insertions(+), 24 deletions(-) diff --git a/plugins/inmemoryscanner/src/lib/IYaraInterface.h b/plugins/inmemoryscanner/src/lib/IYaraInterface.h index c3815e37..d458d8ac 100644 --- a/plugins/inmemoryscanner/src/lib/IYaraInterface.h +++ b/plugins/inmemoryscanner/src/lib/IYaraInterface.h @@ -19,8 +19,7 @@ namespace InMemoryScanner public: virtual ~IYaraInterface() = default; - virtual std::vector scanMemory(VmiCore::addr_t regionBase, - std::span mappedRegions) = 0; + virtual std::vector scanMemory(std::span mappedRegions) = 0; protected: IYaraInterface() = default; diff --git a/plugins/inmemoryscanner/src/lib/Scanner.cpp b/plugins/inmemoryscanner/src/lib/Scanner.cpp index c424367a..d13d3047 100644 --- a/plugins/inmemoryscanner/src/lib/Scanner.cpp +++ b/plugins/inmemoryscanner/src/lib/Scanner.cpp @@ -133,7 +133,7 @@ namespace InMemoryScanner // The semaphore protects the yara rules from being accessed more than YR_MAX_THREADS (32 atm.) times in // parallel. semaphore.acquire(); - auto results = yaraInterface->scanMemory(memoryRegionDescriptor.base, mappedRegions); + auto results = yaraInterface->scanMemory(mappedRegions); semaphore.release(); logger->debug("End scanMemory"); diff --git a/plugins/inmemoryscanner/src/lib/YaraInterface.cpp b/plugins/inmemoryscanner/src/lib/YaraInterface.cpp index 1c849b37..05299e6c 100644 --- a/plugins/inmemoryscanner/src/lib/YaraInterface.cpp +++ b/plugins/inmemoryscanner/src/lib/YaraInterface.cpp @@ -64,7 +64,7 @@ namespace InMemoryScanner } } - std::vector YaraInterface::scanMemory(addr_t regionBase, std::span mappedRegions) + std::vector YaraInterface::scanMemory(std::span mappedRegions) { std::vector results; @@ -73,7 +73,7 @@ namespace InMemoryScanner for (const auto& mappedRegion : mappedRegions) { iteratorContext.blocks.emplace_back(mappedRegion.num_pages * pageSizeInBytes, - mappedRegion.guestBaseVA - regionBase, + mappedRegion.guestBaseVA, mappedRegion.mappingBase, &fetch_block_data); } @@ -88,7 +88,13 @@ namespace InMemoryScanner .context = &iteratorContext, .first = &get_first_block, .next = &get_next_block}; #endif - if (auto err = yr_rules_scan_mem_blocks(rules, &iterator, 0, yaraCallback, &results, 0); err != ERROR_SUCCESS) + if (auto err = yr_rules_scan_mem_blocks(rules, + &iterator, + SCAN_FLAGS_PROCESS_MEMORY | SCAN_FLAGS_REPORT_RULES_MATCHING, + yaraCallback, + &results, + 0); + err != ERROR_SUCCESS) { throw YaraException(fmt::format("Error scanning memory. Error code: {}", err)); } diff --git a/plugins/inmemoryscanner/src/lib/YaraInterface.h b/plugins/inmemoryscanner/src/lib/YaraInterface.h index 923d7fb3..2eee6e83 100644 --- a/plugins/inmemoryscanner/src/lib/YaraInterface.h +++ b/plugins/inmemoryscanner/src/lib/YaraInterface.h @@ -36,8 +36,7 @@ namespace InMemoryScanner ~YaraInterface() override; - std::vector scanMemory(VmiCore::addr_t regionBase, - std::span mappedRegions) override; + std::vector scanMemory(std::span mappedRegions) override; private: YR_RULES* rules = nullptr; diff --git a/plugins/inmemoryscanner/test/FakeYaraInterface.cpp b/plugins/inmemoryscanner/test/FakeYaraInterface.cpp index 1b0606e3..eba9aad6 100644 --- a/plugins/inmemoryscanner/test/FakeYaraInterface.cpp +++ b/plugins/inmemoryscanner/test/FakeYaraInterface.cpp @@ -5,8 +5,7 @@ namespace InMemoryScanner { std::vector - FakeYaraInterface::scanMemory([[maybe_unused]] VmiCore::addr_t regionBase, - [[maybe_unused]] std::span mappedRegions) + FakeYaraInterface::scanMemory([[maybe_unused]] std::span mappedRegions) { concurrentThreads++; if (concurrentThreads > YR_MAX_THREADS) diff --git a/plugins/inmemoryscanner/test/FakeYaraInterface.h b/plugins/inmemoryscanner/test/FakeYaraInterface.h index 62d69bc9..e49fd46b 100644 --- a/plugins/inmemoryscanner/test/FakeYaraInterface.h +++ b/plugins/inmemoryscanner/test/FakeYaraInterface.h @@ -7,8 +7,7 @@ namespace InMemoryScanner class FakeYaraInterface : public IYaraInterface { public: - std::vector scanMemory(VmiCore::addr_t regionBase, - std::span mappedRegions) override; + std::vector scanMemory(std::span mappedRegions) override; bool max_threads_exceeded = false; diff --git a/plugins/inmemoryscanner/test/Scanner_unittest.cpp b/plugins/inmemoryscanner/test/Scanner_unittest.cpp index 4c63d56b..4f19233d 100644 --- a/plugins/inmemoryscanner/test/Scanner_unittest.cpp +++ b/plugins/inmemoryscanner/test/Scanner_unittest.cpp @@ -134,7 +134,7 @@ namespace InMemoryScanner auto dumping = std::make_unique>(); dumpingRawPointer = dumping.get(); auto yara = std::make_unique>(); - ON_CALL(*yara, scanMemory(_, _)).WillByDefault(Return(std::vector{})); + ON_CALL(*yara, scanMemory(_)).WillByDefault(Return(std::vector{})); scanner.emplace(pluginInterface.get(), configuration, std::move(yara), std::move(dumping)); }; }; @@ -173,7 +173,7 @@ namespace InMemoryScanner }); auto dumping = std::make_unique(pluginInterface.get(), configuration); auto yara = std::make_unique>(); - ON_CALL(*yara, scanMemory(_, _)).WillByDefault(Return(std::vector{})); + ON_CALL(*yara, scanMemory(_)).WillByDefault(Return(std::vector{})); scanner.emplace(pluginInterface.get(), configuration, std::move(yara), std::move(dumping)); }; diff --git a/plugins/inmemoryscanner/test/YaraInterface_unittest.cpp b/plugins/inmemoryscanner/test/YaraInterface_unittest.cpp index f9539eb1..8aaabc2e 100644 --- a/plugins/inmemoryscanner/test/YaraInterface_unittest.cpp +++ b/plugins/inmemoryscanner/test/YaraInterface_unittest.cpp @@ -67,7 +67,7 @@ namespace InMemoryScanner auto subRegion1 = constructPageWithContent("ABCD"); std::vector memoryRegions{{0x0, subRegion1}}; - auto matches = yaraInterface.scanMemory(memoryRegions.front().guestBaseVA, memoryRegions); + auto matches = yaraInterface.scanMemory(memoryRegions); EXPECT_EQ(matches.size(), 0); } @@ -89,7 +89,7 @@ namespace InMemoryScanner auto subRegion2 = constructPageWithContent("DCBA", false); std::vector memoryRegions{{0x0, subRegion1}, {pageSizeInBytes, subRegion2}}; - auto matches = yaraInterface.scanMemory(memoryRegions.front().guestBaseVA, memoryRegions); + auto matches = yaraInterface.scanMemory(memoryRegions); EXPECT_EQ(matches.size(), 0); } @@ -113,8 +113,8 @@ namespace InMemoryScanner std::vector memoryRegion1{{0x0, subRegion1}}; std::vector memoryRegion2{{4 * pageSizeInBytes, subRegion2}}; - auto matches1 = yaraInterface.scanMemory(memoryRegion1.front().guestBaseVA, memoryRegion1); - auto matches2 = yaraInterface.scanMemory(memoryRegion2.front().guestBaseVA, memoryRegion2); + auto matches1 = yaraInterface.scanMemory(memoryRegion1); + auto matches2 = yaraInterface.scanMemory(memoryRegion2); EXPECT_EQ(matches1.size(), 0); EXPECT_EQ(matches2.size(), 0); @@ -139,7 +139,7 @@ namespace InMemoryScanner std::vector memoryRegions{{0x0, subRegion1}, {4 * pageSizeInBytes, subRegion2}}; Rule expectedMatch{"testRule", "default", {{"$test", 0x0}, {"$test2", 4 * pageSizeInBytes}}}; - auto matches = yaraInterface.scanMemory(memoryRegions.front().guestBaseVA, memoryRegions); + auto matches = yaraInterface.scanMemory(memoryRegions); ASSERT_EQ(matches.size(), 1); EXPECT_THAT(matches, UnorderedElementsAre(expectedMatch)); @@ -178,7 +178,7 @@ namespace InMemoryScanner Rule expectedMatch2{ "testRule2", "default", {{"$test", 8 * pageSizeInBytes}, {"$test2", 8 * pageSizeInBytes + 1}}}; - auto matches = yaraInterface.scanMemory(memoryRegions.front().guestBaseVA, memoryRegions); + auto matches = yaraInterface.scanMemory(memoryRegions); ASSERT_EQ(matches.size(), 2); EXPECT_THAT(matches, UnorderedElementsAre(expectedMatch1, expectedMatch2)); diff --git a/plugins/inmemoryscanner/test/mock_YaraInterface.h b/plugins/inmemoryscanner/test/mock_YaraInterface.h index d9efa3c4..96b7a77d 100644 --- a/plugins/inmemoryscanner/test/mock_YaraInterface.h +++ b/plugins/inmemoryscanner/test/mock_YaraInterface.h @@ -8,9 +8,6 @@ namespace InMemoryScanner class MockYaraInterface : public IYaraInterface { public: - MOCK_METHOD(std::vector, - scanMemory, - (VmiCore::addr_t, std::span), - (override)); + MOCK_METHOD(std::vector, scanMemory, (std::span), (override)); }; } From b70ab318683300f1776f603e5126f00c36f746fc Mon Sep 17 00:00:00 2001 From: Dorian Eikenberg Date: Wed, 28 Feb 2024 11:12:58 +0100 Subject: [PATCH 2/3] Require yara 4.2 --- plugins/inmemoryscanner/src/lib/CMakeLists.txt | 6 +----- plugins/inmemoryscanner/src/lib/YaraInterface.cpp | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/plugins/inmemoryscanner/src/lib/CMakeLists.txt b/plugins/inmemoryscanner/src/lib/CMakeLists.txt index 390d21c1..b2d51202 100644 --- a/plugins/inmemoryscanner/src/lib/CMakeLists.txt +++ b/plugins/inmemoryscanner/src/lib/CMakeLists.txt @@ -14,13 +14,9 @@ target_include_directories(inmemoryscanner-obj INTERFACE $=4) +pkg_check_modules(YARA REQUIRED yara>=4.2) target_link_libraries(inmemoryscanner-obj PUBLIC ${YARA_LINK_LIBRARIES}) -if (${YARA_VERSION} VERSION_GREATER_EQUAL 4.1) - target_compile_definitions(inmemoryscanner-obj PRIVATE LIBYARA_4_1) -endif () - pkg_check_modules(TCLAP REQUIRED tclap>=1.2) include(FetchContent) diff --git a/plugins/inmemoryscanner/src/lib/YaraInterface.cpp b/plugins/inmemoryscanner/src/lib/YaraInterface.cpp index 05299e6c..70403eac 100644 --- a/plugins/inmemoryscanner/src/lib/YaraInterface.cpp +++ b/plugins/inmemoryscanner/src/lib/YaraInterface.cpp @@ -77,16 +77,12 @@ namespace InMemoryScanner mappedRegion.mappingBase, &fetch_block_data); } -#ifdef LIBYARA_4_1 + YR_MEMORY_BLOCK_ITERATOR iterator{.context = &iteratorContext, .first = &get_first_block, .next = &get_next_block, .file_size = nullptr, .last_error = ERROR_SUCCESS}; -#else - YR_MEMORY_BLOCK_ITERATOR iterator{ - .context = &iteratorContext, .first = &get_first_block, .next = &get_next_block}; -#endif if (auto err = yr_rules_scan_mem_blocks(rules, &iterator, From 8e9d29dead86dfe5fb1ad5913b20bed0f887b128 Mon Sep 17 00:00:00 2001 From: Dorian Eikenberg Date: Wed, 28 Feb 2024 11:28:12 +0100 Subject: [PATCH 3/3] Add scan timeout --- plugins/inmemoryscanner/Readme.md | 2 ++ plugins/inmemoryscanner/src/lib/Config.cpp | 6 ++++++ plugins/inmemoryscanner/src/lib/Config.h | 5 +++++ plugins/inmemoryscanner/src/lib/IYaraInterface.h | 5 +++++ plugins/inmemoryscanner/src/lib/InMemory.cpp | 2 +- plugins/inmemoryscanner/src/lib/Scanner.cpp | 7 +++++++ plugins/inmemoryscanner/src/lib/YaraInterface.cpp | 9 +++++++-- plugins/inmemoryscanner/src/lib/YaraInterface.h | 3 ++- .../inmemoryscanner/test/YaraInterface_unittest.cpp | 10 +++++----- plugins/inmemoryscanner/test/mock_Config.h | 1 + 10 files changed, 41 insertions(+), 9 deletions(-) diff --git a/plugins/inmemoryscanner/Readme.md b/plugins/inmemoryscanner/Readme.md index 15b0416f..5f25dd64 100644 --- a/plugins/inmemoryscanner/Readme.md +++ b/plugins/inmemoryscanner/Readme.md @@ -132,6 +132,7 @@ For this, add the following parts to the _VMICore_ config and tweak them to your | `plugins` | Add your plugin here by the exact name of your shared library (e.g. `libinmemoryscanner.so`). All plugin specific config keys should be added as sub-keys under this name. | | `scan_all_regions` | Optional boolean (defaults to `false`). Indicates whether to eagerly scan all memory regions as opposed to ignoring shared memory. | | `signature_file` | Path to the compiled signatures with which to scan the memory regions. | +| `scan_timeout` | Timeout in seconds that determines when libyara will cancel the scan process for a single memory region. | Example configuration: @@ -145,6 +146,7 @@ plugin_system: dump_memory: false scan_all_regions: false output_path: "" + scan_timeout: 10 ignored_processes: - SearchUI.exe - system diff --git a/plugins/inmemoryscanner/src/lib/Config.cpp b/plugins/inmemoryscanner/src/lib/Config.cpp index a236566b..8e257fda 100644 --- a/plugins/inmemoryscanner/src/lib/Config.cpp +++ b/plugins/inmemoryscanner/src/lib/Config.cpp @@ -21,6 +21,7 @@ namespace InMemoryScanner outputPath = rootNode["output_path"].as(); dumpMemory = rootNode["dump_memory"].as(false); scanAllRegions = rootNode["scan_all_regions"].as(false); + scanTimeout = rootNode["scan_timeout"].as(10); auto ignoredProcessesVec = rootNode["ignored_processes"].as>(std::vector()); @@ -43,6 +44,11 @@ namespace InMemoryScanner return outputPath; } + int Config::getScanTimeout() const + { + return scanTimeout; + } + bool Config::isProcessIgnored(const std::string& processName) const { return ignoredProcesses.find(processName) != ignoredProcesses.end(); diff --git a/plugins/inmemoryscanner/src/lib/Config.h b/plugins/inmemoryscanner/src/lib/Config.h index 2c4c79c1..2edbdc19 100644 --- a/plugins/inmemoryscanner/src/lib/Config.h +++ b/plugins/inmemoryscanner/src/lib/Config.h @@ -26,6 +26,8 @@ namespace InMemoryScanner [[nodiscard]] virtual std::filesystem::path getOutputPath() const = 0; + [[nodiscard]] virtual int getScanTimeout() const = 0; + [[nodiscard]] virtual bool isProcessIgnored(const std::string& processName) const = 0; [[nodiscard]] virtual bool isScanAllRegionsActivated() const = 0; @@ -51,6 +53,8 @@ namespace InMemoryScanner [[nodiscard]] std::filesystem::path getOutputPath() const override; + [[nodiscard]] int getScanTimeout() const override; + [[nodiscard]] bool isProcessIgnored(const std::string& processName) const override; [[nodiscard]] bool isScanAllRegionsActivated() const override; @@ -66,5 +70,6 @@ namespace InMemoryScanner std::set ignoredProcesses; bool dumpMemory{}; bool scanAllRegions{}; + int scanTimeout; }; } diff --git a/plugins/inmemoryscanner/src/lib/IYaraInterface.h b/plugins/inmemoryscanner/src/lib/IYaraInterface.h index d458d8ac..81c97a34 100644 --- a/plugins/inmemoryscanner/src/lib/IYaraInterface.h +++ b/plugins/inmemoryscanner/src/lib/IYaraInterface.h @@ -14,6 +14,11 @@ namespace InMemoryScanner using std::runtime_error::runtime_error; }; + class YaraTimeoutException final : public YaraException + { + using YaraException::YaraException; + }; + class IYaraInterface { public: diff --git a/plugins/inmemoryscanner/src/lib/InMemory.cpp b/plugins/inmemoryscanner/src/lib/InMemory.cpp index 2587904f..f68c626f 100644 --- a/plugins/inmemoryscanner/src/lib/InMemory.cpp +++ b/plugins/inmemoryscanner/src/lib/InMemory.cpp @@ -44,7 +44,7 @@ namespace InMemoryScanner { configuration->overrideDumpMemoryFlag(dumpMemoryArgument.getValue()); } - auto yara = std::make_unique(configuration->getSignatureFile()); + auto yara = std::make_unique(configuration->getSignatureFile(), configuration->getScanTimeout()); auto dumping = std::make_unique(pluginInterface, configuration); scanner = std::make_unique(pluginInterface, configuration, std::move(yara), std::move(dumping)); } diff --git a/plugins/inmemoryscanner/src/lib/Scanner.cpp b/plugins/inmemoryscanner/src/lib/Scanner.cpp index d13d3047..86a0e3fb 100644 --- a/plugins/inmemoryscanner/src/lib/Scanner.cpp +++ b/plugins/inmemoryscanner/src/lib/Scanner.cpp @@ -177,6 +177,13 @@ namespace InMemoryScanner *processInformation->fullName, memoryRegionDescriptor); } + catch (const YaraTimeoutException&) + { + logger->warning("Scan timeout reached", + {{"Process", *processInformation->fullName}, + {"BaseVA", memoryRegionDescriptor.base}, + {"Size", memoryRegionDescriptor.size}}); + } catch (const std::exception& exc) { logger->error("Error scanning memory region of process", diff --git a/plugins/inmemoryscanner/src/lib/YaraInterface.cpp b/plugins/inmemoryscanner/src/lib/YaraInterface.cpp index 70403eac..dd4e5774 100644 --- a/plugins/inmemoryscanner/src/lib/YaraInterface.cpp +++ b/plugins/inmemoryscanner/src/lib/YaraInterface.cpp @@ -40,7 +40,7 @@ namespace namespace InMemoryScanner { - YaraInterface::YaraInterface(const std::string& rulesFile) + YaraInterface::YaraInterface(const std::string& rulesFile, int scanTimeout) : scanTimeout(scanTimeout) { auto err = yr_initialize(); if (err != ERROR_SUCCESS) @@ -89,9 +89,14 @@ namespace InMemoryScanner SCAN_FLAGS_PROCESS_MEMORY | SCAN_FLAGS_REPORT_RULES_MATCHING, yaraCallback, &results, - 0); + scanTimeout); err != ERROR_SUCCESS) { + if (err == ERROR_SCAN_TIMEOUT) + { + throw YaraTimeoutException("Scan timeout"); + } + throw YaraException(fmt::format("Error scanning memory. Error code: {}", err)); } diff --git a/plugins/inmemoryscanner/src/lib/YaraInterface.h b/plugins/inmemoryscanner/src/lib/YaraInterface.h index 2eee6e83..4753bd88 100644 --- a/plugins/inmemoryscanner/src/lib/YaraInterface.h +++ b/plugins/inmemoryscanner/src/lib/YaraInterface.h @@ -10,7 +10,7 @@ namespace InMemoryScanner class YaraInterface : public IYaraInterface { public: - explicit YaraInterface(const std::string& rulesFile); + YaraInterface(const std::string& rulesFile, int scanTimeout); YaraInterface(const YaraInterface& other) = delete; @@ -39,6 +39,7 @@ namespace InMemoryScanner std::vector scanMemory(std::span mappedRegions) override; private: + int scanTimeout; YR_RULES* rules = nullptr; static int yaraCallback(YR_SCAN_CONTEXT* context, int message, void* message_data, void* user_data); diff --git a/plugins/inmemoryscanner/test/YaraInterface_unittest.cpp b/plugins/inmemoryscanner/test/YaraInterface_unittest.cpp index 8aaabc2e..f06e41ed 100644 --- a/plugins/inmemoryscanner/test/YaraInterface_unittest.cpp +++ b/plugins/inmemoryscanner/test/YaraInterface_unittest.cpp @@ -63,7 +63,7 @@ namespace InMemoryScanner all of them } )"; - auto yaraInterface = YaraInterface(compileYaraRules(rules)); + auto yaraInterface = YaraInterface(compileYaraRules(rules), 0); auto subRegion1 = constructPageWithContent("ABCD"); std::vector memoryRegions{{0x0, subRegion1}}; @@ -84,7 +84,7 @@ namespace InMemoryScanner all of them } )"; - auto yaraInterface = YaraInterface(compileYaraRules(rules)); + auto yaraInterface = YaraInterface(compileYaraRules(rules), 0); auto subRegion1 = constructPageWithContent("ABCD", true); auto subRegion2 = constructPageWithContent("DCBA", false); std::vector memoryRegions{{0x0, subRegion1}, {pageSizeInBytes, subRegion2}}; @@ -107,7 +107,7 @@ namespace InMemoryScanner all of them } )"; - auto yaraInterface = YaraInterface(compileYaraRules(rules)); + auto yaraInterface = YaraInterface(compileYaraRules(rules), 0); auto subRegion1 = constructPageWithContent("ABCD"); auto subRegion2 = constructPageWithContent("DCBA"); std::vector memoryRegion1{{0x0, subRegion1}}; @@ -133,7 +133,7 @@ namespace InMemoryScanner all of them } )"; - auto yaraInterface = YaraInterface(compileYaraRules(rules)); + auto yaraInterface = YaraInterface(compileYaraRules(rules), 0); auto subRegion1 = constructPageWithContent("ABCD"); auto subRegion2 = constructPageWithContent("DCBA"); std::vector memoryRegions{{0x0, subRegion1}, {4 * pageSizeInBytes, subRegion2}}; @@ -168,7 +168,7 @@ namespace InMemoryScanner all of them } )"; - auto yaraInterface = YaraInterface(compileYaraRules(rules)); + auto yaraInterface = YaraInterface(compileYaraRules(rules), 0); auto subRegion1 = constructPageWithContent("ABCD"); auto subRegion2 = constructPageWithContent("DCBA"); auto subRegion3 = constructPageWithContent("EFGH"); diff --git a/plugins/inmemoryscanner/test/mock_Config.h b/plugins/inmemoryscanner/test/mock_Config.h index 108089fe..c97237f4 100644 --- a/plugins/inmemoryscanner/test/mock_Config.h +++ b/plugins/inmemoryscanner/test/mock_Config.h @@ -11,6 +11,7 @@ namespace InMemoryScanner MOCK_METHOD(void, parseConfiguration, (const VmiCore::Plugin::IPluginConfig&), (override)); MOCK_METHOD(std::filesystem::path, getSignatureFile, (), (const, override)); MOCK_METHOD(std::filesystem::path, getOutputPath, (), (const, override)); + MOCK_METHOD(int, getScanTimeout, (), (const, override)); MOCK_METHOD(bool, isProcessIgnored, (const std::string& processName), (const, override)); MOCK_METHOD(bool, isScanAllRegionsActivated, (), (const, override)); MOCK_METHOD(bool, isDumpingMemoryActivated, (), (const, override));