• 注册
  • C/C++ C/C++ 关注:2 内容:43

    文件/进程特征码定位 高性能搜索方法

  • 查看作者
  • 打赏作者
  • 当前位置: 七七博客 > C/C++ > 正文
    • 5
    • C/C++
    • 这是一个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);
      }
      Lv.7
      灌水*2

      卧槽!无奈本人没文化,一句卧槽行天下!

      回复

      楼主辛苦了,谢谢楼主,楼主好人一生平安!

      回复
      Lv.7
      灌水*2

      楼主辛苦了,谢谢楼主,楼主好人一生平安!

      回复
      Lv.11
      灌水*1

      楼主辛苦了,谢谢楼主,楼主好人一生平安!

      回复
      Lv.11

      楼主辛苦了,谢谢楼主,楼主好人一生平安!

      回复

      请登录之后再进行评论

      登录
    • 任务系统
    • 帖子间隔 侧栏位置: