
FindFunc は、特定のアセンブリまたはバイトパターンを含む、特定の名前や文字列を参照する、またはその他のさまざまな制約に準拠するコード関数を検索するための IDA Pro プラグインです。
FindFunc は、2022 HexRays IDA Pro Plugin Contest で第3位を獲得しました。

FindFunc の主な機能は、ユーザーが IDA Pro のコード関数が満たす必要がある「ルール」または制約のセットを指定できることです。FF は、すべてのルールを満たすすべての関数を検索してリストします(つまり、現在すべてのルールは AND 結合されています)。例外: ルールは「反転」して否定マッチにすることができます。そのようなルールは「AND NOT」に準拠します。
FF は、処理時間を最小限に抑えるために、ルールをスマートな順序でスケジュールします。 機能概要:
「Find Functions」ボタンは既存の結果をクリアして新規検索を開始し、「Refine Results」は前回の検索結果のみを考慮します。
FF の補助機能として、以下のオプションで命令のバイナリ表現をコピーする機能があります。
詳細は下記の「高度なコピー」セクションを参照してください。 この機能は Byte Pattern ルールと相性が良いです。
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 でテスト済みです。
現在、以下の6つのルールが利用可能です。パフォーマンスへの影響が大きい順に並べられています。 大規模なデータベースでは、まず安価なルールで候補関数を絞り込んでから、コードルールなどの重いマッチングを行うことをお勧めします。FF は自動的にルールをスマートな順序でスケジュールします。
指定されたアセンブリコードスニペットを含む関数をフィルタリングするルールです。 これは IDA のテキスト逆アセンブル表現のテキスト検索ではなく、基になる命令の高度なマッチングを実行します。 スニペットには、連続した複数の命令を1行に1つずつ含めることができます。関数チャンクに対応しています。 リテラルアセンブリに加えて、特別なワイルドカードマッチングをサポートします。
その他の例:
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 はデータベース全体を逆アセンブルする以外に選択肢がありません。非常に大きなバイナリでは数分かかる可能性があります。パフォーマンスに関する注意事項を参照してください。
関数が指定された即値を少なくとも1回、任意の位置で含む必要があります。 即値とは、命令のバイナリ表現に固定された値です。 即値 0x100 にマッチする命令の例:
mov eax, 0x100
mov eax, [0x100]
and al, [eax + ebx*8 + 0x100]
push 0x100
即値はクリップボードから直接ルールリストに貼り付けることができます。 注: IDA は任意のサイズと任意の位置の即値を広範にマッチングします。4バイトまたは8バイトの特定の幅であることがわかっている場合、バイトパターンの方が高速になる可能性があります(ただし、誤検出が発生する可能性があります)。
関数が指定されたバイトパターンを少なくとも1回含む必要があります。 パターンは IDA のバイナリ検索と同じ形式であり、ワイルドカードをサポートします。これは高度なコピー機能に最適です。
例:
11 22 33 44 aa bb cc
11 22 33 ?? ?? bb cc -> ?? は任意のバイト
バイトパターンはクリップボードから直接ルールリストに貼り付けることができます。 注: パターンマッチングは非常に高速で、迅速に候補を絞り込むのに適しています。
関数が指定された文字列を少なくとも1回参照する必要があります。 文字列は Python の 'fnmatch' モジュールに従ってマッチングされ、ワイルドカードのようなマッチングをサポートします。 マッチングは大文字と小文字を区別しません。 以下の形式の文字列が考慮されます: [idaapi.STRTYPE_C, idaapi.STRTYPE_C_16] (Config クラスで変更可能)。
例:
注: 文字列マッチングは高速で、迅速に候補を絞り込むのに適しています。
関数が指定された名前/ラベルを少なくとも1回参照する必要があります。 名前/ラベルは Python の 'fnmatch' モジュールに従ってマッチングされ、ワイルドカードのようなマッチングをサポートします。 マッチングは大文字と小文字を区別しません。
例:
注: 名前マッチングは非常に高速で、迅速に候補を絞り込むのに最適です。
関数のサイズが指定された範囲内である必要があります: "min <= functionsize <= max"。 データは "min,max" の形式の文字列として入力されます。 関数のサイズにはすべてのチャンクが含まれます。
注: 関数サイズのマッチングは非常に高速で、迅速に候補を絞り込むのに最適です。
使いやすさのために、FF は以下のキーボードショートカットで使用できます。
その他の GUI 操作
アセンブリのバイナリパターンを検索したいが、ハードコードされたアドレスや値(即値)を除外したり、命令の実際のオペコードのみを検索したいことがよくあります。FindFunc は、逆アセンブリのポップアップメニューに3つのコピーオプションを追加することでこれを容易にします。
すべての命令バイトを16進文字列としてクリップボードにコピーします。Byte-Pattern-Rule(または 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 ??
すべての命令バイトを16進文字列としてクリップボードにコピーしますが、実際のオペコードではないバイト(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 を保持します。
注: これは IDA の API を使用した「ベストエフォート」であり、一部のケースでは部分的にしか機能しない可能性があります。 100% 正しいソリューションを実現するには、専用の x86 逆アセンブルライブラリを同梱する必要があります。 同様の結果は Code Pattern Rules でも得られますが、ユーザーの操作と実際の検索の両方で、こちらがより高速な場合があります。
選択した逆アセンブルを、IDA に表示されている通りにクリップボードにコピーします。
パフォーマンスに関する簡単な説明: