feat: Added binary pattern search to find view
This commit is contained in:
parent
1d9e8dbda7
commit
0ac8fcd1eb
@ -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);
|
||||
|
@ -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 {};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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" },
|
||||
|
@ -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" },
|
||||
|
@ -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" },
|
||||
|
@ -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" },
|
||||
|
@ -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" },
|
||||
|
@ -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" },
|
||||
|
@ -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" },
|
||||
|
Loading…
x
Reference in New Issue
Block a user