From 5ccb7a7b9a4eaaffcaf74a5eae64b8374ff60d8b Mon Sep 17 00:00:00 2001 From: WerWolv Date: Wed, 21 Feb 2024 23:17:12 +0100 Subject: [PATCH] feat: Added simple yara data analyzer --- .../source/content/views/view_information.cpp | 2 +- plugins/yara_rules/CMakeLists.txt | 1 + .../yara_rules/include/content/yara_rule.hpp | 2 +- .../content/data_information_sections.cpp | 75 +++++++++++++++++++ .../source/content/views/view_yara.cpp | 2 +- .../yara_rules/source/content/yara_rule.cpp | 4 +- plugins/yara_rules/source/plugin_yara.cpp | 4 +- 7 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 plugins/yara_rules/source/content/data_information_sections.cpp diff --git a/plugins/builtin/source/content/views/view_information.cpp b/plugins/builtin/source/content/views/view_information.cpp index a6557e198..82cf6012a 100644 --- a/plugins/builtin/source/content/views/view_information.cpp +++ b/plugins/builtin/source/content/views/view_information.cpp @@ -188,7 +188,7 @@ namespace hex::plugin::builtin { // Draw the section content ImGui::BeginDisabled(!enabled); - { + if (section->isEnabled()) { if (section->isValid()) section->drawContent(); else if (section->isAnalyzing()) diff --git a/plugins/yara_rules/CMakeLists.txt b/plugins/yara_rules/CMakeLists.txt index b0f5b8f67..fe3e81608 100644 --- a/plugins/yara_rules/CMakeLists.txt +++ b/plugins/yara_rules/CMakeLists.txt @@ -16,6 +16,7 @@ add_imhex_plugin( source/plugin_yara.cpp source/content/yara_rule.cpp + source/content/data_information_sections.cpp source/content/views/view_yara.cpp INCLUDES include diff --git a/plugins/yara_rules/include/content/yara_rule.hpp b/plugins/yara_rules/include/content/yara_rule.hpp index ea81494e5..f0910968d 100644 --- a/plugins/yara_rules/include/content/yara_rule.hpp +++ b/plugins/yara_rules/include/content/yara_rule.hpp @@ -38,7 +38,7 @@ namespace hex::plugin::yara { std::string message; }; - wolv::util::Expected match(prv::Provider *provider, u64 address, size_t size); + wolv::util::Expected match(prv::Provider *provider, Region region); void interrupt(); [[nodiscard]] bool isInterrupted() const; diff --git a/plugins/yara_rules/source/content/data_information_sections.cpp b/plugins/yara_rules/source/content/data_information_sections.cpp new file mode 100644 index 000000000..dd778ceb4 --- /dev/null +++ b/plugins/yara_rules/source/content/data_information_sections.cpp @@ -0,0 +1,75 @@ +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace hex::plugin::yara { + + class InformationYaraRules : public ContentRegistry::DataInformation::InformationSection { + public: + InformationYaraRules() : InformationSection("hex.yara.information_section.yara_rules") { } + ~InformationYaraRules() override = default; + + void process(Task &task, prv::Provider *provider, Region region) override { + const auto &ruleFilePaths = romfs::list("rules"); + task.setMaxValue(ruleFilePaths.size()); + + u32 progress = 0; + for (const auto &ruleFilePath : ruleFilePaths) { + const std::string fileContent = romfs::get(ruleFilePath).data(); + + YaraRule rule(fileContent); + auto result = rule.match(provider, region); + if (result.has_value()) { + m_matches[ruleFilePath.filename().string()] = result.value().matches; + } + + task.update(progress); + progress += 1; + } + } + + void reset() override { + m_matches.clear(); + } + + void drawContent() override { + if (ImGui::BeginTable("information", 2, ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_NoKeepColumnsVisible)) { + ImGui::TableSetupColumn("Left", ImGuiTableColumnFlags_WidthStretch, 0.5F); + ImGui::TableSetupColumn("Right", ImGuiTableColumnFlags_WidthStretch, 0.5F); + + ImGui::TableNextRow(); + + for (auto &[name, matches] : m_matches) { + if (matches.empty()) + continue; + + ImGui::TableNextColumn(); + ImGuiExt::BeginSubWindow(name.c_str()); + { + for (const auto &match : matches) { + ImGui::TextUnformatted(match.identifier.c_str()); + } + } + ImGuiExt::EndSubWindow(); + } + + ImGui::EndTable(); + } + } + + private: + std::map> m_matches; + }; + + void registerDataInformationSections() { + ContentRegistry::DataInformation::addInformationSection(); + } + +} diff --git a/plugins/yara_rules/source/content/views/view_yara.cpp b/plugins/yara_rules/source/content/views/view_yara.cpp index 956678dc6..3a518fdcb 100644 --- a/plugins/yara_rules/source/content/views/view_yara.cpp +++ b/plugins/yara_rules/source/content/views/view_yara.cpp @@ -264,7 +264,7 @@ namespace hex::plugin::yara { rule.interrupt(); }); - auto result = rule.match(provider, provider->getBaseAddress(), provider->getSize()); + auto result = rule.match(provider, { provider->getBaseAddress(), provider->getSize() }); if (!result.has_value()) { TaskManager::doLater([this, error = result.error()] { m_consoleMessages->emplace_back(error.message); diff --git a/plugins/yara_rules/source/content/yara_rule.cpp b/plugins/yara_rules/source/content/yara_rule.cpp index cd4542862..fb8aa5c58 100644 --- a/plugins/yara_rules/source/content/yara_rule.cpp +++ b/plugins/yara_rules/source/content/yara_rule.cpp @@ -73,7 +73,7 @@ namespace hex::plugin::yara { return results.rule->isInterrupted() ? CALLBACK_ABORT : CALLBACK_CONTINUE; } - wolv::util::Expected YaraRule::match(prv::Provider *provider, u64 address, size_t size) { + wolv::util::Expected YaraRule::match(prv::Provider *provider, Region region) { YR_COMPILER *compiler = nullptr; yr_compiler_create(&compiler); ON_SCOPE_EXIT { @@ -126,7 +126,7 @@ namespace hex::plugin::yara { ScanContext context; context.provider = provider; - context.region = { address, size }; + context.region = region; context.currBlock.base = 0; context.currBlock.fetch_data = [](YR_MEMORY_BLOCK *block) -> const u8 * { auto &context = *static_cast(block->context); diff --git a/plugins/yara_rules/source/plugin_yara.cpp b/plugins/yara_rules/source/plugin_yara.cpp index 08ab1ee36..f15269320 100644 --- a/plugins/yara_rules/source/plugin_yara.cpp +++ b/plugins/yara_rules/source/plugin_yara.cpp @@ -10,8 +10,9 @@ using namespace hex; using namespace hex::plugin::yara; -namespace { +namespace hex::plugin::yara { + void registerDataInformationSections(); void registerViews() { ContentRegistry::Views::add(); } @@ -24,4 +25,5 @@ IMHEX_PLUGIN_SETUP("Yara Rules", "WerWolv", "Support for matching Yara rules") { hex::ContentRegistry::Language::addLocalization(nlohmann::json::parse(romfs::get(path).string())); registerViews(); + registerDataInformationSections(); }