这是一个C/C++ 支持 x86 x64 与 SSE 实现的特征码加速算法,是一般暴力搜索算法代码的3倍以上的速度【要求至少32纳米的CPU,超过32纳米CPU不能使用SSE加速】。
本文附带两种实现方法,一种暴力搜索,一种SSE加速暴力搜索。
特征码定位格式以OD为标准【BB ?? ?? ?? ?? 8B C3 33 C9 BA ?? ?? ?? ?? E8】默认我将??替换成了'X'方便算法过滤,当然您可以动手修改成您自己想要的格式。
头文件缺少以及其他依赖项请自行理解添加,由于整理仓猝所以缺少东西,希望理解,如有不解,请回帖我会一一解释。
#include <string> #include <algorithm> #include <array> #include <immintrin.h> static constexpr char charhexset[] = "0123456789ABCDEFabcdef"; typedef unsigned int u32; #if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) typedef long long s96; typedef unsigned long long u96; #else typedef int s96; typedef unsigned int u96; #endif static bool StringReplace(std::string& source, const std::string& delimiters, const std::string& dispose = "", const std::size_t offset = 1) { if (source.empty()) { return false; } if (delimiters.empty()) { return true; } for (std::string::size_type pos = source.find(delimiters); pos != std::string::npos; pos = source.find(delimiters)) { if (source.replace(pos, offset, dispose).size()) { continue; } return false; } return true; } static bool Hexadec2xdigit(const std::string& data, std::string& buffer, std::size_t offset) { if (data.empty()) { return false; } for (std::size_t i = 0; i < data.size(); i += offset) { if (std::isxdigit(data[i])) { buffer += static_cast<char>(std::stoul(data.substr(i, offset), nullptr, 16)); } else { buffer += 'X'; } } return true; } static bool Hexadec2xdigitEx(const std::string& data, std::string& buffer, u32 checkxdigit = 0, u32 transform = 1) { if (data.empty()) { return false; } std::string masks(data); { // 去掉 0x 去掉 空格 if (StringReplace(masks, "0x") && StringReplace(masks, " ")) { // 大小写转换 if (masks.end() == (1 == transform ? std::transform(masks.begin(), masks.end(), masks.begin(), [] (unsigned char ch) { return toupper(ch); }) : std::transform(masks.begin(), masks.end(), masks.begin(), [] (unsigned char ch) { return tolower(ch); }))) { // 检查是否是完整的十六进制数 if (checkxdigit) { if (std::string::npos != masks.find_first_not_of(charhexset)) { return false; } } return Hexadec2xdigit(static_cast<const std::string&>(masks), buffer, 2); } } } return false; } static bool SearchPattern(const unsigned char* pos, const std::string& chars) { for (std::string::const_iterator xdigit = chars.cbegin(); xdigit != chars.cend(); ++xdigit, ++pos) { if (*pos != static_cast<const unsigned char>(*xdigit) && // no match 'X' != static_cast<const unsigned char>(*xdigit)) // filter out arbitrary characters { return false; } else { // hit character continue; } } return true; } static bool SearchPattern(const void* start, // start address const void* end, // end address const std::string& keyword, // characteristic code std::size_t index, // take out the serial number void*& address) // return to address { if (keyword.empty()) { return false; } if (start != end && static_cast<const unsigned char*>(end) > static_cast<const unsigned char*>(start) && static_cast<std::size_t>(static_cast<const unsigned char*>(end) - static_cast<const unsigned char*>(start)) > keyword.size()) { std::string chars; { if (Hexadec2xdigitEx(keyword, chars, 0)) { for (auto [pos, i] = std::make_tuple(static_cast<const unsigned char*>(start), static_cast<std::size_t>(0)); pos <= end; ++pos) { if (SearchPattern(pos, chars)) { if (++i != index) { continue; } else { address = const_cast<void*>(reinterpret_cast<const void*>(pos)); } return true; } } } } } return false; } static bool SearchPattern(const u96 start, const u96 end, const std::string& keyword, std::size_t index, void*& address) { return SearchPattern(reinterpret_cast<const void*>(start), reinterpret_cast<const void*>(end), keyword, index, address); } static bool SearchPatternEx(const void* start, const void* end, const std::string& chars, std::size_t index, std::size_t count, void*& address) { for (auto [masks, i, n, pos] = std::make_tuple(std::array<std::size_t, 32>{}, static_cast<std::size_t>(0), static_cast<std::size_t>(0), static_cast<const unsigned char*>(start)); i < count; ++i) { for (std::size_t j = 0; j < 16 && n < chars.size(); ++j, ++n) { if ('X' != static_cast<const char*>(chars.c_str() + i * 16)[j]) { masks[i] |= static_cast<std::size_t>(1) << j; } } for (auto [store, j] = std::make_tuple(_mm_loadu_si128(reinterpret_cast<const __m128i *>(chars.c_str() + i * 16)), static_cast<std::size_t>(0)); pos <= end; _mm_prefetch(reinterpret_cast<const char*>(++pos + 64), _MM_HINT_NTA)) { if (static_cast<std::size_t>(static_cast<std::size_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i *>(pos + i * 16)), store))) & masks[i]) == masks[i]) { if (n < chars.size()) { break; } if (++j != index) { continue; } else { address = const_cast<void*>(reinterpret_cast<const void*>(pos)); } return true; } } } return false; } static bool SearchPatternEx(const void* start, const void* end, const std::string& keyword, std::size_t index, void*& address) { if (keyword.empty()) { return false; } if (start != end && static_cast<const unsigned char*>(end) > static_cast<const unsigned char*>(start) && static_cast<std::size_t>(static_cast<const unsigned char*>(end) - static_cast<const unsigned char*>(start)) > keyword.size()) { std::string chars; { if (Hexadec2xdigitEx(keyword, chars, 0)) { return SearchPatternEx(start, end, chars, index, static_cast<std::size_t>((((chars.size()) + (16 - 1)) & ~(16 - 1)) >> 4), address); } } } return false; } static bool SearchPatternEx(const u96 start, const u96 end, const std::string& keyword, std::size_t index, void*& address) { return SearchPatternEx(reinterpret_cast<const void*>(start), reinterpret_cast<const void*>(end), keyword, index, address); }
卧槽!无奈本人没文化,一句卧槽行天下!
楼主辛苦了,谢谢楼主,楼主好人一生平安!
楼主辛苦了,谢谢楼主,楼主好人一生平安!
楼主辛苦了,谢谢楼主,楼主好人一生平安!
楼主辛苦了,谢谢楼主,楼主好人一生平安!