Xiaomi Scooter Firmware reverse engineering

20 Januar 2026
2
1
E-Scooter
Xiaomi 5 pro
Hallo zusammen,

nachdem auf meinen Post von heute 15:00 Uhr leider keine Rückmeldung kam, habe ich beschlossen, das Thema selbst in die Hand zu nehmen. Mir ist klar, dass die neue Brightway-Architektur (Linkosemi LKS32MC081 Chip) eine andere Hausnummer ist als die alten STM32-Controller, aber ich bin bereits tief im Reverse Engineering der Firmware.

Was ich bisher gemacht habe:

Ich habe die MCU-Firmware extrahiert und erfolgreich in Ghidra (ARM Cortex-M0, Little Endian) importiert und analysiert.

Meine Funde bisher:

  1. Speed-Init Funktion (FUN_000031dc): Ich habe die Stelle gefunden, an der die Fahrmodi initialisiert werden.
    • Der Code lädt ein Array mit 0x14 (20 km/h) und 0x18 (24 km/h) und übergibt es an FUN_0000cd80. Das ist der Einstiegspunkt für die Limits.
  2. UART Kommunikation: Ich habe den Protokoll-Handler (FUN_00003f00) und die TX-Logik identifiziert (Magic Byte 0xAA, Checksummen-Berechnung).
  3. CRC-Logik: Die Firmware nutzt eine CRC16-Prüfung (0xA001 Polynom), die ich im Code lokalisiert habe (FUN_00003b42).
Mein Ziel:

Ich will keinen statischen "Patch" (dauerhaft 30 km/h), sondern echtes "German Maneuver" (GM) via Code-Injection implementieren.

  • Plan: Einen Hook in die Speed-Init-Funktion setzen, der zu einer Code-Cave springt.
  • Payload: Dort prüfe ich eine RAM-Variable (ausgelöst durch Bremshebel-Sequenz). Wenn aktiv -> 0x1E (30 km/h), sonst 0x14.
Wobei ich Hilfe brauche / Suche nach Mitstreitern:

Ich hänge aktuell an zwei Punkten und suche Leute, die sich mit der Brightway-Memory-Map auskennen:

  1. RAM-Adresse Bremshebel: Hat jemand die genaue Speicheradresse (ADC-Register oder globale Variable) für den Bremshebel-Status beim LKS32MC081 gemappt? Ich sehe die UART-Sendelogik, finde aber den Rückweg vom ADC noch nicht.
  2. Signatur/CRC: Wenn ich den Hook setze, muss die Checksumme im Header korrigiert werden. Hat jemand das genaue Format des Brightway-Headers oder ein Python-Script zur Neuberechnung der File-CRC?
Ich stelle meine Ghidra-Ergebnisse gerne zur Verfügung. Wer fit in Assembler (Thumb) ist oder schon an der Brightway-FW arbeitet: Bitte meldet euch! Ich will das Ding knacken, brauche aber noch ein paar Puzzleteile.

LG
 

Anhänge

  • {655C97F0-E669-458C-9340-A0CDFF8EC511}.webp
    {655C97F0-E669-458C-9340-A0CDFF8EC511}.webp
    94,8 KB · Aufrufe: 0
  • Hilfreich!
Reaktionen: knarfboy
Hallo zusammen,

nachdem auf meinen Post von heute 15:00 Uhr leider keine Rückmeldung kam, habe ich beschlossen, das Thema selbst in die Hand zu nehmen. Mir ist klar, dass die neue Brightway-Architektur (Linkosemi LKS32MC081 Chip) eine andere Hausnummer ist als die alten STM32-Controller, aber ich bin bereits tief im Reverse Engineering der Firmware.

Was ich bisher gemacht habe:

Ich habe die MCU-Firmware extrahiert und erfolgreich in Ghidra (ARM Cortex-M0, Little Endian) importiert und analysiert.

Meine Funde bisher:

  1. Speed-Init Funktion (FUN_000031dc): Ich habe die Stelle gefunden, an der die Fahrmodi initialisiert werden.
    • Der Code lädt ein Array mit 0x14 (20 km/h) und 0x18 (24 km/h) und übergibt es an FUN_0000cd80. Das ist der Einstiegspunkt für die Limits.
  2. UART Kommunikation: Ich habe den Protokoll-Handler (FUN_00003f00) und die TX-Logik identifiziert (Magic Byte 0xAA, Checksummen-Berechnung).
  3. CRC-Logik: Die Firmware nutzt eine CRC16-Prüfung (0xA001 Polynom), die ich im Code lokalisiert habe (FUN_00003b42).
Mein Ziel:

Ich will keinen statischen "Patch" (dauerhaft 30 km/h), sondern echtes "German Maneuver" (GM) via Code-Injection implementieren.

  • Plan: Einen Hook in die Speed-Init-Funktion setzen, der zu einer Code-Cave springt.
  • Payload: Dort prüfe ich eine RAM-Variable (ausgelöst durch Bremshebel-Sequenz). Wenn aktiv -> 0x1E (30 km/h), sonst 0x14.
