Reverse-engineering notebook for MOROBOT / XBOT / E-WHEELS BLE speed-control and firmware-update research.
Snapshot status: 2026-08-15, updated through verified XBOT ForcedUpgrade HTTP/file routing with the target's current DK image.
- BLE transport: Nordic UART Service (NUS)
- Service:
6E400001-B5A3-F393-E0A9-E50E24DCCA9E - RX/write:
6E400002-B5A3-F393-E0A9-E50E24DCCA9E - TX/notify:
6E400003-B5A3-F393-E0A9-E50E24DCCA9E - Controller branch: ScooterIII / HB
- BLE payload transform: bytewise XOR
0x34 F3uses direct uint16 little-endian encoding in units of0.001 km/hF3=30000was written and independently read back as30.0 km/h- Profile block observed:
EE=225EF=463~= 18 km/hF0=515~= 20 km/hF1=386~= 15 km/hF2=0F3=30000
- E-WHEELS/XBOT scaling for EF/F0/F1 is approximately
km/h = raw * EE / 5794.652832 - Numeric mode/slot mapping:
7E=0 -> F07E=1 -> EF7E=2 -> F17E=3 -> F3
- Per-profile maxima are consumed from
C2,C4, andC6. - Direct attempts to raise profile slots or
C2above their controller maxima are rejected/ignored on readback. - Direct HB
0x72=0limiter-off is rejected:0x1Dremains0x07F9, bit 0 set. - Direct
EE=226wheel-factor test is rejected: controller reads backEE=225. - A root
app_processBluetoothGatt client works without APK installation when Android Bluetooth framework bootstrap is recreated and the process runs as system UID 1000.
The complete installed XBOT split set was recovered, including split_config.arm64_v8a.apk and lib/arm64-v8a/libcpp_empty_test.so.
Static analysis found:
- a real firmware-update engine in
Bluetooth::UpdateApp()/Bluetooth::UpdataWrite() - forced-upgrade paths under
ForcedUpgrade/Scooter/... - normal E-WHEELS / Lebitec update paths
- firmware families including
DK,XK, andBP - a
PoJieinteger parsed from forced-upgradeConfig.xml
PoJie remains an unverified lead. A native patch forcing PoJie=1 did not produce a demonstrated controller-side speed bypass.
The target resolves to:
DK_MODEL = 0x84A8
DK_ID = 0x061007F9
The matching live E-WHEELS vendor image was recovered:
DK061007f9.bin
size = 28444 bytes
sha256 = 856c19b176f9e8d1f73f627e731e4a991282c9fba2a136b14651831b981bff62
A nearby vendor image was also recovered:
DK061007a7.bin
size = 28380 bytes
sha256 = 919f76d8447044d58945dc491eeed324e6154f55c9cee7edce2d256410458595
The images are high-entropy and not a simple near-identical plaintext pair, so blind binary patching is not currently justified.
An isolated XBOT native patch redirects only the ForcedUpgrade URLs to a local Termux HTTP server.
Test code:
MORO42001
Probe mode deliberately withheld firmware binaries. XBOT successfully fetched local Config.xml and then requested:
/f/MORO42001/DK01.bin
This proved that the real XBOT ForcedUpgrade path was following the controlled local source and that this branch selects DK01.bin.
The server was then switched to current-image mode. XBOT successfully downloaded the exact current vendor image as DK01.bin:
HTTP 200
28444 bytes
sha256 856c19b176f9e8d1f73f627e731e4a991282c9fba2a136b14651831b981bff62
This verifies the complete HTTP/file-selection side of ForcedUpgrade.
It does not yet prove that the controller completed the firmware flash. The next proof target is the BLE/HCI update transaction and ACK state machine.
See docs/09-forced-update-dk.md.
The normal writable HB register layer is no longer the primary path for unlocking the protected profile ceilings. C2/C4/C6, 0x72, and EE have all failed controller readback tests, while the separate ForcedUpgrade path is now experimentally reachable and controllable.
Highest-value next work:
- capture full HCI/ACL during one current-image ForcedUpgrade cycle,
- reconstruct the controller update-mode command and ACK progression,
- prove the current DK image completes controller-side update mode,
- then test only a compatible alternate vendor DK or minimally modified image,
- retain a from-scratch controller firmware as a fallback rather than the immediate next step.
GATT WRITE status=0 is never treated as proof that a controller setting changed. HTTP 200 is never treated as proof that firmware was flashed. Controller readback or update ACK progression is required.
docs/human-readable documentationdocs/restless-original/earlier write-up copied frombspippi1337/restlesstools/generated helpersMANIFEST.sha256digest manifest for the larger evidence bundle