Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Lors de la rĂ©union 0x0A DC7831 DEF CON Nijni Novgorod Le 16 fĂ©vrier, nous avons prĂ©sentĂ© un rapport sur les principes de base de l'Ă©mulation de code binaire et notre dĂ©veloppement — un Ă©mulateur de plateformes matĂ©rielles. Kopycat.

Dans cet article, nous décrirons le lancement du firmware d'un dispositif dans l'émulateur, démontrerons l'interaction avec le débogueur et réaliserons une petite analyse dynamique du firmware.

Contexte

Il y a longtemps, dans une galaxie lointaine, trĂšs lointaine

Il y a quelques années, notre laboratoire a eu besoin d'étudier le firmware d'un dispositif. Le firmware était compressé et décompressé par le bootloader. Il le faisait de maniÚre assez complexe, réorganisant plusieurs fois les données en mémoire. De plus, le firmware interagissait activement avec le matériel. Et tout cela sur un noyau MIPS.

Les Ă©mulateurs existants ne nous convenaient pas pour des raisons Ă©videntes, et nous voulions quand mĂȘme exĂ©cuter le code. Nous avons donc dĂ©cidĂ© de crĂ©er notre propre Ă©mulateur qui ferait le minimum et permettrait de dĂ©compresser le firmware principal. Nous avons essayĂ© — ça a marchĂ©. Nous avons rĂ©flĂ©chi, et si nous ajoutions du matĂ©riel pour exĂ©cuter Ă©galement le firmware principal. Cela n'a pas Ă©tĂ© trop douloureux — et ça a aussi marchĂ©. Nous avons encore rĂ©flĂ©chi et dĂ©cidĂ© de crĂ©er un Ă©mulateur complet.

Au final, un émulateur de systÚmes de calcul a été créé. Kopycat.

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat
Pourquoi Kopycat ?

Il s'agit d'un jeu de mots.

  1. copycat (anglais, nom [ˈkɒpÉȘkĂŠt]) — imitateur, copieur
  2. cat (anglais, nom [ˈkĂŠt]) — chat, le chat — animal de compagnie prĂ©fĂ©rĂ© d'un des crĂ©ateurs du projet
  3. La lettre « K » vient du langage de programmation Kotlin

Kopycat

Lors de la création de l'émulateur, des objectifs bien définis ont été fixés :

  • capacitĂ© Ă  crĂ©er rapidement un nouveau matĂ©riel, un module, un cƓur de processeur ;
  • capacitĂ© Ă  assembler un dispositif virtuel Ă  partir de diffĂ©rents modules ;
  • capacitĂ© Ă  charger dans la mĂ©moire de l'appareil virtuel n'importe quelle donnĂ©e binaire (firmware) ;
  • capacitĂ© Ă  travailler avec des snapshots (captures d'Ă©tat du systĂšme) ;
  • capacitĂ© d'interaction avec l'Ă©mulateur via un dĂ©bogueur intĂ©grĂ© ;
  • un langage de dĂ©veloppement moderne et agrĂ©able.

Au final, Kotlin a Ă©tĂ© choisi pour les implĂ©mentations, une architecture de bus (c'est lorsque les modules sont reliĂ©s entre eux via des bus de donnĂ©es virtuels), JSON — comme format de description de l'appareil, et GDB RSP — comme protocole d'interaction avec le dĂ©bogueur.

Le dĂ©veloppement a lieu depuis un peu plus de deux ans et se poursuit activement. Au cours de cette pĂ©riode, des cƓurs de processeur MIPS, x86, V850ES, ARM et PowerPC ont Ă©tĂ© rĂ©alisĂ©s.

Le projet grandit, et il est temps de le présenter au grand public. Une description détaillée du projet sera faite plus tard, mais concentrons-nous maintenant sur l'utilisation de Kopycat.

Pour les plus impatients – la version promotionnelle de l'Ă©mulateur peut ĂȘtre tĂ©lĂ©chargĂ©e Ă  le lien.

Rhinocéros dans l'émulateur

Rappelons qu'un dispositif de test dénommé « Rhinocéros » a été créé pour la conférence SMARTRHINO-2018 afin d'apprendre des compétences en reverse engineering. Le processus d'analyse statique du firmware a été décrit dans cet article.

Nous allons maintenant essayer d'ajouter un peu de « dynamique » et lancer le firmware dans l'émulateur.

Nous aurons besoin de :
1) Java 1.8
2) Python et le module Jep pour utiliser Python Ă  l'intĂ©rieur de l'Ă©mulateur. L'assemblage WHL du module Jep sous Windows peut ĂȘtre tĂ©lĂ©chargĂ© ici.

