2010-11-25 20 views
9

Estoy intentando construir un gráfico de flujo de control de los resultados del ensamblado que se devuelven mediante una llamada a objdump -d. Actualmente, el mejor método que he encontrado es colocar cada línea del resultado en una lista vinculada, y separar la dirección de memoria, el código de operación y los operandos para cada línea. Los estoy separando confiando en la naturaleza regular de los resultados objdump (la dirección de memoria va desde el carácter 2 hasta el carácter 7 en la cadena que representa cada línea).Elaboración de un gráfico de flujo de control utilizando los resultados de Objdump

Una vez hecho esto, comienzo la instrucción CFG real. Cada nodo en el CFG contiene una dirección de memoria de inicio y finalización, un puntero al bloque básico anterior y apunta a cualquier bloque básico de elementos secundarios. Luego reviso los resultados objdump y comparo el opcode con una matriz de todos los códigos de operación de flujo de control en x86_64. Si el código de operación es uno de flujo de control, registro la dirección como el final del bloque básico y, dependiendo del código de operación, agrego dos punteros secundarios (código de operación condicional) o uno (llamada o devolución).

Estoy en proceso de implementar esto en C, y parece que funcionará, pero se siente muy tenue. ¿Alguien tiene alguna sugerencia o algo que no esté teniendo en cuenta?

¡Gracias por tomarse el tiempo para leer esto!

edición:

La idea es utilizarlo para comparar trazas de la pila de llamadas de sistema generadas por DynamoRIO en contra de la esperada para un CFG binaria objetivo, espero que la construcción de ésta como esto facilitará que. No he reutilizado lo que está disponible porque A) Realmente no lo había pensado y B) Necesito que el gráfico se convierta en una estructura de datos utilizable para que pueda hacer comparaciones de rutas. Voy a echar un vistazo a algunas de las utilidades en la página que alineaste, gracias por apuntarme en la dirección correcta. Gracias por sus comentarios, ¡realmente lo aprecio!

+0

Suena como un enfoque general plausible. Es posible que desee pensar qué hacer cuando vea una llamada indirecta. Además, usted dice que las instrucciones de devolución tendrán un sucesor, ¿qué sucedería exactamente para una función con varias personas que llaman? Las llamadas y devoluciones a menudo no se incluyen en CFG (como LLVM IR). La respuesta "correcta" depende de lo que planeas hacer con el CFG después de haberlo creado. –

+0

Enfoque interesante. Hay varias herramientas (Ver http://en.wikipedia.org/wiki/Call_graph) que se pueden usar para crear CFG a partir del código fuente. ¿Hay alguna razón específica por la que desee adoptar este enfoque en lugar de reutilizar lo que está disponible? – Sudhanshu

+0

¿cómo estás resolviendo punteros a las funciones? También estoy escribiendo un tipo de programa similar, pero aún me pregunto cómo resolveré los indicadores de función. – prap19

Respuesta

3

Debe usar un IL diseñado para el análisis de programas. Hay algunos.

El proyecto DynInst (dyninst.org) tiene un elevador que puede traducir binarios ELF en CFG para funciones/programas (o lo hizo la última vez que lo busqué). DynInst está escrito en C++.

BinNavi utiliza la salida de IDA (el desensamblador interactivo) para crear un diagrama de flujo IL fuera de control identificado por IDA. También recomendaría una copia de IDA, que te permitirá detectar visualmente los CFG visualmente. Una vez que tienes un programa en BinNavi puedes obtener su representación IL de una función/CFG.

Los punteros de función son solo el comienzo de sus problemas para identificar estáticamente el gráfico de flujo de control. Las tablas de salto (las clases generadas para las declaraciones de cambio de mayúsculas en ciertos casos, a mano en otras) también arrojan una llave inglesa. Cada marco de análisis de código que conozco trata de aquellos con un enfoque muy heurístico. Luego tiene excepciones y manejo de excepciones, y también código de auto modificación.

¡Buena suerte! Ya está obteniendo mucha información del seguimiento de DynamoRIO, le sugiero que utilice la mayor cantidad de información posible de ese seguimiento ...

0

Encontré su pregunta porque estaba interesado en buscar lo mismo. he encontrado nada y escribió un simple script en Python para esto y lo tiró en github: https://github.com/zestrada/playground/blob/master/objdump_cfg/objdump_to_cfg.py

Tenga en cuenta que tengo algunas heurísticas para desempeñar las funciones que nunca se devuelven, el protector pila gcc en x86 de 32 bits, etc ... Puede o no querer tales cosas.

Trato las llamadas indirectas de manera similar a como lo hace (básicamente tiene un nodo en el gráfico que es una fuente cuando regresa de un indirecto).

Esperamos que esto sea útil para cualquiera que quiera hacer un análisis similar con restricciones similares.

Cuestiones relacionadas