From a955f522bd4ef8fbbaa6f2739f8c8f5e4c57b92f Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sun, 15 Nov 2020 01:42:43 +0100 Subject: [PATCH] Added strings finder --- CMakeLists.txt | 1 + include/views/view_strings.hpp | 36 +++++++++ source/main.cpp | 2 + source/views/view_strings.cpp | 140 +++++++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+) create mode 100644 include/views/view_strings.hpp create mode 100644 source/views/view_strings.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 264bca573..98d512f6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ add_executable(ImHex source/views/view_information.cpp source/views/view_help.cpp source/views/view_tools.cpp + source/views/view_strings.cpp libs/glad/source/glad.c diff --git a/include/views/view_strings.hpp b/include/views/view_strings.hpp new file mode 100644 index 000000000..da2963b3d --- /dev/null +++ b/include/views/view_strings.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "views/view.hpp" + +#include +#include + +namespace hex { + + namespace prv { class Provider; } + + struct FoundString { + std::string string; + u64 offset; + size_t size; + }; + + class ViewStrings : public View { + public: + explicit ViewStrings(prv::Provider* &dataProvider); + ~ViewStrings() override; + + void createView() override; + void createMenu() override; + + private: + prv::Provider* &m_dataProvider; + bool m_windowOpen = true; + bool m_shouldInvalidate = false; + + std::vector m_foundStrings; + int m_minimumLength = 5; + char *m_filter; + }; + +} \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index d1465b7d6..6f7a598af 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -8,6 +8,7 @@ #include "views/view_information.hpp" #include "views/view_help.hpp" #include "views/view_tools.hpp" +#include "views/view_strings.hpp" #include "providers/provider.hpp" @@ -26,6 +27,7 @@ int main() { window.addView(dataProvider, patternData); window.addView(dataProvider); window.addView(dataProvider); + window.addView(dataProvider); window.addView(); window.addView(); diff --git a/source/views/view_strings.cpp b/source/views/view_strings.cpp new file mode 100644 index 000000000..f4676f57c --- /dev/null +++ b/source/views/view_strings.cpp @@ -0,0 +1,140 @@ +#include "views/view_strings.hpp" + +#include "providers/provider.hpp" + +#include + +namespace hex { + + ViewStrings::ViewStrings(prv::Provider* &dataProvider) : View(), m_dataProvider(dataProvider) { + View::subscribeEvent(Events::DataChanged, [this](void*){ + this->m_shouldInvalidate = true; + }); + + this->m_filter = new char[0xFFFF]; + std::memset(this->m_filter, 0x00, 0xFFFF); + } + + ViewStrings::~ViewStrings() { + View::unsubscribeEvent(Events::DataChanged); + delete[] this->m_filter; + } + + void ViewStrings::createView() { + if (!this->m_windowOpen) + return; + + if (this->m_dataProvider == nullptr || !this->m_dataProvider->isReadable()) + return; + + if (this->m_shouldInvalidate) { + this->m_shouldInvalidate = false; + + this->m_foundStrings.clear(); + + + std::vector buffer(1024, 0x00); + u32 foundCharacters = 0; + for (u64 offset = 0; offset < this->m_dataProvider->getSize(); offset += buffer.size()) { + this->m_dataProvider->read(offset, buffer.data(), buffer.size()); + + for (u32 i = 0; i < buffer.size(); i++) { + if (buffer[i] >= 0x20 && buffer[i] <= 0x7E) + foundCharacters++; + else { + if (foundCharacters >= this->m_minimumLength) { + FoundString foundString; + + foundString.offset = offset + i - foundCharacters; + foundString.size = foundCharacters; + foundString.string.reserve(foundCharacters); + foundString.string.resize(foundCharacters); + this->m_dataProvider->read(foundString.offset, foundString.string.data(), foundCharacters); + + this->m_foundStrings.push_back(foundString); + } + + foundCharacters = 0; + } + } + } + } + + if (ImGui::Begin("Strings", &this->m_windowOpen)) { + if (ImGui::InputInt("Minimum length", &this->m_minimumLength, 1, 0)) + this->m_shouldInvalidate = true; + + ImGui::InputText("Filter", this->m_filter, 0xFFFF); + + ImGui::Separator(); + ImGui::NewLine(); + + ImGui::BeginChild("##scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav); + + if (ImGui::BeginTable("##strings", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg)) { + ImGui::TableSetupColumn("Position", 0, -1, ImGui::GetID("position")); + ImGui::TableSetupColumn("Size", 0, -1, ImGui::GetID("size")); + ImGui::TableSetupColumn("String", 0, -1, ImGui::GetID("string")); + + auto sortSpecs = ImGui::TableGetSortSpecs(); + + if (sortSpecs->SpecsDirty) { + std::sort(this->m_foundStrings.begin(), this->m_foundStrings.end(), [this, &sortSpecs](FoundString &left, FoundString&right) -> bool { + if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("position")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left.offset > right.offset; + else + return left.offset < right.offset; + } + else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("size")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left.size > right.size; + else + return left.size < right.size; + } + else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("string")) { + if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending) + return left.string > right.string; + else + return left.string < right.string; + } + + return false; + }); + + sortSpecs->SpecsDirty = false; + } + + ImGui::TableHeadersRow(); + u32 rowCount = 0; + for (auto &foundString : this->m_foundStrings) { + if (strlen(this->m_filter) != 0 && foundString.string.find(this->m_filter) == std::string::npos) + continue; + + ImGui::TableNextRow(ImGuiTableRowFlags_Headers); + ImGui::TableNextColumn(); + ImGui::Text("0x%08lx:0x%08lx", foundString.offset, foundString.offset + foundString.size); + ImGui::TableNextColumn(); + ImGui::Text("%08lx", foundString.size); + ImGui::TableNextColumn(); + ImGui::Text("%s", foundString.string.c_str()); + ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ((rowCount % 2) == 0) ? 0xFF101010 : 0xFF303030); + rowCount++; + } + + ImGui::EndTable(); + } + + ImGui::EndChild(); + } + ImGui::End(); + } + + void ViewStrings::createMenu() { + if (ImGui::BeginMenu("View")) { + ImGui::MenuItem("Strings View", "", &this->m_windowOpen); + ImGui::EndMenu(); + } + } + +} \ No newline at end of file