Pour Windows :
1) com0com
2) PuTTY

Pour Linux :
1) socat

Comme client GDB, vous pouvez utiliser Eclipse, IDA Pro ou radare2.

Comment cela fonctionne ?

Pour exécuter le firmware dans l'émulateur, il est nécessaire de « construire » un dispositif virtuel qui représente un équivalent du dispositif réel.

Le dispositif rĂ©el (« rhinocĂ©ros ») peut ĂȘtre illustrĂ© par le schĂ©ma structurel :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

L'Ă©mulateur possĂšde une structure modulaire et le dispositif virtuel final peut ĂȘtre dĂ©crit dans un fichier JSON.

JSON de 105 lignes

{
  "top": true,

  // Le nom du plugin doit ĂȘtre le mĂȘme que le nom du fichier (ou le chemin complet depuis le dĂ©but de la bibliothĂšque)
  "plugin": "rhino",

  // RĂ©pertoire oĂč le plugin place
  "library": "user",

  // ParamĂštres du plugin (paramĂštres du constructeur si version jar-plugin)
  "params": [
    { "name": "tty_dbg", "type": "String"},
    { "name": "tty_bt", "type": "String"},
    { "name": "firmware", "type": "String", "default": "NUL"}
  ],

  // Ports externes du plugin
  "ports": [  ],

  // Bus internes du plugin
  "buses": [
    { "name": "mem", "size": "BUS30" },
    { "name": "nand", "size": "4" },
    { "name": "gpio", "size": "BUS32" }
  ],

  // Composants internes du plugin
  "modules": [
    {
      "name": "u1_stm32",
      "plugin": "STM32F042",
      "library": "mcu",
      "params": {
        "firmware:String": "params.firmware"
      }
    },
    {
      "name": "usart_debug",
      "plugin": "UartSerialTerminal",
      "library": "terminals",
      "params": {
        "tty": "params.tty_dbg"
      }
    },
    {
      "name": "term_bt",
      "plugin": "UartSerialTerminal",
      "library": "terminals",
      "params": {
        "tty": "params.tty_bt"
      }
    },
    {
      "name": "bluetooth",
      "plugin": "BT",
      "library": "mcu"
    },

    { "name": "led_0",  "plugin": "LED", "library": "mcu" },
    { "name": "led_1",  "plugin": "LED", "library": "mcu" },
    { "name": "led_2",  "plugin": "LED", "library": "mcu" },
    { "name": "led_3",  "plugin": "LED", "library": "mcu" },
    { "name": "led_4",  "plugin": "LED", "library": "mcu" },
    { "name": "led_5",  "plugin": "LED", "library": "mcu" },
    { "name": "led_6",  "plugin": "LED", "library": "mcu" },
    { "name": "led_7",  "plugin": "LED", "library": "mcu" },
    { "name": "led_8",  "plugin": "LED", "library": "mcu" },
    { "name": "led_9",  "plugin": "LED", "library": "mcu" },
    { "name": "led_10", "plugin": "LED", "library": "mcu" },
    { "name": "led_11", "plugin": "LED", "library": "mcu" },
    { "name": "led_12", "plugin": "LED", "library": "mcu" },
    { "name": "led_13", "plugin": "LED", "library": "mcu" },
    { "name": "led_14", "plugin": "LED", "library": "mcu" },
    { "name": "led_15", "plugin": "LED", "library": "mcu" }
  ],

  // Connexion du plugin entre les composants
  "connections": [
    [ "u1_stm32.ports.usart1_m", "usart_debug.ports.term_s"],
    [ "u1_stm32.ports.usart1_s", "usart_debug.ports.term_m"],

    [ "u1_stm32.ports.usart2_m", "bluetooth.ports.usart_m"],
    [ "u1_stm32.ports.usart2_s", "bluetooth.ports.usart_s"],

    [ "bluetooth.ports.bt_s", "term_bt.ports.term_m"],
    [ "bluetooth.ports.bt_m", "term_bt.ports.term_s"],

    [ "led_0.ports.pin",  "u1_stm32.buses.pin_output_a", "0x00"],
    [ "led_1.ports.pin",  "u1_stm32.buses.pin_output_a", "0x01"],
    [ "led_2.ports.pin",  "u1_stm32.buses.pin_output_a", "0x02"],
    [ "led_3.ports.pin",  "u1_stm32.buses.pin_output_a", "0x03"],
    [ "led_4.ports.pin",  "u1_stm32.buses.pin_output_a", "0x04"],
    [ "led_5.ports.pin",  "u1_stm32.buses.pin_output_a", "0x05"],
    [ "led_6.ports.pin",  "u1_stm32.buses.pin_output_a", "0x06"],
    [ "led_7.ports.pin",  "u1_stm32.buses.pin_output_a", "0x07"],
    [ "led_8.ports.pin",  "u1_stm32.buses.pin_output_a", "0x08"],
    [ "led_9.ports.pin",  "u1_stm32.buses.pin_output_a", "0x09"],
    [ "led_10.ports.pin", "u1_stm32.buses.pin_output_a", "0x0A"],
    [ "led_11.ports.pin", "u1_stm32.buses.pin_output_a", "0x0B"],
    [ "led_12.ports.pin", "u1_stm32.buses.pin_output_a", "0x0C"],
    [ "led_13.ports.pin", "u1_stm32.buses.pin_output_a", "0x0D"],
    [ "led_14.ports.pin", "u1_stm32.buses.pin_output_a", "0x0E"],
    [ "led_15.ports.pin", "u1_stm32.buses.pin_output_a", "0x0F"]
  ]
}

