SOURCE ARCHIVE
EXTRACTED CONTENT
30,697 charsLow Power, High Risk: Fuzzing the Chips Behind IoT
Noah Holmdin & Ravishankar Borgaonkar Hardwear.IO 2025 Amsterdam, Netherlands 20.11.2025
About Me – Noah Holmdin & Ravishankar Borgaonkar
Noah Holmdin- NTNU / Aalto University Security enthusiast interested in both technical and strategical dimensions of information security • Last year MSc in Information security student at the Norwegian University of Science and Technology (NTNU) • Currently on an exchange term at Aalto University • BSc in Computer Science, Linköping University
Ravishankar Borgaonkar - Senior Research Scientist (SINTEF AS) 15+ years of research in telecom/cyber security research, with experience at: • University of Oxford, Oxford, UK / TU Berlin / Aalto University • Deutsche Telekom Labs ( T-Labs), Berlin, Germany / Intel ICRI, Helsinki, Finland
Focus areas: • ICT Security architecture & vulnerability analysis • Contributed to 4G/5G (3GPP) security improvements Feel free to reach out: • Recognized by Google, GSMA, Qualcomm, Huawei (Hall of Fame) Email: Noah.Holmdin@outlook.com Email: Ravi.Borgaonkar@sintef.no 2 LinkedIn: linkedin.com/in/noah-holmdin-112579252
wall Fuzzing 101
3
Fuzzing 101 75 years
Al TOOLS WRITE
FIRMWARE CODE NOW
Sh)
=
/ ZN |] 1
A
7 y 1 | He
1
QUERY
4
Fuzzing Technique
Why Fuzzing • Automates security testing by sending malformed inputs to uncover bugs and vulnerabilities • Critical for IoT and embedded systems due to complex code, broad attack surfaces, & limited OSisolation • Proactive approach: identify vulnerabilities before attackers exploit them
What • Repeatedly executes target software with random or mutated inputs to trigger faults or crashes • Embedded/firmware fuzzing is unique: inputs delivered via hardware peripherals (MMIO, interrupts, DMA) rather than standard interfaces How • Coverage-guided fuzzing: leverages feedback on code paths explored during execution • Emulation/re-hosting: simulates firmware in virtual environments (e.g., QEMU, Unicorn) to enable fuzzing without physical hardware
5
Why Fuzz anything?
Usual CPU fuzzing • Targets OS-based binaries and user-space software (e.g., browsers, kernels) • Benefits from standard I/O, memory management, process isolation, and high execution speed
IoT/Microcontroller Unit (MCU) fuzzing challenges • No OS protection: monolithic firmware with constrained memory and non-standard I/O • Inputs delivered through Memory-Mapped I/O (MMIO) registers, interrupts, and DMA • Hardware dependency prevents firmware from running easily off-device
Low power bluetooth IoT MCUs • Built on SoCs like Nordic nRF52 • Complex peripheral behavior, timing sensitivity, and radio events add fuzzing complexity • On-device fuzzing impractical (slow and potentially destructive); emulation-based re-hosting is essential
6
FUZZWARE** Tool for
Overview
• Combines lightweight program analysis, firmware re-hosting, and coverage-guided fuzzing
• Novelty: Precise MMIO modeling that eliminates input overhead by focusing only on meaningful
hardware-generated values – best for MCUs
Fuzzware: Using Precise MMIO Modeling
for Effective Firmware Fuzzing
Tobias Scharnowski, Nils Bars, and Moritz Schloegel, Ruhr-Universitat Bochum; Eric Gustafson, UC Santa Barbara; Marius Muench, Vrije Universiteit Amsterdam; Giovanni Vigna, UC Santa Barbara and VMware; Christopher Kruegel, UC Santa Barbaro; Thorsten Holz and Ali Abbasi, Bochum https//www.usenix,org/conference/usenixsecurity22/presentation/scharnowski
** Soruce - https://www.usenix.org/system/files/sec22-scharnowski.pdf
7
FUZZWARE main() Logic Fuzzware: Using Precise MMIO Modeling
for Effective Firmware Fuzzing
SINTEF Tobias Scharnowski, Nils Bars, and Moritz Schloegel, Ruhr-Universitat Bochum; Marius Gustafson, 75 year Eric UC Santa Barbara; Muench, Vrije Universiteit Amsterdam; Giovanni Vigna, UC Santa Barbara and VMware; Christopher Kruegel, UC Santa Barbara; Thorsten Holz and Ali Abbasi, Bochum Main Components https//www.usenix.org/conference/usentxsecurity22/presentation/scharnowski
• Fuzzing Engine: Generates random or mutated input data to test | how the firmware reacts. It also monitors which parts of the code Hardware: io Access are executed (coverage feedback). enerate Value • Raw Input: The sequence of bytes produced by the fuzzer, e.g. like - Joost fake sensor readings or control signals. Fuzzware Emulator nl • MMIO Access Model: Converts chunks of the raw input into — “hardware-like” responses. e.g, when firmware tries to read from a sensor register, the MMIO model provides a realistic fake value. Fuzzing Engine Feedback • ISA Emulator: Runs the firmware binary as if it were on a real Figure 4: FUZZWARE's MMIO access handling design. The fuzzing engine microcontroller, using the fake MMIO responses. generates a raw input file. Upon MMIO accesses, chunks of the input file are • Coverage Feedback: After each run, the emulator reports which consumed by MMIO access models and translated into (potentially larger) hardware-generated values, which are then served to the emulated firmware. new code blocks were executed, helping the fuzzer learn and refine Once the raw input is exhausted, coverage feedback is provided to the fuzzing future inputs. engine to guide the fuzzing process.
Source - https://www.usenix.org/system/files/sec22-scharnowski.pdf 8
Run Fuzzware
UNE
Jr. if A fe Hi₀ »
AFT
§
a oi JY ( 1587.
oa i Ry ful
9
Fuzzing Project Work
01 02 03
Improving the user- Motivated by Secondary goal: friendliness of using previous research Analyze crashes Fuzzware on nRF52 regarding feasibility that are deemed devices of Fuzzing potential embedded devices vulnerabilities
10
Initial Experiments
Configuration issues
• Fuzzerware’s automatic configuration tool did not create a valid memory map for our target binary • The configuration did not include the FICR and UICR mmio memory sections → Could not emulate the binary • UICR = a user-programmable configuration memory that can influence how the chip boots • FICR = holds read-only factory data about the chip.
Initial Experiments
Manual Configuration
Manually created configuration which could be emulated, but:
Slow Identified Difficult to execution crashes in the know how to time emulation move forward
gual The Aurora-Fuzz workflow
A simple, but structured workflow for starting a fuzzing process.
If new version
If emulation failed
If coverage meaningful
If coverage not meaningful
, encountered
Analyze Crash / Crashes If crash caused by configuration
13
The Aurora-Fuzz Workflow
• Through the iterative process, we improved our configuration by: ‒ Adding static/constant mmio reads in bootloader → Quicker path to “user code” ‒ Identified and patched delay functions → Improved speed significantly ‒ Identified and patched “wait-for-flag” conditions
14
The Aurora-Fuzz Configuration Script ;
• Enabling simple automation of : Ce Fuzzware’s configuration process for nRF52 binaries = • Python script developed in response to feature requests from our industry partners 0x1000 ‒ One-click tool: generate configuration + i start fuzzing as Va ri 15 em = o
The Aurora-Fuzz python3 configuration_tool.py ../testing test.bin
—75years— Configuration Script Ue Retr leva Found binary file: ../testing/test.bin Do you want to load an existing config, or generate a new based on template? Key Features 0. Exit ‒ Command-line tool for creating and 1. Generate a new config 2. Load from ../testing directory modifying Fuzzware configurations re BE pt ‒ Start fuzzing sessions directly from the script Note, the configuration will not be saved unless explictily choosing the save option ‒ Filtering certain MMIO reads from 1. Print Memory Map Softdevice 2. Modify Memory Map 3. Skip Softdevice Noise ‒ Load static UICR/FICR state of from hex 4. Add Symbols S. Load UICR/FICR preset file file, or directly from USB connected chip 6. Modify BOOT i t ‒ Run flags that can be used to 8. Modify Interrupt Config 9. Modify Return Handlers automatically patch certain delay 10. Modify Exit At Model functions 11. Save config 12. Test Fuzzing Configuration 13. Start Fuzzing Session
0. Exit
16 Enter menu choice: J]
SINTEF Framework Evaluation
Experiment against a nrf52 binary, Translation Blocks Visited Over Time id with three configurations created oe with the configuration script: • Config 1: basic configuration 2000 • Config 2: automatic optimization i • Config 3: automatic + manual § optimizations 5 oo
—
—— Session2 - config2.log
0 —— Session3 - config3.log
0 10 15 20 25
Elapsed Time (Hours)
17
SINTEF Framework Evaluation
Translation Blocks Visited Over Time
Takeaways: gai • Aurora-Fuzz capable of generating 4000 05 working configuration • Optimizations discovered through 2 3000 the iterative Aurora-fuzz workflow 2 significantly improved coverage 2000 • Defining “good” coverage in embedded firmware remains 1000 difficult —— Session: 1 - configl.log • Complexity of architecture still —— Session2 - 3 config2.log 0 — og Session config3 cause emulator to plateau early ° i eed Time (ours) 2
18
SINTEF From Project Work to Bug Hunting
| Shifting focus to analyze crashes
~ a encountered during our experiments ee • We encountered similar crashes early —_ in program execution during fuzzing of several binaries
: | AK
Image generated with ChatGPT
19
SINTEF
Crash Analysis Calling function: delay machine code.6 from nrfx_coredep delay us (PC=0x3e850, LR=0x2643d)
Basic Block: addr= (1r=0x2643d)
Basic Block: addr= 0x000000000002643c (1r=0x2643d)
An initial overview Basic Block: addr= (1r=0x2643d)
>>> Read: addr= size=4 [(pc
Basic Block: addr= (1r=0x2643d)
>>> Read: addr= 0x2003ffbc[SP:-0004] size=4 data=0x0000002b (pc 0x000266b8)
• Using Fuzzware’s built in functionalities to: >>> Write: addr= 0x2003ffbc[SP:-0004] size=4 data=0x0000002a (pe (pc >>> Read: addr= 0x2003ffbc[SP:-0004] size=4 0x000266be)
‒ Maps crashes based on their instruction pointer and link registers Basic Block: addr= 0x000000000002641c (1r=0x266b9) ‒ Creates paths that can be used to replay the crash >>> Write: addr= 0x2003ffb4[SP:+0004] size=4 (pc >>> Write: addr= size=4 data=0x000003e8 (pcGather crash buckets Basic Block: addr= 0x00000000000266b0 (1r=0x2643d) Calling function: nrfx_coredep delay us from ms (PC=0x2641c, LR=0x266b9)
‒ Outputs path taken in emulator up until the crash, including >>> Read: addr= 0x0000000000026448 size=4 data=0x0003e850 (pc 0x00026428) ▪ MMIO interactions, and >>> Write: addr= 0x2003ffac[SP:-000c] size=4 (pc ▪ code blocks visited >>> Read: addr= 0x2003ffa4[SP:-0004] size=4 data=0x000003e8 (pc 0x00026430) >>> Write: addr= 0x2003ffa8[SP:-0008] size=4 (pc 0x00026434) >>> Read: addr= 0x2003ffac[SP:-000c] size=4 data=0x0003e851 (pc 0x00026436) >>> Read: addr= 0x2003ffa8[SP:-0008] size=4 (pc 0x00026438)Replay crash traces Basic >>> Read: addr= 0x2003ffa4[SP:-0004] size=4 data=0x000003e8 (pc 0x00026422) Block: addr= 0x0000000000026428 (1r=0x266b9)
→ Gives an initial overview of the crash Calling function: delay machine code.6 from nrfx_coredep delay us (PC=0x3e850, LR=0x2643d) Basic Block: addr= 0x000000000003e850 (1r=0x2643d) Basic Block: addr= 0x000000000003e854 (1r=0x2643d) Basic Block: addr= (1r=0x2643d) Basic Block: addr= (1r=0x2643d) Instruction pointer (EIP, PC) = The instruction pointer tells >>> Read: addr= size=4 (pc the CPU what instruction to execute next. Basic Block: addr= (1r=0x2643d) >>> Read: addr= size=4 data=0x0000002a (pc 0x000266b8) Link register = The link register stores the return address — >>> Write: addr= 0x2003ffbc[SP:-0004] size=4 data=0x00000029 (pc where the CPU should go back to after finishing a function Basic >>> Read: addr= 0x2003ffbc[SP:-0004] size=4 data=0x00000029 (pc 0x600266be) Block: addr= (1r=0x2643d) Calling function: nrfx_coredep delay us from nrf delay ms (PC=0x2641c, LR=0x266b9)
Crash Analysis Instruction Pointer values at crashes
An initial overview
→ In our case: • Crashes occurred at around the same stage of EIP: 0x55555555 execution, but with different instruction pointer values • Mostly related to the emulator trying to read from unallocated memory sections ‒ Repeating values in stack pointer, ex: 0xA5A5A5A5 • All crashes showed a consistent sequence of code blocks leading up to the failure • So we needed to dig deeper into this shared execution pattern to understand what those blocks were doing
SINTEF Crash Analysis 75 year Going deeper
4% oo ©
[ll BES 0050c - (packedup) |
data 77 A i
EE
sequen
Utilized the reverse ane ora outs acm Good et akin
engineering tool ghidra Br 00400090. 00
8 fini_array P aa ELf64_Endr 9 bool
mm FE
B fini 00400005 01 dedb n e_ident_data i - topkey for << 0c)
= sn
- 00400018 0 04 40 0 60 dh In Hd! 1s; Th od GHIDRA Sa + cous dg entry o_phoff 4 1 ite Givers 1s
1+ JO | ‒ Enabled us to find the § FUN00400500 oo 7 b¥ars = 18 < 0; instructions causing the Tce red 0 60 ohn 3 arty) Cn 1+ 101 = i ri crash ie El ec ‒ Related to MMIO reads » jd Eo | writell, Yep! jou got the flag 1 from the UICR memory sari os ot ror +7 section, in the SoftDevice 1x BEE 1 part of the binary er mm co. HHH
< >
= adix
Fier.
2! Source: https://commons.wikimedia.org/w/index.php?curid=77146565
Crash Analysis Understanding the root cause
Fuzzed UICR READ:
0xA1A1A1A1
SP: 0xA1A1A1A1
Crash path EIP: 0xFFAAFFAA
JUMP block
SP
SP: 0x20001000 SP: 0x20001000 SP: 0x20001000 Path determined by UICR read EIP: 0x00000000 EIP: 0x00000008 EIP: 0x0000000F
EIP
Intended path SP: 0x20001000 MAIN
EIP: 0x00210000
Fuzzed UICR READ:
0xFFAAFFAA
Reminder: UICR = a user-programmable configuration memory that can influence how the chip boots
SINTEF
75 years.
Crash Analysis Creating an emulation PoC
Modified the Fuzzware configuration with a static MMIO read at the exact instruction pointer in the JUMP block → Read 0x00000000 → EIP set to 0x00000000 Result
SP: 0x20001000 SP: 0x20001000 SP: 0x20001000 = Path determined by UICR read
Loop path EIP: 0x00000000 EIP: 0x00000008 EIP: 0x0000000F
= Infinite loop EIP Intended path SP: 0x20001000 MAIN
EIP: 0x00210000
Static UICR READ:
0x00000000
At this stage
Confirmed weakness in the emulated environment
Next: Does the weakness also affect the actual hardware? =
|}
Problem: How should we manipulate a MMIO read? )
Generated with ChatGPT
25
SINTEF Deciding on an approach Target: NRF52840 development kit +4 fay 4 ed Two potential approaches: ® pi 2 I §
- Hardware glitching – voltage/power fault injection =
- Realistic pt fv
- Complex pen
- Debug mode – Inject value UICR through the nrfjprog
utility
- Feasible fre : x
- Controlled but less realistic
Chosen method: Debug mode Hi 5 i nRF52840-DK 89 26 Source: https://www.nordicsemi.com/Products/Development-hardware/nRF52840-DK
SINTEF — Creating the PoC { attribute ((used)) malicious ( ) leds_init();
for ( =0; j < 16; j++)
• Added a hidden “malicious” function to modified { for blinky firmware • Compiled the firmware and located the function bsp_board led nrf_delay address in Ghidra — 0); • Injected that address into the UICR register read at == 15 & i >= 2 the JUMP block (using nrfjprog) ‒ To test whether the MCU would jump to the “mov re, %[vall i unreachable code
"re"
ii
main ( ) }
{
}
bsp_board led on(0);
led on(1);
bsp_board led on(2);
if (* *)0x20003000 == 0xA2B3C4D5) led on(3);
{
malicious(); nrf_delay
} bsp_board led off(0);
bsp_board led off(2);
for (;;) nrf_delay ms(3000);
{
idle state handle(); buffer underwrite();
} }
27
Demo https://youtu.be/9nBUH_oLk9E SINTEF - FM SOK 15... Q = =Nov20B x1539 Gow v « 8 @ = B a 9 sh program₊ BF Trees | | v X 2840 x Ts a B deta 1 WIG: stain @&= B 08 c7 cz 00 PIM WARNING bals starting wil [B® DAT Sh B on sack J A
[© observers nm 1a 23 00 20
segment. hstrtab 14 undefined [Program ree | = | 78 c1 62 60 our} i bap
x| 8 wi J PT T our) a “ned tes 1 Pom 5
os \ void 2 dw { em cote a = aris wid FUE page do{ Ri + 01 18 41 3 ” 20 H
§ 34 4d13 ot bo u - = ofa 18 61 i 17 Salts 40 45 10 01 03 7 41 10 00 03 ne NEE | la of
Types 00620208 ze de out 00 2 84 » 45 » 0002a20¢ cb 18 00 90 #8}= 47 bsp on(2) 5 48
re mom bo L ST cs 34 id | add
Scripting. x
28 El 15 Corso % | % | maiicious [push
—75 years — Demo
https://youtube.com/shorts/YnC6WsLTQ3k https://www.youtube.com/shorts/LrtDehPDt 8U
CLE EB te 5 i
29
Implications
If we can manipulate the specific UICR read, then we gain control of both the instruction pointer and the stack pointer →Remote Code Execution →Denial of Service →Stack Overflow
Next step: report the findings to the manufacturer
30
Bug(?) Reporting
Wrote vulnerability report and sent in through Nordic’s vulnerability disclosure form ➢ Weeks without answer Uploaded private blog post on Nordic’s forum ➢ Quick response, referring us to the disclosure form Tried gaining access to their private bug bounty program ➢ Could not get an invite Eventually established direct contact with their security team and prepared to submit the report via PGP ➢ While PGP may offer Pretty Good Privacy, it also offered Pretty Difficult Privacy Takeaway: Do not report vulnerabilities during the summer in the nordics 31
SINTEF Is this a vulnerability?
Yes/No, but interesting a i • Our PoC required debug mode, the behavior is not i exploitable in the same way for production devices ae ‒ And in debug mode, even worse things can be done • Using values from UICR to set PC/SP is an intended (( )) feature for customer customization • Feature vs potential security issue BUG FEATURE Source: https://www.reddit.com/r/ProgrammerHumor/comments/1w1u3o/bug_vs_feature/
32
SINTEF Is this a vulnerability?
What about other injection approaches?
‒ NRF52 family has been shown vulnerable to glitching \ | \ |
attacks
▪ CVE-2020-27211 PN Pa
▪ "MEDICAL DEVICE Security Analysis", Cc-sw, Available: ie
https://cc-sw.com/medical-device-security-analysis/ svi,
This means the code path we identified might be \\
reachable under real-world glitching conditions BUG FEATURE
• Shows that there is a thin line between feature and Source: https://www.reddit.com/r/ProgrammerHumor/comments/1w1u3o/bug_vs_feature/ flaw ‒ Removing the feature improves security… ‒ …but may break legitimate customer use cases 33
Take Aways
• At it’s core, Fuzzware is good for finding vulnerabilities, but lacks some usability aspects Not “plug and play” • Our approach for improving user-friendliness makes starting a fuzzing process easier. But, the analysis still demands manual analysis of analyzing outputs. Which requires a good understanding memory layouts and assembly instructions • Fuzzing Bluetooth devices is time consuming due to reliance on MMIO communication. To get good coverage • There is some cases a thin line between feature and security flaw (Again!) • Vulnerability disclosure - Do not report vulnerabilities in the Scandinavia during the summer
34 27/08/2025
Questions?
Feel free to reach out: © Email: Noah.Holmdin@outlook.com © Email: Ravi.Borgaonkar@sintef.no ¢ LinkedIn: linkedin.com/in/noah-holmdin-112579252
Special Thanks for :
TELEMETRY EU Project (https://telemetry-project.eu/) Norwegian Research Council funded RAKSHA Project - 312122 Norwegian Research Council funded NORCICS Project –310105