diff --git a/GleeBug/GleeBug.vcxproj b/GleeBug/GleeBug.vcxproj index 3e3d3e3..c46c4e6 100644 --- a/GleeBug/GleeBug.vcxproj +++ b/GleeBug/GleeBug.vcxproj @@ -165,6 +165,7 @@ + @@ -181,6 +182,7 @@ + diff --git a/GleeBug/GleeBug.vcxproj.filters b/GleeBug/GleeBug.vcxproj.filters index 1557404..bafd179 100644 --- a/GleeBug/GleeBug.vcxproj.filters +++ b/GleeBug/GleeBug.vcxproj.filters @@ -71,6 +71,9 @@ Source Files + + Source Files + @@ -121,5 +124,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/GleeBug/Static.Pattern.cpp b/GleeBug/Static.Pattern.cpp new file mode 100644 index 0000000..d16d9ed --- /dev/null +++ b/GleeBug/Static.Pattern.cpp @@ -0,0 +1,171 @@ +#include "Static.Pattern.h" + +using namespace std; + +namespace GleeBug +{ + string Pattern::FormatPattern(const string & patterntext) + { + string result; + result.reserve(patterntext.length()); + for (auto ch : patterntext) + { + if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f' || ch == '?') + result += ch; + } + return result; + } + + bool Pattern::Transform(const std::string & patterntext, std::vector & pattern) + { + pattern.clear(); + auto formattext = FormatPattern(patterntext); + auto len = formattext.length(); + if (!len) + return false; + + if (len % 2) //not a multiple of 2 + { + formattext += '?'; + len++; + } + + auto hexChToInt = [](char ch) + { + if (ch >= '0' && ch <= '9') + return ch - '0'; + if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 10; + if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + return -1; + }; + + Byte newByte; + auto j = 0; + for (auto ch : formattext) + { + if (ch == '?') //wildcard + { + newByte.nibble[j].wildcard = true; //match anything + } + else //hex + { + newByte.nibble[j].wildcard = false; + newByte.nibble[j].data = hexChToInt(ch) & 0xF; + } + + j++; + if (j == 2) //two nibbles = one byte + { + j = 0; + pattern.push_back(newByte); + } + } + return true; + } + + size_t Pattern::Find(const uint8* data, size_t datasize, const std::vector & pattern) + { + auto MatchByte = [](uint8 byte, const Byte & pbyte) + { + auto matched = 0; + + unsigned char n1 = (byte >> 4) & 0xF; + if (pbyte.nibble[0].wildcard) + matched++; + else if (pbyte.nibble[0].data == n1) + matched++; + + unsigned char n2 = byte & 0xF; + if (pbyte.nibble[1].wildcard) + matched++; + else if (pbyte.nibble[1].data == n2) + matched++; + + return matched == 2; + }; + + auto searchpatternsize = pattern.size(); + for (size_t i = 0, pos = 0; i < datasize; i++) //search for the pattern + { + if (MatchByte(data[i], pattern.at(pos))) //check if our pattern matches the current byte + { + pos++; + if (pos == searchpatternsize) //everything matched + return i - searchpatternsize + 1; + } + else if (pos > 0) //fix by Computer_Angel + { + i -= pos; + pos = 0; //reset current pattern position + } + } + return -1; + } + + size_t Pattern::Find(const uint8* data, size_t datasize, unsigned char* pattern, size_t patternsize) + { + if (patternsize > datasize) + patternsize = datasize; + for (size_t i = 0, pos = 0; i < datasize; i++) + { + if (data[i] == pattern[pos]) + { + pos++; + if (pos == patternsize) + return i - patternsize + 1; + } + else if (pos > 0) + { + i -= pos; + pos = 0; //reset current pattern position + } + } + return -1; + } + + size_t Pattern::Find(const uint8* data, size_t datasize, const char* pattern) + { + string patterntext(pattern); + vector searchpattern; + if (!Transform(patterntext, searchpattern)) + return -1; + return Find(data, datasize, searchpattern); + } + + void Pattern::Write(uint8* data, size_t datasize, const char* pattern) + { + vector writepattern; + string patterntext(pattern); + if (!Transform(patterntext, writepattern)) + return; + + auto writepatternsize = writepattern.size(); + if (writepatternsize > datasize) + writepatternsize = datasize; + + auto WriteByte = [](uint8* byte, const Byte & pbyte) + { + unsigned char n1 = (*byte >> 4) & 0xF; + unsigned char n2 = *byte & 0xF; + if (!pbyte.nibble[0].wildcard) + n1 = pbyte.nibble[0].data; + if (!pbyte.nibble[1].wildcard) + n2 = pbyte.nibble[1].data; + *byte = ((n1 << 4) & 0xF0) | (n2 & 0xF); + }; + + for (size_t i = 0; i < writepatternsize; i++) + WriteByte(&data[i], writepattern.at(i)); + } + + bool Pattern::Snr(uint8* data, size_t datasize, const char* searchpattern, const char* replacepattern) + { + auto found = Find(data, datasize, searchpattern); + if (found == -1) + return false; + Write(data + found, datasize - found, replacepattern); + return true; + } +}; \ No newline at end of file diff --git a/GleeBug/Static.Pattern.h b/GleeBug/Static.Pattern.h new file mode 100644 index 0000000..3ed0482 --- /dev/null +++ b/GleeBug/Static.Pattern.h @@ -0,0 +1,30 @@ +#ifndef STATIC_PATTERN_H +#define STATIC_PATTERN_H + +#include "Static.Global.h" + +namespace GleeBug +{ + class Pattern + { + public: + struct Byte + { + struct Nibble + { + uint8 data; + bool wildcard; + } nibble[2]; + }; + + static std::string FormatPattern(const std::string & pattern); + static bool Transform(const std::string & patterntext, std::vector & pattern); + static size_t Find(const uint8* data, size_t datasize, const std::vector & pattern); + static size_t Find(const uint8* data, size_t datasize, unsigned char* pattern, size_t patternsize); + static size_t Find(const uint8* data, size_t datasize, const char* pattern); + static void Write(uint8* data, size_t datasize, const char* pattern); + static bool Snr(uint8* data, size_t datasize, const char* searchpattern, const char* replacepattern); + }; +}; + +#endif //STATIC_PATTERN_H \ No newline at end of file