Veuillez prĂȘter attention au paramĂštre firmware dans la section params — c'est le nom du fichier que vous pouvez tĂ©lĂ©charger sur l'appareil virtuel en tant que firmware.

Un appareil virtuel et son interaction avec le systĂšme d'exploitation principal peuvent ĂȘtre reprĂ©sentĂ©s par le schĂ©ma suivant :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

L'instance actuelle de l'Ă©mulateur permet l'interaction avec les ports COM du systĂšme d'exploitation principal (UART de dĂ©bogage et UART pour le module Bluetooth). Cela peut ĂȘtre des ports rĂ©els auxquels des appareils sont connectĂ©s ou des ports COM virtuels (c'est exactement ce dont ont besoin com0com / socat).

Pour interagir avec l'émulateur depuis l'extérieur, il existe actuellement deux principales méthodes :

  • le protocole GDB RSP (les outils qui prennent en charge ce protocole — Eclipse / IDA / radare2) ;
  • l'interface de ligne de commande interne de l'Ă©mulateur (Argparse ou Python).

Ports COM virtuels

Pour interagir avec le UART de l'appareil virtuel sur la machine locale via un terminal, il est nĂ©cessaire de crĂ©er une paire de ports COM virtuels liĂ©s. Dans notre cas, un port est utilisĂ© par l'Ă©mulateur, et l'autre — par le programme terminal (PuTTY ou screen) :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Utilisation de com0com

Les ports COM virtuels sont configurĂ©s Ă  l'aide de l'utilitaire setup du package com0com (version console — C:Program Files (x86)com0comsetupс.exe, ou version GUI — C:Program Files (x86)com0comsetupg.exe):

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Il convient d'activer les options enable buffer overrun pour tous les ports virtuels créés, sinon l'émulateur attendra une réponse du port COM.

Utilisation de socat

Sur les systÚmes UNIX, les ports COM virtuels sont automatiquement créés par l'émulateur à l'aide de l'utilitaire socat, il suffit à cet effet, lors du lancement de l'émulateur, de spécifier le préfixe dans le nom du port socat :.

Interface interne de ligne de commande (Argparse ou Python)

Étant donnĂ© que Kopycat est une application en ligne de commande, pour interagir avec ses objets et variables, l'Ă©mulateur propose deux options d'interface de ligne de commande : Argparse et Python.

Argparse est une interface CLI intégrée à Kopycat, elle est toujours accessible à tous.

L'alternative CLI est l'interpréteur Python. Pour l'utiliser, il est nécessaire d'installer le module Python Jep et de configurer l'émulateur pour travailler avec Python (l'interpréteur Python installé sur le systÚme principal de l'utilisateur sera utilisé).

Installation du module Python Jep

Sous Linux, Jep peut ĂȘtre installĂ© via pip :

pip install jep

Pour installer Jep sous Windows, il est nĂ©cessaire de prĂ©alablement installer Windows SDK et la version correspondante de Microsoft Visual Studio. Nous avons un peu simplifiĂ© votre tĂąche en fournissant des builds WHL JEP pour les versions actuelles de Python sous Windows, donc le module peut ĂȘtre installĂ© Ă  partir du fichier :

pip install jep-3.8.2-cp27-cp27m-win_amd64.whl

Pour vérifier l'installation de Jep, il est nécessaire d'exécuter dans l'invite de commandes :

python -c "import jep"

La rĂ©ponse doit ĂȘtre le message suivant :

ImportError : Jep n'est pas supportĂ© dans Python autonome, il doit ĂȘtre intĂ©grĂ© dans Java.

Dans le fichier de commande de l'Ă©mulateur pour votre systĂšme (kopycat.bat — pour Windows, kopycat — pour Linux) ajoutez le paramĂštre supplĂ©mentaire Ă  la liste de paramĂštres DEFAULT_JVM_OPTS ajoutez le paramĂštre supplĂ©mentaire Djava.library.path — il doit contenir le chemin vers le module Jep installĂ©.

Par conséquent, pour Windows, la chaßne devrait ressembler à ceci :

set DEFAULT_JVM_OPTS="-XX:MaxMetaspaceSize=256m" "-XX:+UseParallelGC" "-XX:SurvivorRatio=6" "-XX:-UseGCOverheadLimit" "-Djava.library.path=C:/Python27/Lib/site-packages/jep"

Lancement de Kopycat

L'émulateur est une application JVM en ligne de commande. Le lancement se fait via un script de l'invite de commandes du systÚme d'exploitation (sh/cmd).

Commande pour lancer sous Windows :

binkopycat -g 23946 -n rhino -l user -y library -p firmware=firmwarerhino_pass.bin,tty_dbg=COM26,tty_bt=COM28

Commande pour lancer sous Linux en utilisant l'outil socat :

./bin/kopycat -g 23946 -n rhino -l user -y library -p firmware=./firmware/rhino_pass.bin, tty_dbg=socat:./COM26,tty_bt=socat:./COM28

  • -g 23646 — le port TCP qui sera ouvert pour accĂ©der au serveur GDB ;
  • -n rhino — le nom du module principal du systĂšme (dispositif assemblĂ©) ;
  • -l user — le nom de la bibliothĂšque pour rechercher le module principal ;
  • -y library — le chemin pour rechercher les modules compris dans le dispositif ;
  • firmwarerhino_pass.bin — chemin vers le fichier de firmware ;
  • COM26 et COM28 — ports COM virtuels.

En conséquence, une invite sera affichée Python > ou Argparse >):

