
Плагин для IDA Pro для фильтрации функций по шаблонам ассемблера, последовательностям байт, ссылкам на строки/имена и ограничениям по размеру, с поиском на основе правил и расширенным копированием бинарных данных.
FindFunc — это плагин для IDA Pro, предназначенный для поиска функций, содержащих определённый ассемблерный или байтовый паттерн, ссылающихся на заданное имя или строку, или соответствующих другим ограничениям.
FindFunc занял третье место в конкурсе плагинов IDA Pro HexRays 2022 года!

Основная функциональность FindFunc заключается в том, что пользователь задаёт набор «Правил» (ограничений), которым должна удовлетворять функция в IDA Pro. FF находит и отображает все функции, удовлетворяющие ВСЕМ правилам (все правила соединяются логическим «И»). Исключение: правила могут быть «инвертированы» для отрицательного совпадения, что соответствует «И НЕ».
FF будет планировать выполнение правил в оптимальном порядке для минимизации времени обработки.
Обзор возможностей:
Кнопка «Find Functions» очищает предыдущие результаты и начинает новый поиск, «Refine Results» учитывает только результаты предыдущего поиска.
Дополнительная функция FF — копирование двоичного представления инструкций со следующими опциями:
Подробнее см. раздел «Расширенное копирование» ниже. Эта функция отлично дополняет правило «Байтовый паттерн»!
FindFunc — это плагин для IDA Pro на Python, не имеющий внешних зависимостей.
Его можно установить, скачав репозиторий и скопировав файл findfuncmain.py и папку findfunc в каталог плагинов IDA Pro.
Для IDA 9.0+ репозиторий также можно клонировать непосредственно в каталог плагинов.
В любом случае сборка не требуется.
Требования: IDA Pro 8.x (8.3+) с окружением python3. FindFunc предназначен только для архитектуры x86/x64. Протестировано с IDA 8.3 – 9.2, python 3.11 на Windows 10 и 11.
В настоящее время доступно шесть правил. Они отсортированы от самых тяжёлых к самым лёгким по влиянию на производительность. Для больших баз данных рекомендуется сначала сократить количество кандидатов с помощью лёгкого правила, прежде чем выполнять тяжёлое сопоставление, например, с помощью правила «Код». FF автоматически планирует правила оптимальным образом.
Правило для фильтрации функций по наличию заданного фрагмента ассемблерного кода. Это НЕ текстовый поиск по дизассемблированному представлению IDA, а расширенное сопоставление базовой инструкции. Фрагмент может содержать несколько последовательных инструкций, по одной на строку. Поддерживаются фрагменты функций. Помимо буквального ассемблера поддерживаются специальные шаблоны:
Больше примеров:
mov r64, [r32 * 8 + 0x100]
mov r, [r * 8 - 0x100]
mov r64, [r32 * 8 + imm]
pass
mov r, word [eax + r32 * 8 - 0x100]
any r64, r64
push imm
push any
Важно: Будьте осторожны при копировании ассемблера из IDA. IDA вставляет в инструкцию имена локальных переменных и другую информацию, что приводит к неудачному сопоставлению. Также не поддерживаются метки («call sub_123456»).
Обратите внимание, что «Паттерн кода» — самое затратное правило; если присутствуют только правила кода, FF не остаётся ничего, кроме как дизассемблировать всю базу данных. Для очень больших двоичных файлов это может занять до нескольких минут. См. примечания по производительности ниже.
Функция должна содержать заданное непосредственное значение хотя бы один раз в любой позиции. Непосредственное значение — это значение, фиксированное в двоичном представлении инструкции. Примеры инструкций, соответствующих непосредственному значению 0x100:
mov eax, 0x100
mov eax, [0x100]
and al, [eax + ebx*8 + 0x100]
push 0x100
Непосредственные значения можно вставлять из буфера обмена прямо в список правил. Примечание: IDA выполняет расширенное сопоставление по любому размеру и любой позиции непосредственного значения. Если известно, что оно имеет определённую ширину (4 или 8 байт), быстрее может быть байтовый паттерн (но он может давать ложные срабатывания).
Функция должна содержать заданный байтовый паттерн хотя бы один раз. Формат паттерна такой же, как у бинарного поиска IDA, и поддерживает подстановочные символы — идеально подходит для функции расширенного копирования!
Примеры:
11 22 33 44 aa bb cc
11 22 33 ?? ?? bb cc -> ?? может обозначать любой байт
Байтовые паттерны можно вставлять из буфера обмена прямо в список правил. Примечание: Сопоставление паттернов выполняется довольно быстро и хорошо подходит для быстрого сокращения количества совпадений!
Функция должна хотя бы один раз ссылаться на заданную строку.
Строка сопоставляется с помощью модуля fnmatch Python, поэтому поддерживается сопоставление с подстановочными знаками.
Сопоставление выполняется без учёта регистра.
Учитываются строки следующих форматов: [idaapi.STRTYPE_C, idaapi.STRTYPE_C_16] (можно изменить в классе Config).
Примеры:
Примечание: Сопоставление строк выполняется быстро и является хорошим выбором для быстрого сокращения числа кандидатов!
Функция должна хотя бы один раз ссылаться на заданное имя/метку.
Имя/метка сопоставляется с помощью модуля fnmatch Python, поэтому поддерживается сопоставление с подстановочными знаками.
Сопоставление выполняется без учёта регистра.
Примеры:
Примечание: Сопоставление имён выполняется очень быстро и идеально подходит для быстрого сокращения числа кандидатов!
Размер функции должен находиться в заданных пределах: «min <= размер функции <= max». Данные вводятся в виде строки вида «min,max». Размер функции включает все её фрагменты.
Примечание: Сопоставление размера функции выполняется очень быстро и идеально подходит для быстрого сокращения числа кандидатов!
Для удобства использования FF можно управлять следующими сочетаниями клавиш:
Дополнительные возможности GUI:
Часто требуется искать двоичные паттерны ассемблера, но без жёстко заданных адресов и значений (непосредственных), или даже только фактические коды операций инструкции. FindFunc упрощает эту задачу, добавляя три опции копирования в контекстное меню дизассемблера:
Копирует все байты инструкции в виде шестнадцатеричной строки в буфер обмена для использования в правиле «Байтовый паттерн» (или бинарном поиске IDA).
B8 44332211 mov eax,11223344
68 00000001 push 1000000
66:894424 70 mov word ptr ss:[esp+70],ax
будет скопировано как
b8 44 33 22 11 68 00 00 00 01 66 89 44 24 70
Копирует байты инструкции для заданной инструкции, маскируя все непосредственные значения. Пример:
B8 44332211 mov eax,11223344
68 00000001 push 1000000
66:894424 70 mov word ptr ss:[esp+70],ax
будет скопировано как
b8 ?? ?? ?? ?? 68 ?? ?? ?? ?? 66 89 44 24 ??
Копирует все байты инструкции в виде шестнадцатеричной строки в буфер обмена, маскируя любые байты, не являющиеся фактическим кодом операции (включая sib, modrm, но сохраняя префиксы).
B8 44332211 mov eax,11223344
68 00000001 push 1000000
66:894424 70 mov word ptr ss:[esp+70],ax
будет скопировано как
b8 ?? ?? ?? ?? 68 ?? ?? ?? ?? 66 89 ?? ?? ??
Комбинация, сохраняющая код операции и непосредственные значения, но маскирующая, например, mod r/m. Обратите внимание, что это сохраняет коды операций, даже если они требуют определённых регистров, например:
B8 44332211 mov eax,11223344
сохранит код операции B8.
Примечание: Это «наилучшая попытка» с использованием API IDA, поэтому в некоторых случаях она может работать лишь частично. Для 100% корректного решения потребовалась бы специализированная библиотека дизассемблирования x86.
Похожих результатов можно достичь с помощью правил паттернов кода, но этот способ может быть быстрее как для взаимодействия с пользователем, так и для самого поиска.
Копирует выбранный дизассемблер в буфер обмена в том виде, в каком он отображается в IDA.
Кратко о производительности: