Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
8cryptdo — Reverse-engineerte Dokumentation und Tools für die 8BitDo-Firmware-Verschlüsselung | Kitploit
Tools/GitHubGitHub/aeromodes/8cryptdo
Embedded-System-SicherheitVerschlüsselungs-/EntschlüsselungstoolsIoT-SicherheitReverse EngineeringKryptographieHardware- & IoT-SicherheitBinäranalysePapers & ForschungFirmware-Analyse
GitHubaeromodes/8cryptdo

8cryptdo

Reverse-engineerte Dokumentation und Tools für die 8BitDo-Firmware-Verschlüsselung

29vor 1 TagNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Repository anzeigen

8CryptDo

Reverse-engineered Dokumentation und Tooling für die Firmware-Verschlüsselung, die von 8BitDo für mehrere GD32-basierte Produkte verwendet wird.

Siehe 8cryptdo.py für ein Entschlüsselungs- und Wieder-Verschlüsselungs-Tool, das den in diesem Dokument beschriebenen Algorithmus anwendet.

Das Tool ermöglicht potenziell die Erstellung angepasster Firmware. Dieses Repository enthält jedoch keine der offiziellen Firmware-Daten. Ein Skript zum Herunterladen der neuesten Firmware-Dateien findet sich im Repository fwupd/8bitdo-firmware, in dem auch einige ältere Firmware-Binärdateien archiviert sind.

Header

Betrachtet man eine Firmware-.dat-Datei oberflächlich, so ist ein 28 Byte großer Klartext-Header vorhanden.

root@kitploit:~
import struct

raw = open("sn30-v2_07.dat", "rb").read()
version, addr, payload_len = struct.unpack("<III", raw[:12])
# version     = 207        -> firmware == v2.07
# addr        = 0x08003400 -> destination (probably)
# payload_len = 99328      -> section payload length in bytes

Bei neueren Firmware-Dateien steht danach ein unbekannter 32-Bit-Wert. Der Rest des Headers ist null.

Schlüssellose Verkettungsschicht

Bei bestimmten Firmware-Dateien zeigt sich ein Muster: Es gibt eine Schicht, die jedes Wort in das nächste einmischt.

root@kitploit:~
def rotr(x, r):
    return ((x >> r) | (x << (32 - r))) & 0xFFFFFFFF

dechained = [words[0]]
for i in range(1, len(words)):
    dechained.append(words[i] ^ rotr(words[i - 1], 3))

Diese Verkettung wird an jeder 128-Wort-Blockgrenze zurückgesetzt. Das erste Wort eines Blocks (pos = 0) hat keinen Vorgängerterm, und pos = 1..127 verkettet sich mit dem jeweils vorherigen Wort.

Eine schlüssellose Schicht bringt keine Sicherheit. Zieht man sie ab, so offenbart sich ein saubereres Zwischenergebnis (dechained), bei dem das Einzige, was den Klartext noch verbirgt, der Keystream ist.

root@kitploit:~
P[i] = dechained[i] ^ keystream[i]

Keystream-Faktorisierung

Das Repository fwupd/8bitdo-firmware enthält einen Katalog älterer Firmware. Diese Firmwares schienen alle die Verkettungsschicht zu besitzen.

XOR-verknüpft man einige von ihnen nach Entfernen der Verkettungsschicht miteinander, so zeigen sich lange Folgen von Nullen und lesbare Strukturen.

root@kitploit:~
plaintext_diff = [a ^ b for a, b in zip(dechained_a, dechained_b)]

Wenn derselbe Keystream in beiden verwendet wird...

root@kitploit:~
a = dechained_a[i] ^ dechained_b[i]
b = (P_a[i] ^ keystream[i]) ^ (P_b[i] ^ keystream[i])
c = P_a[i] ^ P_b[i]
assert a == b == c

hebt sich der Keystream auf.

Dies ist ein klassisches Many-Time-Pad. Ein solcher Keystream ist nur sicher, wenn er einmalig verwendet wird. Aus irgendeinem Grund entschied sich 8BitDo, nicht nur einen Keystream pro Produkt zu verwenden, sondern einen einzigen Keystream über mehrere Produkte hinweg. Dies schwächte die Sicherheit ihrer Verschlüsselung erheblich und ermöglichte den Rest der hier durchgeführten Analyse.

Den Keystream lesen

Sobald man weiß, dass zwei Klartexte miteinander XOR-verknüpft sind, kann man einen Teil des einen erraten und seine Vermutung subtrahieren, um den anderen zu lesen. Dadurch wird der keystream an dieser Stelle wiederhergestellt.

root@kitploit:~
keystream[i] = dechained[i] ^ P[i]
for fw in all_fw:
    P[fw][i] = dechained[fw][i] ^ keystream[i]