18:07:59 INFO [eFactoryBuilder.create ]: Le module top a été créé avec succÚs comme top
18:07:59 INFO [ Module.initializeAndRes]: Configuration du cƓur pour top.u1_stm32.cortexm0.arm pour top
18:07:59 INFO [ Module.initializeAndRes]: Configuration du débogueur pour top.u1_stm32.dbg pour top
18:07:59 WARN [ Module.initializeAndRes]: Tracer non trouvé dans top...
18:07:59 INFO [ Module.initializeAndRes]: Initialisation des ports et bus...
18:07:59 WARN [ Module.initializePortsA]: ATTENTION : Certains ports ont un avertissement, utilisez printModulesPortsWarnings pour le voir...
18:07:59 FINE [ ARMv6CPU.reset ]: Définir l'adresse du point d'entrée sur 08006A75
18:07:59 INFO [ Module.initializeAndRes]: Le module top est initialisé et réinitialisé avec succÚs en tant que cellule toppen !
18:07:59 INFO [ Kopycat.open ]: Démarrage de la virtualisation de la carte top[rhino] avec arm[ARMv6Core]
18:07:59 INFO [ GDBServer.debuggerModule ]: Nouveau module de débogage set top.u1_stm32.dbg pour GDB_SERVER(port=23946,alive=true)
Python >

