Weaponizing ESP32 RF Stacks Previous slide Next slide Toggle fullscreen Open presenter view
Weaponizing ESP32 RF Stacks
Romain Cayre, Damien Cauquil
Who are we ?
Romain Cayre , EURECOM
maintainer of Mirage , a popular BLE swiss-army tool
loves cross-protocol attacks (Wazabee )
Damien Cauquil , Quarkslab
maintainer of Btlejack , another BLE swiss-army tool
loves reversing stuff, including embedded systems
Enter the ESP32 world !
Cheap and lightweight SoCs
Commonly used for IoT devices (and DIY projects)
Provides WiFi , Bluetooth Low Energy / Bluetooth BR/EDR
Tensilica Xtensa (ESP32, ESP32-S3) and RISC-V (ESP-C3)
ESP32 global architecture
Lots of questions ...
Is it possible to:
sniff BLE communications ?
inject an arbitrary BLE PDU ?
divert the radio PHY to do nasty things ?
support other wireless protocols ?
turn any ESP32 into a wireless hacking tool ?
Memory Map
Memory Map
Hardware peripherals
Lots of them are mentionned in the ESP32 datasheet:
BLE controller ?
Playing hide and seek
Playing hide and seek
Found in a pastebin somewhere:
DA14681
BLE Link-Layer initialization
void r_lld_init ()
{
SYNCL = 0xbed6 ;
DAT_3ffb0442 = 0x8e89 ;
SYNCH = 0x8e89 ;
DAT_3ffb0444 = 0x5555 ;
CRCINIT0 = 0x5555 ;
DAT_3ffb0446 = 0x55 ;
CRCINIT1 = 0x55 ;
}
0x8e89bed6 : the advertising access address
ESP32 BLE controller
16-bit registers , like the DA14681
Same register order in ESP32 firmware
Dialog DA14681 is fully documented
What are we looking for ?
BLE stack overview
BLE Core (DA14681 ?)
vHCI
V irtual H ost C ontroller I nterface
Used by upper BLE stacks (NimBLE or Bluedroid)
Standardized messages, no sniffing nor injection possible
ESP-IDF
Provides a compatible implementation of NimBLE and Bluedroid
Shipped as static libraries
Can be updated when ESP-IDF is updated
Too dependent of a specific ESP-IDF version
There is maybe a place ...
ESP32 Internal ROMs
2 specific ROM regions
These regions contain some code and data
Low-level API functions to drive the BLE core
New problem : how to hook these functions?
Hooking ROM functions
ROM functions are called through r_ip_funcs_p
r_ip_funcs_p is a table of function pointers in RAM
Hacked functions (legit)
Let's hook !
PDU sniffing
Two main functions to hook:
Sniffing possible, but only for connections related to our ESP32
PDU injection
Use r_lld_pdu_data_tx_push() to send PDU
Can send data and control PDU !
Needs some wrapping to work properly
Man-in-the-Middle
We need a deep control over the BLE core
Or at least to handle two different connections at the same time
Seems impossible to achieve with an ESP32
Some cool hacks
LL_VERSION_IND injection
def send_version (self ):
"""Send LL_VERSION_IND PDU.
"""
if not self.__version_sent:
self.__version_sent = True
self.send_control(
BTLE_CTRL() / LL_VERSION_IND(
version=self.__llm.stack.bt_version,
company=self.__llm.stack.manufacturer_id,
subversion=self.__llm.stack.bt_sub_version
)
)
Remote BLE stack fingerprinting !
Hacking the physical layer
Cross-protocol attacks
Can ESP32 radio be diverted to interact with other protocols ?
BLE uses Gaussian Frequency Shift Keying (GFSK) modulation...
... like dozens of proprietary protocols in the same band !
(ANT+ / ANT-FS, Riitek, MosArt, Logitech Unifying, Microsoft...)
WazaBee: equivalence between O-QSPK (802.15.4) and 2Mbps GFSK (BLE 2M) 🠂 ESP32-S3 / ESP32-C3 only
Cross-protocol attacks
We need to control low level radio parameters :
CRC verification
frequency
datarate
synchronization word
whitening / dewhitening
input and output bitstreams
BLE RX synchronization
Hacking synchronization
Packet Processing
Bypassing Packet Processing
BLE Packet Transmission
Packet in Packet
Let's dive deeper
BLE Core is programmed using a shared memory zone named Exchange Memory .
Exchange Memory
Frequency table
Control structures
BLE registers
RWBLECNTL Register Definition
Bits Field Name Reset Value
----- ------------------ -----------
31 MASTER_SOFT_RST 0
30 MASTER_TGSOFT_RST 0
29 REG_SOFT_RST 0
28 SWINT_REQ 0
26 RFTEST_ABORT 0
25 ADVERT_ABORT 0
24 SCAN_ABORT 0
22 MD_DSB 0
21 SN_DSB 0
20 NESN_DSB 0
19 CRYPT_DSB 0
18 WHIT_DSB 0
17 CRC_DSB 0
16 HOP_REMAP_DSB 0
09 ADVERTFILT_EN 0
08 RWBLE_EN 0
07:04 RXWINSZDEF 0x0
02:00 SYNCERR 0x0
Arbitrary reception primitive
Arbitrary transmission primitive
Hook r_lld_pdu_tx_push and modify RF parameters
Find the TX buffer in EM and write a packet (PIP attack)
Start radio in TX test mode
RF imperfections
RF imperfections related to transceiver architecture
Mismatch between In-phase (I) and In-quadrature (Q) paths
Calibration process
Imperfections corrected using digital calibration technique :
Loopback between TX and RX path to estimate and compensate I/Q mismatch.
Forcing a full calibration
Calibration data stored in Non Volatile Memory (NVM) .
Full calibration only triggered if calibration data can't be found !
esp_bt_controller_shutdown();
esp_phy_erase_cal_data_in_nvs();
esp_phy_enable();
Hooking PHY functions
PHY functions stored in a specific function pointers array: g_phyFuns (pointer returned byphy_get_romfuncs())
Diverting calibration process
Disable HW frequency control (phy_dis_hw_set_freq)
Infinite loop when rom_loopback_mode_en is called
Have fun with signal control functions (frequency, gain) !
Fun with signals
WiFi Jamming
BLE Jamming
Capture is a screenshot from Ghidra.
These functions have been found in a firmware compiled with Espressig SDK, and are 100% related to BLE.
Let's dig up a bit ...
Looks like it is a DA14681 BLE stack ?! Dafuq ?
>> Home