This repository contains the firmware and hardware required to perform a Voltage Fault Injection attack on Freescale/NXP MC68HC908 microcontrollers. The tool allows you to bypass the Monitor Mode authentication phase and recover the interrupt vectors (which act as the security password), enabling a full dump of the flash memory.
⚠️ Legal Disclaimer: This project is intended for educational purposes, academic research, and recovering data from legally owned and obsolete devices. The authors are not responsible for any damage or illegal use of this tool. Do not use this framework on systems you do not own or do not have explicit permission to evaluate.
- HC08 Fault Injection
While working on a project for my own car, I needed to analyze the central locking system, which is controlled by various MCUs, including a Freescale (now NXP) HC908 microcontroller. To implement new functions on a custom chip that would replace the original, I first needed to understand exactly how the original firmware handled communication and logic.
Deep-diving into the MC68HC908 datasheets revealed the MON08. The Monitor Mode consist in a built-in interface for debugging and programming. However, I immediately encountered a significant security hurdle. Accessing the full command set (including memory readout) requires an 8-byte (64-bit) authentication sequence. Given the protocol's timing constraints, a brute-force approach is mathematically and practically impossible.
I began investigating how professional automotive programmers (such as Multi-Prog or ETL 908) bypass this security. My research suggested that these tools often rely on pre-defined dictionaries of known passwords or vectors used by specific manufacturers. Unfortunately, I couldn't gather more information, as these tools are strictly closed-source, and I didn't have access to them to analyze their inner workings.
This led me to explore scientific literature demonstrating techniques to bypass chip security through hardware attacks, specifically Simple Power Analysis and Fault Injection.
To ensure a controlled environment and avoid damaging the original MCU during the tests, I began the development phase by purchasing an MC68HC908QY4A as a reference target. Since I could reprogram this chip at will, I had full knowledge of its security sequence. This allowed me to calibrate the glitch timing, analyze the power consumption profiles, and validate the attack success rate before moving to the actual target.
While the vulnerabilities of the HC08 architecture have been known and exploited for years, I found a lack of documentation regarding Fault Injection on this specific family. To my knowledge, this is the first documented case of a successful voltage glitching attack on the HC908, especially using non-professional equipment.
My setup consisted of a basic 24MHz WeAct logic analyzer, a Hantek DSO5102P and an STM32F401 Nucleo board.
The following information was collected from the Section 15.3 of the MC68HC908QY4A Datasheet
To force a programmed MCU into Monitor Mode, the following conditions must be met:
- The voltage on the IRQ pin must be at least
$V_{TST} = V_{DD} + 2.5V$ . - Specific GPIO pins must be tied to logic levels that depend on the target chip. For the QY4A, the configuration is
PTA0 = 1,PTA1 = 1, andPTA4 = 0.
Once powered on with these conditions, the chip enters MON08 and waits for an 8-byte security sequence. If correct, the Flash memory is unlocked, otherwise the read commands are locked, and only a mass erase is allowed to permit reprogramming.
MC68HC908QY4A Entry conditions:
| Mode |
|
|
Reset Vector | PTA0 | PTA1 | PTA4 | External Clock | Bus Frequency | Baud Rate |
|---|---|---|---|---|---|---|---|---|---|
| Normal Monitor | X | 1* | 1 | 0 | 9.8304 MHz | 2.4576 MHz | 9600 | ||
| Forced Monitor | X | $FFFF (blank) | 1* | X | X | 9.8304 MHz | 2.4576 MHz | 9600 | |
| Forced Monitor | X | $FFFF (blank) | 1* | X | X | X | 3.2 MHz (Trimmed) | 9600 |
*PTA0 must have a pullup resistor to
Note: After a standard reset (pulling the
$\overline{RST}$ pin to GND), the MCU will still ask for the security bytes, but it will not evaluate them. To properly trigger the security evaluation, the reset must be triggered by a Power-On Reset (POR), obtained by pulling the$V_{DD}$ pin approximately to 0V.
In programmed state, standard MON08 requires a 9.8304 MHz external clock to communicate at a standard 9600 bps.
To minimize external components and maintain precise control over the glitch timing, the target clock is generated directly via an STM32 timer.
During the fault injection phase, the clock is generated at a more conservative frequency of 4 MHz. This yields a baud rate of 3906 bps. Running at a lower frequency provides a wider margin of error when tuning the glitching parameters. If the target allows it, during the dumping phase, the clock can be generated at a higher frequency like 8 MHz.
During MON08 communication, every command and security byte sent to the MCU is followed by a hardware echo to confirm reception.Note: The baud rate is equal to
$\small{CLK/1024}$ if using an external clock.
After 256 bus cycles from power-up, the chip is ready to receive the 8-byte authentication key. Following the echo of the 8th byte, the MCU transmits a BREAK signal.
It is important to note that this BREAK merely confirms that the authentication phase is over, not that the password was correct.
To verify a successful unlock (or a successful glitch) it's possible to read a protected memory address, such as the Reset Vector at 0xFFFE-0xFFFF. If the memory is locked, the MCU actively masks the output and returns 0xAD for every byte. If we read anything other than that, the security bypass was successful (It's very unlikely that the Reset Vector points to an address starting with 0xAD).
Note: The 8 authentication bytes are compared against the Flash memory content at addresses
0xFFF6-0xFFFD. These locations represent the interrupt vectors, which are the memory addresses pointing to the handler functions for the MCU's various peripherals.
Once authenticated, MON08 allows interaction via basic READ and WRITE commands, as well as the ability to execute small RAM applets via the RUN command. To significantly reduce communication overhead when handling consecutive memory blocks, the Monitor ROM also implements IREAD (Indexed Read) and IWRITE (Indexed Write) commands.
Official tools like CodeWarrior rely heavily on these custom RAM applets to program the chips, because MON08 does not natively support direct Flash programming.
At the current time, this repository focuses solely on firmware dumping and glitching. However, the underlying mon08.c driver implements all the aforementioned commands, allowing you to write your own flashing applets if desired.
If you need to reprogram the chip after extracting the security bytes, it is highly recommended to use the dumped key alongside CodeWarrior and a standard serial adapter as proposed in the datasheet (it doesn't require expensive programmers!).
Initially, two classic side-channel approaches were evaluated: the Timing Attack and Simple Power Analysis (SPA). Due to the countermeasures implemented in the microcontroller's ROM, these methodologies proved impractical.
This type of attack is among the simplest and involves measuring the time the CPU takes to validate the password. By analyzing how the response time varies, it would theoretically be possible to deduce the key one byte at a time. However, the Monitor ROM executes this check in constant-time, taking the exact same number of clock cycles regardless of data correctness.
By inserting a shunt resistor between the power supply and the chip's
Even in this case, the outcome was not as hoped. The security bytes evaluation is most likely performed using cumulative logic, executed in bulk only at the very end of the data reception cycle.
A possible internal implementation of the ROM could look like this:
uint8_t input[8];
uint8_t secret[8] = {...};
uint8_t error_flag = 0;
// Receive the eight authentication bytes
for (uint8_t i = 0; i < 8; i++) {
receive_byte(&input[i]);
send_echo(input[i]);
}
// Check the security bytes in constant time (no branching)
for (uint8_t i = 0; i < 8; i++) {
// Thanks to this logic evaluation, the current footprint is almost the same for each byte
error_flag |= (input[i] ^ secret[i]);
}
// Evaluate the error flag only if authentication is done after a power-on reset
if (is_POR()) {
if (error_flag != 0)
disableFlash();
else
enableFlash();
}
send_break();Because of this structural design, deducing the compared bytes and identifying the exact clock cycle in which the error flag is activated would require the much more advanced Differential Power Analysis (DPA) technique, rendering SPA ineffective.
Note: If a differential probe is not available, properly measuring the high-side current requires powering the test circuit with a ground reference isolated from the oscilloscope's ground. This allows referencing the oscilloscope's GND to the circuit's positive power supply and connecting the probe to the other end of the shunt resistor attached to the chip's
$\small{V_{DD}}$ pin. The simplest and safest way to achieve this galvanic isolation is to power the target circuit using a laptop disconnected from the mains (running on battery power).
The SPA results were crucial for understanding the precise timing of the authentication process. By using a Python script to plot the power consumption profiles measured during authentication, two distinct behavioral scenarios emerged:
This data allows us to pinpoint the exact moment the chip evaluates the security sequence and decides whether to enable the Flash. In the graph above, the time reference t = 0 marks the exact moment the MCU finishes transmitting the final echo byte (1 start bit + 8 data bits + 1 stop bit).
The security evaluation occurs immediately after this point. Following a delay equivalent to 2 UART bits, the MCU sends the BREAK signal. It is precisely within this predictable, narrow time window that a voltage glitch can be injected to corrupt the evaluation instruction and forcefully unlock the Flash memory.
The glitch is physically injected by triggering a MOSFET that shorts the microcontroller's
However, the HC08 features an extremely fast internal Power-On Reset (POR) circuit. Consequently, even when generating the shortest possible glitch (at 72 MHz, about 15 ns theoretically, which stretches to a few hundred ns in practice due to the package's parasitic capacitance), the chip will reset, thwarting the attack.
To mitigate this effect, a 22-ohm resistor was placed between the main power supply and the chip's
The schematic is simplified and was built using the few components I had available as a university student away from home. Despite this, it is more than sufficient to successfully perform both the glitch and the memory dump.
| Nucleo Pin | STM32 Pin | Signal Name | Description |
|---|---|---|---|
| D2 | PA10 |
POWER_N |
Drives the NPN transistor for target power control. |
| D3 | PB3 |
POWER_P |
Drives the PNP transistor for target power control. |
| D4 | PB5 |
GLITCHER |
Triggers the MOSFET crowbar for fault injection. |
| D5 | PB4 |
OSC_TRIGGER |
Dedicated trigger output for oscilloscope synchronization. |
| D8 | PA9 |
UART_MON08 |
Half-duplex serial communication with the target's MON08 interface. |
| D10 | PB6 |
CHARGE_PUMP |
PWM output to drive the high-voltage charge pump. |
| D12 | PA6 |
HC08_CLOCK |
Target clock generation. |
- Target Power Control: Instead of the push-pull transistor stage (BC337/BC327 NPN-PNP pair), a dedicated gate driver or a complementary pair of MOSFETs could be used for sharper switching, but the bipolar solution works adequately.
- Voltage Generation: The charge pump operates at 10 kHz with a 50% duty cycle. When driven from the 3.3V logic supply, it generates a voltage that is safely clamped to 6.3V by the Zener satisfying the threshold to trigger Monitor Mode. A more ideal approach would be to drive it with a suitably filtered buffer to avoid stressing the STM32's GPIO output pin.
- Glitcher (Crowbar) Placement: The MOSFET acting as a crowbar should ideally be placed as close to the target's VDD and GND pins as possible to minimize parasitic inductance. However, because the MC68HC908QY4A is susceptible to relatively wide glitch pulses (around 10-20 µs), parasitic effects are less critical. For this target, the entire circuit can be successfully built and operated directly on a standard breadboard.
The driver located in the mon08 directory provides the core interface to the MC68HC908 Monitor Mode, leveraging the STM32's serial peripheral.
-
Bare-Metal UART (
mon08_uart.c): During transmission and reception, serial bus access is performed directly via control and status registers. This completely bypasses the HAL overhead, ensuring precise control during the glitching phase, since the critical timing reference is strictly tied to the exact moment the final security byte is transmitted. -
Dynamic Clock & Baud Rate Generation: Target's clock is generated via a hardware timer (PWM). The driver dynamically calculates and initialize the UART speed based on the generated frequency. This allows on-the-fly switching between conservative speeds for glitching (e.g., 4 MHz) and faster speeds for memory dumping (e.g., 8 MHz). Clock generation can also be disabled if the target is driven by an external clock source, such as a function generator.
-
Power & Charge Pump Control: Handles the physical entry conditions for Monitor Mode. It manages a PWM-driven Charge Pump to generate the high voltage (
$V_{TST}$ ) required on the$\overline{IRQ}$ pin. Furthermore, it manages the target's$V_{DD}$ line with three states:ON,OFF(to force a Power-On Reset), andHIGH-Z(floating state, used to insert the 22-ohm resistor into the circuit for the glitch attack). -
Protocol Commands: Fully implements the
READ,WRITE,IREAD,IWRITE, andRUNcommands, allowing the user to seamlessly read and write the memory area, as well as execute small RAM applets. -
Glitcher Module (
mon08_glitcher.c): Responsible for executing the fault injection attack. It includes a dedicated trigger signal that can be connected to an oscilloscope to observe the exact moment the glitch occurs. -
Log-Friendly: Designed to facilitate comprehensive logging, allowing real-time monitoring of the glitching progress and providing immediate feedback to properly tune the glitching parameters without requiring external instruments. The
mon08_strings.hutility header translates protocol statuses and configuration enumerations into human-readable strings for clear telemetry and console debugging. -
Cross-Platform Compatibility: Designed to be portable across different STM32 families. Currently, it has only been developed and tested on the Nucleo F401RE.
Adapting the driver to a specific board requires populating the Mon08_Config_t structure, which supplies the necessary STM32 peripherals and pins to the driver.
The configuration is shared among the different applets and is located in mon08_config.h. For a detailed description of each configuration parameter, refer to the inline documentation provided within the mon08.h header file.
Note: The glitcher parameters and functions are only compiled if the
MON08_ENABLE_GLITCHERmacro is defined inmon08.h. This allows you to compile a lightweight version of the firmware solely for memory dumping if fault injection is not required.
The firmware is organized into modular applets to separate the hardware initialization code (generated by STM32CubeMX) from the application logic. This architecture allows adding new applets without creating redundant projects and facilitates porting the codebase to different STM32 boards by providing a new CubeMX hardware configuration. The selection and compilation of the desired applet is managed through CMake Presets defined in the CMakePresets.json file.
The glitcher module located in Glitcher folder is responsible for orchestrating and logging the voltage fault injection attack. If the glitch is successful and the chip is unlocked, the applet automatically extracts the 8-byte security password that can be used to dump the target's memory.
The dumper applet located in Dumper folder is designed to extract the target's memory regions and output the result over the serial console in the standard Motorola S-record (.s19) format.
This format allows users to copy and paste the serial output directly into a text file that can be imported into CodeWarrior or a reverse engineering tool like Ghidra.
The specific memory ranges to be extracted are defined within mon08_memory_defs.h. Since the memory map varies across different HC08 models, refer to the specific microcontroller's datasheet to determine the correct Flash/ROM address ranges to dump.
To develop and interact with the system, the following tools are required:
- Editor: Visual Studio Code
- VS Code Extensions:
- STM32 VS Code Extension (for project management and debugging).
- Serial Monitor (to monitor glitcher and dumper output).
- Alternatives: The code can be imported into STM32CubeIDE as a CMake project. In this case, an external serial terminal that supports console commands, such as PuTTY or minicom, is necessary.
-
Open the repository folder with Visual Studio Code.
-
When the STM32 extension detects the project, accept the configuration and enter the information for the development board in use.
-
If prompted by CMake, select the
CMakeLists.txtfile located in the root of the project. -
Select the CMake Preset corresponding to the desired applet (e.g.,
F401RE-DumperorF401RE-Glitcher). -
Connect the STM32 board to the computer and run the Flash firmware task.
The fault injection attack requires precise calibration to identify the operational threshold of the target processor.
-
Software Configuration: Select the Glitcher CMake Preset and flash the board.
-
Hardware Configuration: Connect the 22-ohm resistor between the power source and the chip's
$V_{DD}$ pin. -
Calibration: After powering the circuit, monitor the serial logs. Adjust the multi-turn potentiometer until the
NO_BRKcount (indicating a triggered Power-On Reset) begins to alternate with theUNAUTHcount (indicating a failed authentication attempt without reset). The ideal bypass point is on the POR activation threshold; the tuning is correct when most (but not all) attempts returnUNAUTH. -
Tuning: If the glitch does not result in an unlock, empirically adjust the pulse parameters in
firmware/App/Glitcher/app.c, as susceptibility varies between different chip models.
Once the authentication code has been recovered via the glitcher, proceed with full data extraction.
-
Key Configuration: Enter the recovered authentication code into the Dumper applet source code located in
firmware/App/Dumper/app.c. -
Memory Mapping: Ensure the active memory map matches the target chip's datasheet. If a corresponding map does not exist, define the required memory regions in mon08_memory_defs.h and select it within the dumper code.
-
Firmware Update: Change the CMake build preset to Dumper, remove the 22-ohm resistor to restore direct power, and flash the board.
-
Export: Wait for the dump procedure to complete. Copy the serial output (enclosed between the start and end delimiters) into a text file and save it with the
.s19extension. -
Analysis: The resulting Motorola S-record file can be imported directly into tools such as CodeWarrior or reverse engineering suites like Ghidra.
The project has been successfully tested on the following targets:
-
MC68HC908QY4A: Security bypass is typically achieved in approximately 10 seconds. The attack is highly repeatable.
-
MC68HC908RF2: This model is significantly more resistant to the attack. After extensive parameter tuning, access was achieved after several hours of attempts. The process is less repeatable compared to the previous target and requires precise pulse width calibration.
The methods used and the results obtained were heavily inspired by the following academic material. I recommend referring to these resources to better understand the method and attack strategies used:
-
Bozzato, C., Focardi, R., & Palmarini, F. (2019). Shaping the Glitch: Optimizing Voltage Fault Injection Attacks. IACR Transactions on Cryptographic Hardware and Embedded Systems (TCHES), 2019(2), 199–224.
-
Skorobogatov, S. (2005). Semi-invasive attacks – A new approach to hardware security analysis. Technical Report UCAM-CL-TR-630, University of Cambridge, Computer Laboratory.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
The screenshots and diagrams from the MC68HC908QY4A datasheet included in this documentation are the property of NXP Semiconductors (formerly Freescale). They are used here under Fair Use for technical explanation, documentation, and educational purposes. The full datasheet can be found at the NXP official website. All other product names, logos, and brands are property of their respective owners.