Interaction avec IDA Pro

Comme fichier source pour l'analyse dans IDA pour faciliter le test, nous utilisons le firmware « Rhino » sous forme de fichier ELF (qui contient des métadonnées).

Vous pouvez également utiliser le firmware principal sans métadonnées.

AprĂšs le lancement de Kopycat dans IDA Pro, dans le menu DĂ©bogueur, allons Ă  l'Ă©lĂ©ment «Switch debugger » et choisissons «DĂ©bogueur GDB distant«. Ensuite, configurons la connexion : menu DĂ©bogueur — Options de processus


Nous définissons les valeurs :

  • Application — n'importe quelle valeur
  • Nom d'hĂŽte : 127.0.0.1 (ou l'adresse IP de la machine distante oĂč Kopycat est exĂ©cutĂ©)
  • Port : 23946

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Le bouton de démarrage du débogage (touche F9) devient maintenant disponible :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Nous cliquons dessus — cela connecte au module de dĂ©bogage sur l'Ă©mulateur. IDA passe en mode dĂ©bogage, et des fenĂȘtres supplĂ©mentaires deviennent accessibles : informations sur les registres, sur la pile.

Nous pouvons maintenant utiliser toutes les fonctionnalités standard du débogueur :

  • exĂ©cution pas Ă  pas des instructions (Entrer dans et Sauter — les touches F7 et F8, respectivement) ;
  • lancer et suspendre l'exĂ©cution ;
  • crĂ©er des points d'arrĂȘt Ă  la fois sur le code et sur les donnĂ©es (touche F2).

Se connecter au dĂ©bogueur ne signifie pas dĂ©marrer le code du firmware. La position actuelle pour l'exĂ©cution doit ĂȘtre l'adresse 0x08006A74 — dĂ©but de la fonction Reset_Handler. Si nous faisons dĂ©filer le listing en dessous, nous pouvons voir l'appel de la fonction main. Nous pouvons placer le curseur sur cette ligne (adresse 0x08006ABE) et exĂ©cuter l'opĂ©ration ExĂ©cuter jusqu'au curseur (touche F4).

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Ensuite, nous pouvons appuyer sur F7 pour entrer dans la fonction main.

Si nous exĂ©cutons la commande Continuer le processus (touche F9), une fenĂȘtre «Veuillez patienter» apparaĂźtra avec le seul bouton Suspendre:

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

