
Historiador de firmware solo binario que aprende a localizar funciones en binarios sin procesar extrayendo funciones conocidas de binarios similares, permitiendo una rápida coincidencia de funciones sin desensamblado para el análisis de firmware embebido.
Polypyus aprende a localizar funciones en binarios sin procesar extrayendo funciones conocidas de binarios similares. Por lo tanto, es un historiador de firmware. Polypyus trabaja sin desensamblar estos binarios, lo cual es una ventaja para binarios complejos de desensamblar y donde las herramientas comunes pasan por alto funciones. Además, el enfoque exclusivamente binario lo hace muy rápido y se ejecuta en unos pocos segundos. Sin embargo, este enfoque requiere que los binarios sean de la misma arquitectura y tengan opciones de compilador similares.
Polypyus se integra en el flujo de trabajo de herramientas existentes como Ghidra, IDA, BinDiff y Diaphora. Por ejemplo, puede importar funciones previamente anotadas y aprender de ellas, y también exportar funciones encontradas para importarlas en IDA. Dado que Polypyus utiliza umbrales bastante estrictos, en nuestros experimentos solo encontró coincidencias correctas. Si bien esto genera menos resultados que en las herramientas existentes, es un buen punto de partida para cargar estas coincidencias en IDA para mejorar sus resultados de autoanálisis y luego ejecutar BinDiff sobre ellos.
Al trabajar con binarios de firmware sin procesar, concretamente varias versiones de firmware Bluetooth de Broadcom y Cypress, encontramos que el autoanálisis de IDA a menudo identificaba incorrectamente los inicios de funciones. En IDA Pro 6.8 el autoanálisis es un poco más agresivo, lo que genera más resultados pero también más falsos positivos. En general, IDA Pro 7.2 era más pesimista, pero pasaba por alto muchas funciones. Esto provocó que solo hubiera unas pocas coincidencias de BinDiff entre nuestros firmwares en IDA Pro 6.8 y ninguna coincidencia útil en IDA Pro 7.2.
Curiosamente, BinDiff a menudo fallaba al identificar funciones que, excepto por las ramas, eran idénticas en bytes. Tenga en cuenta que Polypyus busca exactamente estas funciones idénticas en bytes. Suponemos que BinDiff falla en estas funciones debido a un gráfico de llamadas diferente producido por funciones faltantes y falsos positivos. A veces, IDA ya reconocía estas funciones, pero a menudo IDA no las reconocía como código o no las marcaba como función. Tenga en cuenta que Diaphora tiene problemas similares, ya que exporta funciones identificadas por IDA antes de procesarlas posteriormente. A continuación se muestra un punto de referencia sobre el binario de firmware Bluetooth CYW20735B1 que compara varios desensambladores y cómo las fallas del desensamblador generan problemas de diferenciación posteriores.
Además, aunque descubrimos que Amnesia encuentra muchas funciones, también encuentra muchos falsos positivos. Sin embargo, muchas funciones tienen una configuración de marco de pila similar al principio. Por lo tanto, Polypyus tiene una opción para aprender inicios de funciones comunes a partir de los binarios de entrada anotados y aplicar esto a otros binarios para identificar funciones sin emparejar su nombre. Este paso opcional solo se aplica a las regiones en las que no se localizaron funciones previamente; de esta manera, el método de inicios de funciones comunes y la búsqueda principal de funciones no entran en conflicto.
Dado que estos emparejadores trabajan sobre el binario sin procesar, no dependen de un desensamblador. Esto también tiene un inconveniente importante: si hubiera diferentes opciones de compilador o una arquitectura de destino diferente, Polypyus no detectará funciones similares. Además, si bien las coincidencias identificadas son muy confiables, la identificación del inicio de función es un poco menos confiable, así que use esta última con cuidado. A continuación, puede ver que los kits de evaluación de Cypress son muy similares entre sí, pero el firmware de MacBook es muy diferente.
Polypyus crea emparejadores binarios difusos comparando funciones comunes en una colección de binarios de firmware anotados.
Actualmente, se admiten las siguientes anotaciones:
patch.elf de WICED Studio, que es un archivo ELF especial que contiene solo definiciones de símbolos..symdefs tal como lo producen la mayoría de los compiladores ARM..csv con un formato documentado en la carpeta firmware.Estas anotaciones contienen la dirección, el tamaño y el nombre de las funciones conocidas. Cuantas más similitudes tengan los binarios de entrada en la colección de historial, mejor será el rendimiento y los resultados de Polypyus. Dadas varias funciones ligeramente diferentes, Polypyus crea emparejadores muy buenos.
Polypyus requiere Python 3 >= 3.6. Recomendamos el uso de un virtualenv para la siguiente instalación. Clone este repositorio y en esta carpeta ejecute:
pip install .
Después de la instalación, están disponibles los siguientes comandos:
polypyus-guipolypyus-cliPolypyus está disponible a través de una interfaz gráfica y una de línea de comandos.
Tanto la GUI polypyus-gui como la CLI polypyus-cli toman estos argumentos durante la invocación:
--verbose es el nivel de verbosidad. Por defecto, muestra advertencias -v muestra información -vv muestra información de depuración.
--project establece la ubicación del archivo de proyecto. Es una ruta de archivo o ":memory:".
--help Muestra el mensaje de ayuda.
La opción de proyecto le facilita almacenar su trabajo para diferentes contextos en diferentes archivos y también volver a abrirlos.
El flujo de trabajo general de la GUI va del lado izquierdo de la ventana al derecho.
Primero, se agregan binarios al historial. Luego, siguen las anotaciones de símbolos para las entradas en el historial.
Después, se pueden agregar binarios de destino.
Para el emparejamiento, presione Create matchers from history. Una vez creados los emparejadores, se pueden seleccionar destinos individuales o se pueden emparejar todos los destinos seleccionando batch match.
Finalmente, los hallazgos se pueden exportar a un archivo .csv.
A continuación, puede ver un video de demostración donde Polypyus solo toma unos segundos para aprender de dos binarios de entrada, anotarlos, crear emparejadores y aplicar coincidencias a un nuevo binario.
La ventaja de usar la CLI es su capacidad para automatizarse. Por ahora, el formato de salida de la CLI está sujeto a cambios. Sin embargo, aquí hay un ejemplo de su invocación:
polypyus-cli --history firmware/history/20819-A1.bin --annotation firmware/history/20819-A1_patch.elf --history firmware/history/20735B1.bin --annotation firmware/history/20735B1_patch.elf --project test.sqlite
polypyus-cli --target firmware/history/20739B1.bin --project test.sqlite
El primer comando crea test.sqlite como un nuevo archivo de proyecto e importa 20819-A1.bin y 20735B1.bin con sus respectivos archivos patch.elf.
La segunda invocación reutiliza el mismo archivo de proyecto y empareja contra el binario 20739B1.bin.
Para cada comando, el número de --history y --annotation debe coincidir.
Estos dos comandos también podrían combinarse en uno solo agregando el argumento --target al primer comando.
Un artículo que explica los detalles internos se publicó en el Workshop on Binary Analysis Research (BAR) 2021 con el título Polypyus - The Firmware Historian. Algunos detalles más también se incluyen en la presentación final de la tesis de maestría de Jan, que cubre los problemas encontrados al trabajar con enfoques de diferenciación binaria convencionales en modo ARM Thumb2, y cómo funciona el enfoque alternativo solo binario.
Los símbolos filtrados en formato patch.elf o .symdefs solo contienen nombres de funciones y variables globales. Sin embargo, también hay un par de archivos de proyecto .pdom de Eclipse en WICED Studio 6.2 y 6.4. Estos contienen información de tipo adicional. Eclipse los usa internamente para autocompletado, búsqueda de funciones, etc., y podemos utilizarlos en la ingeniería inversa para agregar información de tipos. Dado que los archivos .pdom solo contienen información parcial y en caché, puede ser útil combinar varios de ellos.
En un primer paso, exportamos la información de tipo .pdom a una base de datos SQLite. La exportación lleva un tiempo, pero incluso se puede abortar y continuar más tarde. La exportación funciona de la siguiente manera:
java -jar pdom/export/export.jar -P BCM20739-B0.1462220149391.pdom
La importación PDOM busca nombres de funciones en una base de datos de IDA, los busca en el PDOM para buscar información de tipo y luego aplica esa información de tipo en la base de datos de IDA. Por lo tanto, la base de datos de IDA debe contener nombres de funciones correctos de antemano. En principio, estos se pueden crear con los scripts import_export de Polypyus. Sin embargo, los scripts algo más avanzados que admiten la importación PDOM también pueden manejar secciones patch.elf. Ejecute el importador de la siguiente manera:
T=0x1 (Alt-g).patch.elf (Select file).20739mapb0.h para nombrar registros de hardware (Import map.h).Este script fue probado en IDA Pro 7.4 y 7.5.
Después de algunas pruebas internas, podemos recomendar el siguiente flujo de trabajo al trabajar con IDA Pro y Polypyus:
Alt-g, T=0x1).0x0 con rx, RAM en 0x200000 con rwx (al menos para el firmware Bluetooth).0x4 (o).
En el firmware CYW20735 apunta a 0x3bc+1. Retroceda un byte y cree una función (p)....ahora su base de datos de IDA podría ser algo útil :) Aún hay muchas cosas en las que el desensamblador falla dentro de ARM Thumb2, pero mucho mejor que cualquier cosa que IDA haga por sí solo.
La carpeta firmware contiene varios firmware con y sin símbolos.
Todo en el historial contiene símbolos, todo en targets está sin símbolos.
Para la serie Samsung, el S8 también incluye Note 8 y S8+, etc., y el S10/S20 también incluye todo desde el S10e hasta el Note 20 5G.
La calidad del volcado puede variar, algunos incluyen RAM y otros son solo ROM. Tenemos acceso a la mayoría de los dispositivos en esta lista. Si necesita un volcado con los niveles de parche más recientes e incluyendo RAM, no dude en contactarnos.
Algunos dispositivos mencionados en el artículo no se incluyen aquí, ya que podrían no ser dispositivos solo de investigación, etc. También faltan algunos iPhones y MacBooks, ya que los tenemos como dispositivos solo de investigación pero el volcado original no lo era. Estos dispositivos se agregarán pronto :)
Hay un archivo .editorconfig en este repositorio. Configura el estilo de sangría, el juego de caracteres y los separadores de línea. Siga esta configuración al contribuir, lo que puede ser más fácil si usa un complemento de IDE para .editorconfig.
Para instalar las dependencias de prueba, ejecute
pip install '.[test]'
esto instalará paquetes que solo son necesarios para ejecutar casos de prueba.
Las dependencias de desarrollo proporcionan, por ejemplo, stubs para tipos de paquetes. Para instalarlas, ejecute
pip install '.[development]'
pytest ejecutará todas las pruebas.
El proyecto usa tox para ejecutar localmente las pruebas con diferentes versiones de Python. Tox está configurado para probar con las versiones 3.6, 3.7, 3.8 y 3.9. Para ejecutar tox, instale las dependencias de prueba e instale estas 4 versiones de Python mencionadas. Nuestra forma recomendada de instalar y gestionar varias versiones de Python es pyenv.
Pasos:
pyenv install 3.9.1
pyenv install 3.8.6
pyenv install 3.7.9
pyenv install 3.6.12
pyenv virtualenv 3.9.1 polypyus
penv local polypyus 3.8.6 3.7.9 3.6.12
pip install '.[test]'
pip install '.[development]'
toxPolypyus utiliza GitHub Actions para ejecuciones de prueba automatizadas y algo de linting. Si lo desea, puede ejecutar los pasos de linting localmente con hooks de pre-commit de git.
Cada vez que se crea un nuevo commit, esto activará el linting y mostrará los problemas que impedirían que este código tenga éxito en el paso de linting de GitHub Actions. También formateará los archivos modificados con black.
pip install '.[development]'
pre-commit install
Agradecemos a Anna Stichling por crear el logotipo de Polypyus. También agradecemos a Christian Blichmann y Joxean Koret por sus comentarios.
Polypyus es de código abierto y está licenciado bajo GPLv3.
| Chip | Dispositivo | Fecha de compilación | Símbolos |
|---|
| BCM20703A2 | MacBook/iMac 2016-2017 | Oct 22 2015 | ✔ |
| CYW20719B1 | Placa de evaluación | Jan 17 2017 | ✔ |
| CYW20735B1 | Placa de evaluación | Jan 18 2018 | ✔ |
| CYW20819A1 | Placa de evaluación | May 22 2018 | ✔ |
| Chip | Dispositivo | Fecha de compilación | Símbolos |
|---|
| BCM2046A2 | iMac Late 2009 | 2007? | - |
| BCM2070B0 | MacBook 2011, Thinkpad T420 | Jul 9 2008 | - |
| BCM20702A1 | Dongle USB Asus | Feb (?) 2010 | - |
| BCM4345B0 | iPhone 6 | Jul 15 2013 | - |
| BCM4335C0 | Google Nexus 5 | Dec 11 2012 | - |
| BCM4345B0 | Google Nexus 6P / Galaxy S6 | Oct 23 2014 | - |
| BCM43430A1 | Raspberry Pi 3 y Zero W | Jun 2 2014 | - |
| BCM4345C0 | Raspberry Pi 3+ y 4 | Aug 19 2014 | - |
| BCM4347B0 | Samsung Galaxy S8 series | Jun 3 2016 | - |
| BCM4375B1 | Samsung Galaxy S10/20 series | Apr 13 2018 | - |
| BCM4378B1 | iPhone 11/SE2 | Oct 25 2018 | Strings |