Wobei ich Hilfe brauche / Suche nach Mitstreitern:

Ich hänge aktuell an zwei Punkten und suche Leute, die sich mit der Brightway-Memory-Map auskennen:

  1. RAM-Adresse Bremshebel: Hat jemand die genaue Speicheradresse (ADC-Register oder globale Variable) für den Bremshebel-Status beim LKS32MC081 gemappt? Ich sehe die UART-Sendelogik, finde aber den Rückweg vom ADC noch nicht.
  2. Signatur/CRC: Wenn ich den Hook setze, muss die Checksumme im Header korrigiert werden. Hat jemand das genaue Format des Brightway-Headers oder ein Python-Script zur Neuberechnung der File-CRC?
Ich stelle meine Ghidra-Ergebnisse gerne zur Verfügung. Wer fit in Assembler (Thumb) ist oder schon an der Brightway-FW arbeitet: Bitte meldet euch! Ich will das Ding knacken, brauche aber noch ein paar Puzzleteile.

LG
Vielleicht kann dir unser VooDooShamane VooDooShamane
Hilfe Stellung geben .
 
  • Hilfreich!
Reaktionen: Skipper36
Hallo zusammen,

nachdem auf meinen Post von heute 15:00 Uhr leider keine Rückmeldung kam, habe ich beschlossen, das Thema selbst in die Hand zu nehmen. Mir ist klar, dass die neue Brightway-Architektur (Linkosemi LKS32MC081 Chip) eine andere Hausnummer ist als die alten STM32-Controller, aber ich bin bereits tief im Reverse Engineering der Firmware.

Was ich bisher gemacht habe:

Ich habe die MCU-Firmware extrahiert und erfolgreich in Ghidra (ARM Cortex-M0, Little Endian) importiert und analysiert.

Meine Funde bisher:

  1. Speed-Init Funktion (FUN_000031dc):Ich habe die Stelle gefunden, an der die Fahrmodi initialisiert werden.
    • Der Code lädt ein Array mit 0x14 (20 km/h) und 0x18 (24 km/h) und übergibt es an FUN_0000cd80. Das ist der Einstiegspunkt für die Limits.
  2. UART Kommunikation: Ich habe den Protokoll-Handler (FUN_00003f00) und die TX-Logik identifiziert (Magic Byte 0xAA, Checksummen-Berechnung).
  3. CRC-Logik: Die Firmware nutzt eine CRC16-Prüfung (0xA001 Polynom), die ich im Code lokalisiert habe (FUN_00003b42).
Mein Ziel:

Ich will keinen statischen "Patch" (dauerhaft 30 km/h), sondern echtes "German Maneuver" (GM) via Code-Injection implementieren.

  • Plan: Einen Hook in die Speed-Init-Funktion setzen, der zu einer Code-Cave springt.
  • Payload: Dort prüfe ich eine RAM-Variable (ausgelöst durch Bremshebel-Sequenz). Wenn aktiv -> 0x1E (30 km/h), sonst 0x14.
Wobei ich Hilfe brauche / Suche nach Mitstreitern:

Ich hänge aktuell an zwei Punkten und suche Leute, die sich mit der Brightway-Memory-Map auskennen:

  1. RAM-Adresse Bremshebel: Hat jemand die genaue Speicheradresse (ADC-Register oder globale Variable) für den Bremshebel-Status beim LKS32MC081 gemappt? Ich sehe die UART-Sendelogik, finde aber den Rückweg vom ADC noch nicht.
  2. Signatur/CRC: Wenn ich den Hook setze, muss die Checksumme im Header korrigiert werden. Hat jemand das genaue Format des Brightway-Headers oder ein Python-Script zur Neuberechnung der File-CRC?
Ich stelle meine Ghidra-Ergebnisse gerne zur Verfügung. Wer fit in Assembler (Thumb) ist oder schon an der Brightway-FW arbeitet: Bitte meldet euch! Ich will das Ding knacken, brauche aber noch ein paar Puzzleteile.

LG
Coole Sache, ich versteh zwar nur 30% von dem Code-Chinesisch 😉, aber wenn du dich da rein hängst, überlege dir gut, ob du das wirklich per Bremshebel machen willst.
Der Trick ist so alt wie die Xiaomi Scooter in DE selber und inzwischen bei jedem Dorfsheriff bekannt 😒. Da macht es keinen Unterschied mehr, ob man gleich statisch fährt.

Dann imho lieber richtig, wie SHU das bis zum Dreier macht: Speed einschalten nur per App, persistent lassen und Ausschalten schnell und unauffällig per Kombi, Gas +Bremse z. B.. Ist natürlich mehr Aufwand....
Nichts desto trotz stark, dass du dich da rein knien willst 👍
 
Zuletzt bearbeitet:
  • Hilfreich!
Reaktionen: Skipper36 und Gobi