En appuyant sur Suspendre l'exĂ©cution du code de firmware est suspendue et peut ĂȘtre reprise Ă  la mĂȘme adresse dans le code oĂč elle a Ă©tĂ© interrompue.

Si nous continuons l'exécution du code, dans les terminaux connectés aux ports COM virtuels, nous pouvons voir les lignes suivantes :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

La présence de la ligne «state bypass» indique que le module Bluetooth virtuel est passé en mode de réception de données depuis le port COM de l'utilisateur.

Nous pouvons maintenant entrer des commandes dans le terminal Bluetooth (sur l'image — COM29) conformĂ©ment au protocole «RhinocĂ©ros». Par exemple, pour la commande «MEOW», le terminal Bluetooth retournera la ligne «mur-mur» :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Ne m'émule pas complÚtement

Lors de la construction de l'Ă©mulateur, il est possible de choisir le degrĂ© de dĂ©tail/l'Ă©mulation de tel ou tel appareil. Par exemple, le module Bluetooth peut ĂȘtre Ă©mulĂ© de diffĂ©rentes maniĂšres :

  • l'appareil est entiĂšrement Ă©mulĂ© avec un ensemble complet de commandes;
  • les commandes AT sont Ă©moulĂ©es, et le flux de donnĂ©es est reçu depuis le port COM du systĂšme principal;
  • l'appareil virtuel assure un redirectionnement complet des donnĂ©es vers l'appareil rĂ©el;
  • sous la forme d'une simple prise qui renvoie toujours «OK».

Dans la version actuelle de l'émulateur, une deuxiÚme approche est utilisée : un module Bluetooth virtuel effectue la configuration, puis passe en mode de « proxy » des données du port COM du systÚme principal vers le port UART de l'émulateur.

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

ConsidĂ©rons la possibilitĂ© d'instrumenter facilement le code dans le cas oĂč une partie du matĂ©riel n'est pas implĂ©mentĂ©e. Par exemple, si un minuteur n'est pas créé pour contrĂŽler le transfert de donnĂ©es en DMA (la vĂ©rification se fait dans la fonction ws2812b_wait, situĂ©e Ă  l'adresse 0x08006840), le firmware attendra toujours le rĂ©initialisation du drapeau busy, situĂ© Ă  l'adresse 0x200004C4, qui indique si la ligne de donnĂ©es DMA est occupĂ©e :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Nous pouvons contourner cette situation par un rĂ©initialisation « manuelle » du drapeau busy immĂ©diatement aprĂšs son installation. Dans IDA Pro, vous pouvez crĂ©er une fonction Python et l'appeler dans un point d'arrĂȘt, en plaçant le point d'arrĂȘt dans le code aprĂšs avoir enregistrĂ© la valeur 1 dans le drapeau busy.

Gestionnaire de point d'arrĂȘt

Commençons par crĂ©er une fonction Python dans IDA. Menu Fichier — Commande de script


Ajoutons un nouveau snippet dans la liste de gauche, donnons-lui un nom (par exemple, BPT),
dans le champ de texte Ă  droite, saisissons le code de la fonction :

def skip_dma():
    print "Skipping wait ws2812..."
    value = Byte(0x200004C4)
    if value == 1:
        PatchDbgByte(0x200004C4, 0)
return False

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

AprĂšs cela, nous cliquons sur ExĂ©cution et fermons la fenĂȘtre des scripts.

Maintenant, allons dans le code Ă  l'adresse 0x0800688A, plaçons un point d'arrĂȘt (touche F2), modifions-le (menu contextuel Modifier le point d'arrĂȘt
), n'oubliez pas de dĂ©finir le type de script – Python :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat
Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Si la valeur actuelle du drapeau busy est Ă©gale Ă  1, alors la fonction skip_dma devrait ĂȘtre exĂ©cutĂ©e dans la ligne de scripts :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Si nous lançons le firmware pour l'exĂ©cution, nous pouvons voir l'exĂ©cution du code du gestionnaire de point d'arrĂȘt dans IDA dans la fenĂȘtre Sortie par la ligne Skipping wait ws2812.... Maintenant, le firmware ne devrait pas attendre la rĂ©initialisation du drapeau. busy.

