
Plugin per IDA Pro per filtrare funzioni in base a pattern assembly, sequenze di byte, riferimenti a stringhe/nomi e vincoli di dimensione, con ricerca basata su regole e copia binaria avanzata.
FindFunc è un plugin per IDA Pro per trovare funzioni che contengono un determinato pattern assembly o di byte, fanno riferimento a un certo nome o stringa, o soddisfano vari altri vincoli.
FindFunc si è classificato terzo nel 2022 HexRays IDA Pro Plugin Contest!

La funzionalità principale di FindFunc è permettere all'utente di specificare un insieme di "Regole" o vincoli che una funzione in IDA Pro deve soddisfare. FF troverà e elencherà tutte le funzioni che soddisfano TUTTE le regole (quindi attualmente tutte le Regole sono in congiunzione AND). Eccezione: le regole possono essere "invertite" per diventare corrispondenze negative. Tali regole quindi corrispondono a "AND NOT".
FF pianificherà le regole in un ordine intelligente per minimizzare il tempo di elaborazione. Panoramica delle funzionalità:
Il pulsante "Find Functions" cancella i risultati esistenti e avvia una nuova ricerca, "Refine Results" considera solo i risultati della ricerca precedente.
Una funzionalità secondaria di FF è l'opzione di copiare la rappresentazione binaria delle istruzioni con le seguenti opzioni:
Vedere la sezione "copia avanzata" di seguito per i dettagli. Questa funzionalità si integra perfettamente con la regola Byte Pattern!
FindFunc è un plugin Python per IDA Pro senza dipendenze da pacchetti esterni. Può essere installato scaricando il repository e copiando il file 'findfuncmain.py' e la cartella 'findfunc' nella directory dei plugin di IDA Pro. Per IDA 9.0+ il repository può anche essere clonato direttamente nella directory dei plugin. In ogni caso non è richiesta alcuna compilazione.
Requisiti: IDA Pro 8.x (8.3+) con ambiente python3. FindFunc è progettato solo per architettura x86/x64. È stato testato con IDA 8.3 - 9.2, python 3.11 su Windows 10 + 11
Attualmente sono disponibili le seguenti sei regole. Sono ordinate qui dalla più pesante alla più leggera in termini di impatto sulle prestazioni. Con database grandi è una buona idea ridurre prima le funzioni candidate con una regola economica, prima di eseguire corrispondenze pesanti tramite es. Regole di codice. FF pianificherà automaticamente le regole in modo intelligente.
Regola per filtrare le funzioni in base al fatto che contengono un dato snippet di codice assembly. NON è una ricerca testuale della rappresentazione testuale del disassembly di IDA, ma esegue una corrispondenza avanzata dell'istruzione sottostante. Lo snippet può contenere molte istruzioni consecutive, una per riga. I chunk delle funzioni sono supportati. Supporta la corrispondenza con wildcard speciali, oltre all'assembly letterale:
altri esempi:
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
Attenzione: Fare attenzione quando si copia assembly da IDA. IDA mescola nomi di variabili locali e altre informazioni nell'istruzione, portando al fallimento della corrispondenza. Inoltre, le etichette non sono supportate ("call sub_123456").
Nota che i Pattern di Codice sono la Regola più costosa, e se sono presenti solo Regole di Codice, FF non ha altra scelta che disassemblare l'intero database. Questo può richiedere fino a diversi minuti per binari molto grandi. Vedi note sulle prestazioni di seguito.
La funzione deve contenere l'immediato dato almeno una volta in qualsiasi posizione. Un valore immediato è un valore fissato nella rappresentazione binaria dell'istruzione. Esempi di istruzioni che corrispondono al valore immediato 0x100:
mov eax, 0x100
mov eax, [0x100]
and al, [eax + ebx*8 + 0x100]
push 0x100
Gli immediati possono essere incollati direttamente dagli appunti nell'elenco delle regole. Nota: IDA esegue una corrispondenza estesa di qualsiasi dimensione e qualsiasi posizione dell'immediato. Se sai che ha una larghezza specifica di 4 o 8 byte, un pattern di byte può essere più veloce (ma può produrre falsi positivi).
La funzione deve contenere il pattern di byte dato almeno una volta. Il pattern è dello stesso formato della ricerca binaria di IDA, e quindi supporta wildcard - la corrispondenza perfetta per la funzione di copia avanzata!
Esempi:
11 22 33 44 aa bb cc
11 22 33 ?? ?? bb cc -> ?? può essere qualsiasi byte
I pattern di byte possono essere incollati direttamente dagli appunti nell'elenco delle regole. Nota: La corrispondenza del pattern è abbastanza veloce e un buon candidato per ridurre rapidamente le corrispondenze!
La funzione deve fare riferimento alla stringa data almeno una volta. La stringa viene confrontata secondo il modulo 'fnmatch' di Python, e quindi supporta corrispondenza con wildcard. La corrispondenza è case-insensitive. Vengono considerate stringhe dei seguenti formati: [idaapi.STRTYPE_C, idaapi.STRTYPE_C_16] (questo può essere modificato nella classe Config).
Esempi:
Nota: La corrispondenza delle stringhe è veloce e una buona scelta per ridurre rapidamente i candidati!
La funzione deve fare riferimento al nome/etichetta dato almeno una volta. Il nome/etichetta viene confrontato secondo il modulo 'fnmatch' di Python, e quindi supporta corrispondenza con wildcard. La corrispondenza è case-insensitive.
Esempi:
Nota: La corrispondenza dei nomi è molto veloce e ideale per ridurre rapidamente i candidati!
La dimensione della funzione deve essere entro il limite dato: "min <= dimensione funzione <= max". I dati vengono inseriti come stringa della forma "min,max". La dimensione di una funzione include tutti i suoi chunk.
Nota: La corrispondenza della dimensione della funzione è molto veloce e ideale per ridurre rapidamente i candidati!
Per facilità d'uso, FF può essere utilizzato tramite le seguenti scorciatoie da tastiera:
Ulteriore utilizzo della GUI
Spesso vogliamo cercare pattern binari di assembly, ma senza indirizzi e valori hardcoded (immediati), o anche solo gli opcode effettivi dell'istruzione. FindFunc semplifica questo aggiungendo tre opzioni di copia al menu contestuale del disassembly:
Copia tutti i byte dell'istruzione come stringa esadecimale negli appunti, per l'uso in una Regola di Pattern di Byte (o nella ricerca binaria di IDA).
B8 44332211 mov eax,11223344
68 00000001 push 1000000
66:894424 70 mov word ptr ss:[esp+70],ax
verrà copiato come
b8 44 33 22 11 68 00 00 00 01 66 89 44 24 70
Copia i byte dell'istruzione per l'istruzione data, mascherando eventuali valori immediati. Esempio:
B8 44332211 mov eax,11223344
68 00000001 push 1000000
66:894424 70 mov word ptr ss:[esp+70],ax
verrà copiato come
b8 ?? ?? ?? ?? 68 ?? ?? ?? ?? 66 89 44 24 ??
Copia tutti i byte dell'istruzione come stringa esadecimale negli appunti, mascherando qualsiasi byte che non sia l'opcode effettivo (inclusi sib, modrm, ma mantenendo i prefissi legacy).
B8 44332211 mov eax,11223344
68 00000001 push 1000000
66:894424 70 mov word ptr ss:[esp+70],ax
verrà copiato come
b8 ?? ?? ?? ?? 68 ?? ?? ?? ?? 66 89 ?? ?? ??
Una combinazione che mantiene opcode e immediati, ma maschera ad esempio mod r/m. Nota che mantiene gli opcode anche se impongono registri specifici, ad esempio
B8 44332211 mov eax,11223344
manterrà l'opcode B8.
Nota: Questo è un "best effort" utilizzando l'API di IDA, quindi potrebbero esserci pochi casi in cui funziona solo parzialmente. Per una soluzione corretta al 100%, dovremmo fornire una libreria di disassemblaggio x86 dedicata.
Risultati simili possono essere ottenuti con le Regole di Pattern di Codice, ma questo potrebbe essere più veloce, sia per l'interazione dell'utente che per la ricerca effettiva.
Copia il disassembly selezionato negli appunti, così come appare in IDA.
Un breve commento sulle prestazioni: