2010-11-25 1 views
9

Je tente de générer un graphique de flux de contrôle des résultats d'assemblage renvoyés via un appel à objdump -d. Actuellement, la meilleure méthode que j'ai trouvée est de placer chaque ligne du résultat dans une liste chaînée, et de séparer l'adresse mémoire, l'opcode, et les opérandes pour chaque ligne. Je les sépare en m'appuyant sur la nature régulière des résultats d'objdump (l'adresse mémoire est du caractère 2 au caractère 7 dans la chaîne qui représente chaque ligne).Construction d'un graphique de flux de contrôle à l'aide des résultats d'Objdump

Une fois cela fait, je démarre l'instruction CFG réelle. Chaque nœud du CFG contient une adresse mémoire de début et de fin, un pointeur vers le bloc de base précédent et des pointeurs vers des blocs de base enfants. Je passe ensuite en revue les résultats d'objdump et compare l'opcode avec un tableau de tous les opcodes de flux de contrôle dans x86_64. Si l'opcode est un flux de contrôle, j'enregistre l'adresse comme la fin du bloc de base, et en fonction de l'opcode soit ajouter deux pointeurs enfants (opcode conditionnel) ou un (appel ou retour).

Je suis en train de mettre en œuvre ceci en C, et il semble que cela fonctionnera mais se sent très ténu. Est-ce que quelqu'un a des suggestions ou quelque chose que je ne prends pas en compte?

Merci d'avoir pris le temps de lire ceci!

modifier:

L'idée est de l'utiliser pour comparer les traces de la pile des appels système générés par DynamoRIO contre le CFG attendu pour un binaire cible, j'espère que la construction comme ceci facilitera cela. Je n'ai pas réutilisé ce qui est disponible parce que A) Je n'y avais pas vraiment réfléchi et B) J'ai besoin d'obtenir le graphique dans une structure de données utilisable pour que je puisse faire des comparaisons de chemin. Je vais jeter un oeil à certains utilitaires sur la page que vous avez alignée, merci de m'indiquer dans la bonne direction. Merci pour vos commentaires, j'apprécie vraiment!

+0

Cela ressemble à une approche globale plausible. Vous voudrez peut-être réfléchir à ce que vous devez faire lorsque vous voyez un appel indirect. En outre, vous dites que les instructions de retour auront un successeur - que serait-ce, exactement, pour une fonction avec plusieurs appelants? Les appels et les retours ne sont souvent pas inclus dans les fichiers CFG (tels que LLVM IR). La "bonne" réponse dépend de ce que vous envisagez de faire avec le CFG après l'avoir construit. –

+0

Approche intéressante. Il existe plusieurs outils (voir http://en.wikipedia.org/wiki/Call_graph) qui peuvent être utilisés pour créer des CFG à partir du code source. Y a-t-il une raison particulière pour laquelle vous voulez adopter cette approche au lieu de réutiliser ce qui est disponible? – Sudhanshu

+0

Comment résolvez-vous les pointeurs de fonction? J'écris aussi un genre de programme similaire mais je me demande toujours comment je vais résoudre les pointeurs de fonction? – prap19

Répondre

3

Vous devez utiliser une IL conçue pour l'analyse de programme. Il y a un peu.

Le projet DynInst (dyninst.org) dispose d'un lifter qui peut convertir des binaires ELF en CFG pour les fonctions/programmes (ou la dernière fois que j'ai regardé). DynInst est écrit en C++.

BinNavi utilise la sortie de l'IDA (le désassembleur interactif) pour créer des graphes de flux IL hors contrôle que l'IDA identifie. Je recommanderais aussi une copie de l'IDA, qui vous permettra de vérifier visuellement les CFG. Une fois que vous avez un programme dans BinNavi, vous pouvez obtenir sa représentation IL d'une fonction/CFG.

Les pointeurs de fonction ne sont que le début de vos problèmes d'identification statique du graphique de flux de contrôle. Les tables de sauts (les genres générés pour les instructions de changement de cas dans certains cas, à la main dans d'autres) jettent aussi une clé. Chaque structure d'analyse de code que je connais traite de ceux dans une approche très heuristique. Ensuite, vous avez des exceptions et la gestion des exceptions, ainsi que du code auto-modifiable.

Bonne chance! Vous obtenez déjà beaucoup d'informations sur la trace de DynamoRIO, je vous suggère d'utiliser autant d'informations que possible à partir de cette trace ...

0

J'ai trouvé votre question puisque j'étais intéressé par la recherche de la même chose. Je ne ai rien trouvé et écrit un script python simple pour cela et jeté sur github: https://github.com/zestrada/playground/blob/master/objdump_cfg/objdump_to_cfg.py

Notez que j'ai quelques heuristiques pour faire face à des fonctions qui ne reviennent jamais, le protecteur gcc pile sur x86 32 bits, etc ... Vous pouvez ou ne pouvez pas vouloir de telles choses.

Je traite les appels indirects de la même manière que vous (vous avez essentiellement un nœud dans le graphique qui est une source lors du retour d'un appel indirect).

Espérons que ceci est utile pour quiconque cherche à faire des analyses similaires avec des restrictions similaires.

Questions connexes