Interaction avec l'émulateur

L'émulation juste pour le plaisir d'émuler ne suscitera probablement pas d'enthousiasme. Il est beaucoup plus intéressant si l'émulateur aide le chercheur à voir des données en mémoire ou à établir l'interaction des flux.

Voyons comment établir dynamiquement l'interaction des tùches RTOS. Au préalable, il faut suspendre l'exécution du code, si elle est en cours. Si vous accédez à la fonction bluetooth_task_entry dans la branche de traitement de la commande « LED » (adresse 0x080057B8), vous pouvez voir qu'un message est d'abord créé, puis envoyé dans la queue systÚme ledControlQueueHandle .

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Il convient de placer un point d'arrĂȘt sur l'accĂšs Ă  la variable ledControlQueueHandle, situĂ©e Ă  l'adresse 0x20000624 et de continuer l'exĂ©cution du code :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

En consĂ©quence, un arrĂȘt se produira d'abord Ă  l'adresse 0x080057CA avant l'appel de la fonction osMailAlloc, ensuite, Ă  l'adresse 0x08005806 avant l'appel de la fonction osMailPut, puis aprĂšs un certain temps, Ă  l'adresse 0x08005BD4 (avant l'appel de la fonction osMailGet), qui appartient Ă  la fonction leds_task_entry (tĂąche LED), c'est-Ă -dire qu'il y a eu un changement de tĂąche, et maintenant, la gestion est passĂ©e Ă  la tĂąche LED.

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Cette méthode simple permet d'établir comment les tùches RTOS interagissent les unes avec les autres.

Bien sĂ»r, en rĂ©alitĂ©, l'interaction des tĂąches peut ĂȘtre plus complexe, mais avec l'utilisation d'un Ă©mulateur, le suivi de cette interaction devient moins ardu.

Ici On peut visionner une courte vidéo sur le lancement de l'émulateur et l'interaction avec IDA Pro.

Lancement avec Radare2

On ne peut pas ignorer un outil aussi polyvalent que Radare2.

Pour se connecter à l'émulateur en utilisant r2, la commande sera la suivante :

radare2 -A -a arm -b 16 -d gdb://localhost:23946 rhino_fw42k6.elf

Actuellement, le démarrage (dc) et la pause d'exécution (Ctrl+C) sont disponibles.

Malheureusement, pour le moment, r2 prĂ©sente des problĂšmes lors de l'utilisation du serveur gdb matĂ©riel et de la mise en page de la mĂ©moire, ce qui empĂȘche les points d'arrĂȘt et les Ă©tapes (commande ds). Nous espĂ©rons que cela sera corrigĂ© prochainement.

Lancement avec Eclipse

Une des façons d'utiliser l'émulateur est de déboguer le firmware de l'appareil en développement. Pour plus de clarté, nous allons également utiliser le firmware "Rhinocéros". Vous pouvez télécharger le code source du firmware d'ici.

Nous allons utiliser Eclipse comme IDE de l'ensemble System Workbench for STM32.

Pour que le firmware, directement compilé dans Eclipse, soit chargé dans l'émulateur, il est nécessaire d'ajouter le paramÚtre firmware=null à la commande de lancement de l'émulateur :

binkopycat -g 23946 -n rhino -l user -y modules -p firmware=null,tty_dbg=COM26,tty_bt=COM28

Configuration de debug

Dans Eclipse, choisissez le menu ExĂ©cuter — Configurations de debug
 Dans la fenĂȘtre qui s'ouvre, sous la section GDB Hardware Debugging il est nĂ©cessaire d'ajouter une nouvelle configuration, aprĂšs quoi, dans l'onglet « Principal », indiquer le projet actuel et l'application Ă  dĂ©boguer :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Dans l'onglet « Débogueur », il est nécessaire d'indiquer la commande GDB :
${openstm32_compiler_path}arm-none-eabi-gdb

Et également d'entrer les paramÚtres pour se connecter au serveur GDB (hÎte et port) :

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Dans l'onglet « Démarrage », il est nécessaire d'indiquer les paramÚtres suivants :

  • cocher la case Load image (pour que le chargement de l'image compilĂ©e du firmware soit effectuĂ© dans l'Ă©mulateur) ;
  • cocher la case Load symbols;
  • ajouter la commande de lancement : set $pc = *0x08000004 (dĂ©finir la valeur PC Ă  partir de la mĂ©moire Ă  l'adresse 0x08000004 — lĂ  oĂč l'adresse est stockĂ©e ResetHandler).

Veuillez noter, si vous ne souhaitez pas charger le fichier de firmware depuis Eclipse, alors les paramÚtres Load image et Exécutez les commandes ne sont pas nécessaires.

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

AprÚs avoir cliqué sur Debug, vous pouvez travailler en mode débogage :

  • exĂ©cution pas Ă  pas du code
    Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat
  • interactions avec les points d'arrĂȘt
    Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

Remarque. Dans Eclipse, il y a, euh
 certaines spĂ©cificitĂ©s
 et il faut vivre avec. Par exemple, si un message « No source available for «0x0″ » apparaĂźt au lancement du dĂ©bogueur, exĂ©cutez la commande Step (F5)

Un rhinocĂ©ros Ă  l'intĂ©rieur d'un chat — dĂ©marrer un firmware dans l'Ă©mulateur Kopycat

En conclusion

L'Ă©mulation du code natif est un sujet particuliĂšrement intĂ©ressant. Pour le dĂ©veloppeur d'appareils, cela permet de dĂ©boguer le firmware sans appareil rĂ©el. Pour le chercheur, c'est une opportunitĂ© de rĂ©aliser une analyse dynamique du code, ce qui n'est pas toujours possible mĂȘme avec un appareil.

Nous voulons fournir aux spécialistes un outil qui soit pratique, relativement simple et qui ne prenne pas trop de temps et d'efforts pour sa configuration et son lancement.

Écrivez dans les commentaires votre expĂ©rience avec les Ă©mulateurs matĂ©riels. Nous vous invitons Ă  discuter et nous serons ravis de rĂ©pondre Ă  vos questions.

Seuls les utilisateurs enregistrés peuvent participer au sondage. Connectez-vous, s'il vous plaßt.

Pourquoi utilisez-vous l'émulateur ?

  • je dĂ©veloppe (dĂ©bogue) des firmwares

  • j'analyse des firmwares

  • je lance des jeux (Dendi, Sega, PSP)

  • autre chose (Ă©crivez dans les commentaires)

7 utilisateurs ont voté. 2 utilisateurs se sont abstenus.

Quel logiciel utilisez-vous pour l'émulation de code natif ?

  • QEMU

  • Moteur Unicorn

  • Proteus

  • autre chose (Ă©crivez dans les commentaires)

6 utilisateurs ont voté. 2 utilisateurs se sont abstenus.

Qu'aimeriez-vous améliorer dans l'émulateur utilisé ?

  • je souhaite de la rapiditĂ©

  • je souhaite un rĂ©glage/lancement plus facile

  • je souhaite plus d'options d'interaction avec l'Ă©mulateur (API, hooks)

  • tout me convient

  • autre chose (Ă©crivez dans les commentaires)

8 utilisateurs ont voté. 1 utilisateur s'est abstenu.

Source : habr.com

Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS đŸ”„ Acheter un hĂ©bergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster