1
0
mirror of synced 2025-01-19 01:24:15 +01:00

feat: Added binary pattern search to find view

This commit is contained in:
WerWolv 2022-08-03 10:19:34 +02:00
parent 1d9e8dbda7
commit 0ac8fcd1eb
11 changed files with 136 additions and 8 deletions

View File

@ -326,6 +326,8 @@ namespace hex {
return remainder != 0 ? value + (alignment - remainder) : value;
}
std::optional<u8> hexCharToValue(char c);
bool isProcessElevated();
std::optional<std::string> getEnvironmentVariable(const std::string &env);

View File

@ -280,6 +280,15 @@ namespace hex {
#endif
}
std::optional<u8> hexCharToValue(char c) {
if (std::isdigit(c))
return c - '0';
else if (std::isxdigit(c))
return std::toupper(c) - 'A' + 0x0A;
else
return { };
}
std::string encodeByteString(const std::vector<u8> &bytes) {
std::string result;
@ -370,12 +379,8 @@ namespace hex {
for (u8 i = 0; i < 2; i++) {
byte <<= 4;
if (c() >= '0' && c() <= '9')
byte |= 0x00 + (c() - '0');
else if (c() >= 'A' && c() <= 'F')
byte |= 0x0A + (c() - 'A');
else if (c() >= 'a' && c() <= 'f')
byte |= 0x0A + (c() - 'a');
if (auto hexValue = hexCharToValue(c()); hexValue.has_value())
byte |= hexValue.value();
else
return {};

View File

@ -19,13 +19,18 @@ namespace hex::plugin::builtin {
private:
struct BinaryPattern {
u8 mask, value;
};
struct SearchSettings {
int range = 0;
enum class Mode : int {
Strings,
Sequence,
Regex
Regex,
BinaryPattern
} mode = Mode::Strings;
struct Strings {
@ -49,6 +54,11 @@ namespace hex::plugin::builtin {
struct Regex {
std::string pattern;
} regex;
struct BinaryPattern {
std::string input;
std::vector<ViewFind::BinaryPattern> pattern;
} binaryPattern;
} m_searchSettings, m_decodeSettings;
std::map<prv::Provider*, std::vector<Region>> m_foundRegions, m_sortedRegions;
@ -60,6 +70,9 @@ namespace hex::plugin::builtin {
static std::vector<Region> searchStrings(Task &&task, prv::Provider *provider, Region searchRegion, SearchSettings::Strings settings);
static std::vector<Region> searchSequence(Task &&task, prv::Provider *provider, Region searchRegion, SearchSettings::Bytes settings);
static std::vector<Region> searchRegex(Task &&task, prv::Provider *provider, Region searchRegion, SearchSettings::Regex settings);
static std::vector<Region> searchBinaryPattern(Task &&task, prv::Provider *provider, Region searchRegion, SearchSettings::BinaryPattern settings);
static std::vector<BinaryPattern> parseBinaryPatternString(std::string string);
void runSearch();
std::string decodeValue(prv::Provider *provider, Region region);

View File

@ -100,6 +100,63 @@ namespace hex::plugin::builtin {
});
}
std::vector<ViewFind::BinaryPattern> ViewFind::parseBinaryPatternString(std::string string) {
std::vector<BinaryPattern> result;
if (string.length() < 2)
return { };
bool inString = false;
while (string.length() > 0) {
BinaryPattern pattern = { 0, 0 };
if (string.starts_with("\"")) {
inString = !inString;
string = string.substr(1);
continue;
} else if (inString) {
pattern = { 0xFF, u8(string.front()) };
string = string.substr(1);
} else if (string.starts_with("??")) {
pattern = { 0x00, 0x00 };
string = string.substr(2);
} else if ((std::isxdigit(string.front()) || string.front() == '?') && string.length() >= 2) {
const auto hex = string.substr(0, 2);
for (const auto &c : hex) {
pattern.mask <<= 4;
pattern.value <<= 4;
if (std::isxdigit(c)) {
pattern.mask |= 0x0F;
if (auto hexValue = hex::hexCharToValue(c); hexValue.has_value())
pattern.value |= hexValue.value();
else
return { };
} else if (c != '?') {
return { };
}
}
string = string.substr(2);
} else if (std::isspace(string.front())) {
string = string.substr(1);
continue;
} else {
return { };
}
result.push_back(pattern);
}
if (inString)
return { };
return result;
}
std::vector<Region> ViewFind::searchStrings(Task &&task, prv::Provider *provider, hex::Region searchRegion, SearchSettings::Strings settings) {
std::vector<Region> results;
@ -196,6 +253,34 @@ namespace hex::plugin::builtin {
return result;
}
std::vector<Region> ViewFind::searchBinaryPattern(Task &&task, prv::Provider *provider, hex::Region searchRegion, SearchSettings::BinaryPattern settings) {
std::vector<Region> results;
auto reader = prv::BufferedReader(provider);
reader.seek(searchRegion.getStartAddress());
reader.setEndAddress(searchRegion.getEndAddress());
u32 matchedBytes = 0;
u64 address = searchRegion.getStartAddress();
const size_t patternSize = settings.pattern.size();
for (u8 byte : reader) {
if ((byte & settings.pattern[matchedBytes].mask) == settings.pattern[matchedBytes].value) {
matchedBytes++;
if (matchedBytes == settings.pattern.size()) {
results.push_back(Region { address - (patternSize - 1), patternSize });
task.update(address);
matchedBytes = 0;
}
} else {
matchedBytes = 0;
}
address++;
}
return results;
}
void ViewFind::runSearch() {
Region searchRegion = [this]{
if (this->m_searchSettings.range == 0 || !ImHexApi::HexEditor::isSelectionValid()) {
@ -222,7 +307,10 @@ namespace hex::plugin::builtin {
case Regex:
this->m_foundRegions[provider] = searchRegex(std::move(task), provider, searchRegion, settings.regex);
break;
}
case BinaryPattern:
this->m_foundRegions[provider] = searchBinaryPattern(std::move(task), provider, searchRegion, settings.binaryPattern);
break;
}
this->m_sortedRegions = this->m_foundRegions;
this->m_searchRunning = false;
@ -259,6 +347,7 @@ namespace hex::plugin::builtin {
break;
case Sequence:
case Regex:
case BinaryPattern:
result = hex::encodeByteString(bytes);
break;
}
@ -361,6 +450,18 @@ namespace hex::plugin::builtin {
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("hex.builtin.view.find.binary_pattern"_lang)) {
auto &settings = this->m_searchSettings.binaryPattern;
mode = SearchSettings::Mode::BinaryPattern;
ImGui::InputText("hex.builtin.view.find.binary_pattern"_lang, settings.input);
settings.pattern = parseBinaryPatternString(settings.input);
this->m_settingsValid = !settings.pattern.empty();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}

View File

@ -402,6 +402,7 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.find.strings.line_feeds", "Line Feeds" },
{ "hex.builtin.view.find.sequences", "Sequenzen" },
{ "hex.builtin.view.find.regex", "Regex" },
{ "hex.builtin.view.find.binary_pattern", "Binärpattern" },
{ "hex.builtin.view.find.search", "Suchen" },
{ "hex.builtin.view.find.context.copy", "Wert Kopieren" },
{ "hex.builtin.view.find.context.copy_demangle", "Demangled Wert Kopieren" },

View File

@ -406,6 +406,7 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.find.strings.line_feeds", "Line Feeds" },
{ "hex.builtin.view.find.sequences", "Sequences" },
{ "hex.builtin.view.find.regex", "Regex" },
{ "hex.builtin.view.find.binary_pattern", "Binary Pattern" },
{ "hex.builtin.view.find.search", "Search" },
{ "hex.builtin.view.find.context.copy", "Copy Value" },
{ "hex.builtin.view.find.context.copy_demangle", "Copy Demangled Value" },

View File

@ -405,6 +405,7 @@ namespace hex::plugin::builtin {
// { "hex.builtin.view.find.strings.line_feeds", "Line Feeds" },
// { "hex.builtin.view.find.sequences", "Sequences" },
// { "hex.builtin.view.find.regex", "Regex" },
// { "hex.builtin.view.find.binary_pattern", "Binary Pattern" },
// { "hex.builtin.view.find.search", "Search" },
// { "hex.builtin.view.find.context.copy", "Copy Value" },
// { "hex.builtin.view.find.context.copy_demangle", "Copy Demangled Value" },

View File

@ -406,6 +406,7 @@ namespace hex::plugin::builtin {
// { "hex.builtin.view.find.strings.line_feeds", "Line Feeds" },
// { "hex.builtin.view.find.sequences", "Sequences" },
// { "hex.builtin.view.find.regex", "Regex" },
// { "hex.builtin.view.find.binary_pattern", "Binary Pattern" },
// { "hex.builtin.view.find.search", "Search" },
// { "hex.builtin.view.find.context.copy", "Copy Value" },
// { "hex.builtin.view.find.context.copy_demangle", "Copy Demangled Value" },

View File

@ -403,6 +403,7 @@ namespace hex::plugin::builtin {
// { "hex.builtin.view.find.strings.line_feeds", "Line Feeds" },
// { "hex.builtin.view.find.sequences", "Sequences" },
// { "hex.builtin.view.find.regex", "Regex" },
// { "hex.builtin.view.find.binary_pattern", "Binary Pattern" },
// { "hex.builtin.view.find.search", "Search" },
// { "hex.builtin.view.find.context.copy", "Copy Value" },
// { "hex.builtin.view.find.context.copy_demangle", "Copy Demangled Value" },

View File

@ -406,6 +406,7 @@ namespace hex::plugin::builtin {
// { "hex.builtin.view.find.strings.line_feeds", "Line Feeds" },
// { "hex.builtin.view.find.sequences", "Sequences" },
// { "hex.builtin.view.find.regex", "Regex" },
// { "hex.builtin.view.find.binary_pattern", "Binary Pattern" },
// { "hex.builtin.view.find.search", "Search" },
// { "hex.builtin.view.find.context.copy", "Copy Value" },
// { "hex.builtin.view.find.context.copy_demangle", "Copy Demangled Value" },

View File

@ -404,6 +404,7 @@ namespace hex::plugin::builtin {
// { "hex.builtin.view.find.strings.line_feeds", "Line Feeds" },
// { "hex.builtin.view.find.sequences", "Sequences" },
// { "hex.builtin.view.find.regex", "Regex" },
// { "hex.builtin.view.find.binary_pattern", "Binary Pattern" },
// { "hex.builtin.view.find.search", "Search" },
// { "hex.builtin.view.find.context.copy", "Copy Value" },
// { "hex.builtin.view.find.context.copy_demangle", "Copy Demangled Value" },