Am einfachsten wäre dies mit Zeichenketten, aber der produktivste Trick hier war die versionsübergreifende Verschiebung von ARM-Instruktionen. Eine Funktion kann in zwei Firmware-Versionen an verschobenen Positionen auftauchen. Wo der Keystream in einer Version bekannt ist, kann man den gemeinsamen Code in einer anderen ausrichten und neue Keystream-Werte ernten.

Die Ausnutzung dessen brachte die bekannten Keystream-Wörter von ~1.500 auf mehrere Tausend, etwa 18 % der lesbaren Firmware.

Keystream-Regel

Mit einer größeren Stichprobe des keystream wurden Muster sichtbar. Er hatte Positionen im Abstand von 16 Wörtern, die um einen nahezu konstanten Betrag weiterschritten, und jedes Byte bewegte sich um eine vorhersagbare Größe.

Durch Ausprobieren wurde entdeckt, dass jedes Keystream-Wort in einem Block einer Formel folgt:

root@kitploit:~
STEP  = 0x92A753FA
A_MUL = 0x80000301
ROT   = 18
UINT32_MAX  = 0xFFFFFFFF

def rotr(x, r):
    r &= 31
    return ((x >> r) | (x << (32 - r))) & UINT32_MAX if r else x

def block_base(block):
    return (block * A_MUL + block // 2) & UINT32_MAX

def keystream(block, pos, block_key):
    counter = (block_base(block) + pos * STEP) & UINT32_MAX
    mask = rotr(block_key, ROT * pos)
    return counter ^ mask

Innerhalb eines Blocks läuft ein einfacher Zähler (block_base(block) + pos*STEP), und dieser wird mit einer Maske XOR-verknüpft, die bei block_key beginnt und sich bei jedem Schritt um 18 Bit dreht. Der gesamte 128-Wort-Block wird durch eine einzige 32-Bit-Zahl, block_key, bestimmt.

Ein bekanntes Wort entsperrt einen ganzen Block. Durch Umstellen der Formel erhält man den block_key aus jedem bekannten Keystream-Wort:

root@kitploit:~
def block_key_from_known(block, pos, known_keystream):
    counter = (block_base(block) + pos * STEP) & UINT32_MAX
    return rotr(known_keystream ^ counter, -ROT * pos & 31)

Seed-Tabelle

Woher kam der Schlüssel jedes Blocks? Er faktorisiert sich in zwei 16-Bit-Hälften, die aus einer Seed-Tabelle mit 256 Einträgen stammen:

root@kitploit:~
def block_key_of(block, seed_table):
    hi = seed_table[block]
    lo = seed_table[block ^ 0xF9]
    return (hi << 16) | lo

Die Seed-Tabelle selbst scheint keine bestimmte Formel zu haben; sie besteht wahrscheinlich aus 512 konstanten Bytes, die irgendwo im Bootloader jedes Geräts gespeichert sind. Die XOR-Verknüpfung mit 0xF9 hat jedoch einen wunderbaren Nebeneffekt: ein Spiegelgesetz. Ein Block und sein Partner block ^ 0xF9 werden aus denselben zwei Tabelleneinträgen aufgebaut, nur vertauscht.

root@kitploit:~
mirror = block_key_of(block ^ 0xF9, seed_table)
assert mirror == rotr(block_key_of(block, seed_table), 16)

Dies knackte zuvor unbekannte Regionen. Anstatt einen vollständigen 32-Bit- block_key blind zu erraten, kann man zwei 16-Bit-Hälften erraten und bewerten, welche Wahl beide Blöcke in glaubwürdige Zeichenketten oder ARM-Instruktionen verwandelt.

Damit wurde eine 100%ige Abdeckung aller Firmware-Daten erreicht, die diese spezifische Verschlüsselung verwenden.

Verbleibende Arbeit

Diese Verschlüsselung scheint die meisten 8BitDo-Produkte um 2020 abzudecken, sowie aktuelle Produkte, die noch GD32-SoCs verwenden (einschließlich des SN30 Pro).

Einige Geräte wie der M30 und Zero 2 scheinen mehrteilig zu sein, wobei einige Firmware-Daten diese Verschlüsselung verwenden und eine andere Firmware ein anderes Verschlüsselungsschema nutzt.

Neuere Geräte, zumindest solche mit einem anderen SoC, scheinen ein stärkeres Firmware-Verschlüsselungsschema zu haben. Eine oberflächliche Analyse deutet darauf hin, dass es möglicherweise gemeinsam genutzt wird, aber das ist unsicher. Dies muss weiter untersucht werden.

Tool herunterladen