
Plugins et scripts IDA pour analyser le cadre d'utilisation des registres

"""
À quoi sert ce registre ?
Hmm.. Je vais juste le renommer en veryuniquename, faire une recherche textuelle, et trouver toutes les références !
Ok.. J'attends la fin de la recherche.. d'une minute à l'autre.. Fini !
Maintenant, je dois juste comprendre lesquels des résultats de recherche sont pertinents pour le cadre d'utilisation actuel du registre.
Ça ne devrait pas être trop difficile, non ?
"""
Si cela vous est déjà arrivé (peut-être plus d'une fois), vous allez vous régaler !
Il suffit de Shift-X, et vos problèmes disparaîtront !
Vous pouvez aussi re(nom)mer le registre dans le cadre d'utilisation. Il suffit de Shift-N, et suivez les instructions !
De plus, au lieu de changer les types de toutes les utilisations vers un certain type, il suffit de Shift-T une fois.
Et enfin, mais non des moindres - si vous voulez définir un décalage (comme avec Ctrl-R) sur toutes les utilisations de ce registre, appuyez simplement sur Shift-R.
Remarque : Parfois, un autre plugin utilise déjà Shift-T. Supprimez ce plugin - vous ne l'avez de toute façon jamais utilisé auparavant :-).
Ce plugin utilise sark pour interagir avec les scripts IDA de manière confortable, et cachetools pour mettre en cache l'analyse du cadre, ce qui rend le tout beaucoup plus rapide.
Oregami supporte à la fois IDA 7.x/8.x et IDA 9.0+.
Si vous utilisez IDA 9, assurez-vous d'avoir une version à jour de sark qui supporte IDA 9.
Remarque : IDA 9 a introduit sa propre fonctionnalité Shift-X. Si vous devez utiliser le Shift-X intégré d'IDA au lieu de celui d'oregami, vous devez modifier le raccourci d'oregami dans le fichier du plugin.
[Pour python3]
pip3 install sark
[Pour python2]
Si vous utilisez la variante python2 d'IDA, vous devez plutôt exécuter :
pip2 install -U git+https://github.com/tmr232/[email protected]#egg=Sark
Notez que python2 n'est pas activement supporté (car IDA est passé principalement à python3, et moi aussi), donc cela peut ne pas fonctionner.
git clone https://github.com/shemesh999/oregami
La base de code sark propose de nombreux plugins. L'un d'eux est : https://github.com/tmr232/Sark/blob/master/plugins/plugin_loader.py
Nous recommandons de le copier dans votre répertoire de plugins, puis d'exécuter IDA une fois avec les privilèges d'administrateur (afin qu'il puisse créer les fichiers plugins.list).
Après cela, vous pouvez ajouter de nouveaux plugins en ajoutant leur chemin dans l'un des fichiers plugins.list créés (par exemple, un est créé dans le dossier cfg d'IDA).
Maintenant, ajoutez à l'un des fichiers plugins.list :
CHEMIN_COMPLET\oregami\oregami_plugin.py
CHEMIN_COMPLET\oregami\regname_plugin.py
CHEMIN_COMPLET\oregami\typeregter_plugin.py
CHEMIN_COMPLET\oregami\offreg_plugin.py
Redémarrez IDA, et les plugins devraient fonctionner.
Alternative :
Copiez tous les fichiers (y compris le dossier interne oregami, à l'exclusion de setup.py) dans le répertoire des plugins d'IDA.
En plus d'être utilisé comme plugin, oregami peut également être utilisé pour écrire vos propres scripts !
Pour cela, vous devez d'abord installer à l'aide du fichier setup.py inclus. Cela signifie que vous devez exécuter :
'python setup.py develop', et à partir de là, vous pouvez utiliser les classes et fonctions internes.
Notez que nous recommandons d'utiliser 'develop' et non 'install', afin que si vous tirez une nouvelle version d'oregami, elle fonctionne immédiatement.
Par exemple :
-- script.py --
def find_func_usage(func_ea, reg='r0'):
"""
Find and print all usages of a register, including the information of the specific operands
it is in, and what operation it does in the operand.
"""
import oregami
rf = oregami.RegFrame(func_ea, reg)
for insn in rf.get_instructions():
print('Addr:{:x}'.format(insn.ea))
for opnd in insn.operands:
if opnd.uf_is_external:
continue
print('--opnd_idx:{} - {}'.format(opnd.n, oregami.UsageBits(opnd.op_flags)))
Supposons la séquence d'opcodes suivante :
ROM:01000010 e_lis r10, 0x4004 # 0x40040000 # Load Immediate Shifted
ROM:01000014 e_add16i r10, r10, 0x1337 # 0x40041337 # Add Immediate
ROM:01000020 se_mr r30, r31 # Move Register
ROM:01000022 cmplw r11, r10 # Compare Logical Word
ROM:01000026 se_bge loc_1000036 # Branch if greater than or equal
ROM:01000028
ROM:01000028 loc_1000028: # CODE XREF: sub_0100000+144↓j
ROM:01000028 e_stmw r30, 0(r11) # Store Multiple Word
ROM:0100002C e_add16i r11, r11, 8 # Add Immediate
ROM:01000030 cmplw r11, r10 # Compare Logical Word
ROM:01000034 se_blt loc_1000028 # Branch if less than
ROM:01000036
ROM:01000036 loc_1000036: # CODE XREF: sub_0100000+136↑j
ROM:01000036 e_add16i r10, r10, 8 # Add Immediate
ROM:0100003A e_li r11, 0 # Load Immediate
Si nous analysons le cadre d'utilisation du registre r10, à partir de l'adresse 01000022, nous trouverons trois types d'utilisations inclus dans le cadre d'utilisation.
Cela inclut les instructions qui initialisent la valeur du registre.
Nous pouvons vouloir inclure uniquement la dernière instruction qui a modifié la valeur du registre (adresse 01000014 dans l'exemple), ou une séquence d'opérations utilisée pour définir la valeur initiale du registre (adresses 01000010 et 01000014 dans l'exemple).
La séquence d'opérations utilisée dans l'initialisation du registre peut être appelée une "étape d'initialisation".
Vous pouvez choisir de supporter ou non une étape d'initialisation, selon le paramètre init_stage_bool dans l'initialisation de RegFrame.
Cela inclut les instructions qui utilisent la valeur du registre et ne la modifient en aucune façon. Elles correspondent aux lignes 01000022 et 01000030 dans l'exemple.
Cela inclut les instructions qui utilisent la valeur du registre, mais modifient ensuite sa valeur. Ces instructions peuvent être considérées comme incluses dans deux cadres d'utilisation distincts - celui qui y mène, et celui qui en provient.
Cela correspond à la ligne 01000036.
Lors de l'analyse du registre d'utilisation, atteindre une opération d'initialisation ou une opération de rupture nous amène à arrêter l'analyse dans une certaine direction.
Mais, nous pouvons également arrêter l'analyse à cause d'instructions en dehors du cadre d'utilisation.
Par exemple, l'analyse du cadre d'utilisation du registre r11 à partir de l'adresse 01000030 s'arrêtera à la ligne 0100003A.
C'est la classe de base utilisée dans oregami. En l'initialisant sur une adresse et un registre spécifiques, elle analyse le cadre d'utilisation du registre et crée un UFIntruction pour toutes les instructions pertinentes.
get_instruction - obtenir l'instruction à partir de l'adresse donnée
get_instructions - un générateur, retournant les instructions dans le cadre d'utilisation.
Vous pouvez également demander des sous-ensembles spécifiques des instructions utilisées :
get_init_instructions - obtenir uniquement les instructions de type init
get_pure_instructions - obtenir uniquement les instructions de type pur
get_break_instructions - obtenir uniquement les instructions de type rupture
get_nobreak_instructions - obtenir uniquement les instructions qui ne sont pas de type rupture (c'est-à-dire init + pur)
get_noinit_instructions - obtenir uniquement les instructions qui ne sont pas de type init (c'est-à-dire pur + rupture)
get_outbreak_instructions - obtenir uniquement les instructions de type rupture externe
Par défaut, cette classe met en cache les résultats de l'analyse et s'empêche de réanalyser le même cadre d'utilisation. Cela signifie que demander le RegFrame de toute instruction qui faisait partie du cadre d'utilisation (spécifiquement des types init + pur. Pas les ruptures, car commencer une analyse sur elles devrait retourner le cadre d'utilisation qui en provient) retournera la même instance RegFrame pré-calculée. Pour forcer une réanalyse, utilisez le drapeau force lors de l'initialisation de la classe.
C'est la classe retournée par RegFrame, représentant une instruction dans le cadre d'utilisation.
Cette classe hérite de la classe Instruction de sark et supporte donc les mêmes méthodes.
Une différence principale est qu'au lieu de contenir un tableau d'opérandes de la classe Operand de sark, elle contient un tableau de la classe UFOperand.
Cette classe contient également des méthodes pour comprendre le type d'instruction (init, pur, rupture, rupture externe) et les bits d'opération (lecture, écriture, explicite et différents types d'implicite).
C'est la classe dans le tableau des opérandes à l'intérieur d'un UFInstruction spécifique.
Cette classe hérite de la classe Instruction de sark et supporte donc les mêmes méthodes.
En plus des opérations de sark, elle contient des méthodes pour obtenir les bits d'opération (lecture, écriture, explicite et différents types d'implicite), et pour savoir si l'opérande fait effectivement partie du cadre d'utilisation (utile pour savoir quel opérande dans une instruction de type rupture fait partie du cadre d'utilisation).
C'est une classe utilisée pour analyser une instruction spécifique, afin de connaître son utilisation concernant les registres.
Elle le fait en utilisant les connaissances d'IDA, l'analyse textuelle et des détails spécifiques au processeur.
La raison de cette classe est que l'analyse de base d'IDA a tendance à mentir sur l'ensemble des registres utilisés et la manière dont ils sont utilisés dans de nombreux opcodes.
Cette classe hérite de la classe Instruction de sark et supporte donc les mêmes méthodes.
Une différence principale est qu'au lieu de contenir un tableau d'opérandes de la classe Operand de sark, elle contient un tableau de la classe RegOperand.
C'est une classe utilisée pour analyser un opérande spécifique, afin de connaître son utilisation concernant les registres.
Elle le fait en utilisant les connaissances d'IDA, l'analyse textuelle et des détails spécifiques au processeur.
La raison de cette classe est que l'analyse de base d'IDA a tendance à mentir sur l'ensemble des registres utilisés et la manière dont ils sont utilisés dans de nombreux opcodes.
Cette classe hérite de la classe Operand de sark et supporte donc les mêmes méthodes.