Вы часто ищете сигнатурки в бинарных данных? Пишете ли вы поиск вручную или используете готовые решения? Какой используете формат сигнатур? Однострочный или паттерн + маска? Не важно! Теперь всё, и даже больше, в формате одной header-only библиотеки на современном C++ с набором тестов! Итак, представляю Sig: https://github.com/HoShiMin/Sig Библиотека предоставляет поддержку трёх видов сигнатур: На шаблонах: конструирует код проверки в компайл-тайме. Паттерн + маска ("\x11\x22\x00\x44" + "..?.") Однострочный вариант ("11 22 ? 44") И всё - с огромным простором для кастомизации, который ограничен лишь вашей фантазией: Поддержка побитовых сравнений Набор из готовых компараторов Поддержка кастомных компараторов Пользовательские типы Контейнер для сравнений "один из" Поддержка диапазонов (от..до) Контейнер-повторитель Код (C++): #include <Sig.hpp> int main() { // Поддержка кастомных типов: using RelJmp = Sig::Compound<Sig::Byte<E9>, Sig::Dword<>>; using Syscall = Sig::Compound<Sig::Byte<0x0F, 0x05>>; using Ret = Sig::Compound<Sig::Byte<0xC3>>; const void* found = Sig::find<RelJmp, Syscall, Ret>(buf, size); // Гибкое конструирование шаблонов: found = Sig::find< Sig::Rep<Sig::Char<'r'>, 5>, // 'r' повторяется 5 раз Sig::Set<Sig::Byte<10>, Sig::Dword<0x11223344>>, // Или 10, или 0x11223344 Sig::Range<Sig::Byte, 3, 7>, // 3, 4, 5, 6 или 7 Sig::Byte<>, // Любой байт Sig::Char<'t', 'e', 'x', 't'> // Последовательность >(buf, size); // Кастомизация компараторов в шаблоне с маской: found = Sig::find< Sig::Mask::Eq<'.'>, Sig::Mask::Any<'?'>, Sig::Mask::OneOf<'o'> >(buf, size, "\x11\x22\x00\x44\x55\x66", "..?.o."); // Однострочные сигнатуры: found = Sig::find(buf, size, "11 22 ? 44 ?? aA Bb CC dd"); } Подробный ReadMe и примеры - на страничке проекта на гитхабе.
Однажды окинул взором более-менее распространенные движки, не нашел возможности сделать маску на отдельные биты (кроме наркоманской яры, где этого тоже нет, но таки возможность сделать это через задницу есть) и пришлось делать своё. Ну и как бы опять вижу знакомые технологии: Снова байты-ниблы. Что-то типа "\x11\x22\x00\x44" + "\xFF\x7F\x00\x44" как раз выгодно отличало бы твою библиотеку. Просто пожелание.
Так ведь уже можно. Например, в примере выше есть такой вариант: Код (C++): found = Sig::find< Sig::Mask::Eq<'.'>, Sig::Mask::Any<'?'>, Sig::Mask::OneOf<'o'> >(buf, size, "\x11\x22\x00\x44\x55\x66", "..?.o."); Sig::Mask::OneOf - проверяет, что хотя бы один бит из маски взведён в байте из буфера ((byte & mask) != 0). Sig::Mask::AllOf - что все биты из маски взведены в байте из буфера ((byte & mask) == mask). Т.е., в данном примере будет операция "(byte & 0x55) != 0". Это оно?
Может быть и оно, но тут такая стена текста. Тупо паттерн и маска в шестнадцатиричном виде куда проще и понятней, не надо каждый раз синтаксис мучительно вспоминать.
Добавил. Теперь целых три варианта: - Отдельный метод Sig::bitmask(buf, size, "\x11\x22\x00\x44", "\xFF\x7F\x00\x44", 4). - Опциональный компаратор в Sig::find<..., Sig::Mask::BitMask<'m'>>(buf, size, "\x11\x22\x00\x44", "\xFF\x7F\x00\x44", "mm.?") - Опциональный компаратор в шаблонную генерацию: Sig::find<Sig::Cmp::BitMask<...>>(buf, size);
...и ещё немножко сахара: при включенной поддержке C++20 добавил возможность искать строки: Код (C++): Sig::find<Sig::StrEq<"sample text">, Sig::StrEqNoCase<L"Case-insensitive UTF-16 text">>(buf, size);