Dumping a protected MC68HC705C8S

This is the writeup which goes with my 68HC705C8 Glitcher Github project.

I'm involved with some of the reverse-engineering side of HackTV development, and as part of that I tear apart receivers so we can generate the data formats they need for e.g. EPG data and conditional-access. You can see some of that work in the HackTV part of this website.

In the early 2020s someone loaned us a BBC Selector, which is a decoder for the short-lived BBC Select service – an overnight pay-service run by the BBC to distribute training material to several professions. These are VideoCrypt-family decoders but with some key differences:

  • Video scrambling is based on line shuffling (like SYSTER), not line cut-and-rotate.
  • An audio spectrum inversion scheme has been added, which usually means scrambled VHS recordings of Select signals have no audio.
  • An infrared “blaster” to control an external video recorder

We wanted to learn more about the Selector and how it implemented certain features, so the MCUs had to be dumped. Dumping the Verifier (the smartcard interface processor) was easy, it was another unprotected 8052. There were also a pair of MC68HC705C8 processors which needed to be dumped (we believe one handles the IR Blaster and box user interface and the other handles decoding of the VBI data).

The standard Videocrypt boxes contained an MC68HC05 series mask-ROM processor which handles VBI decoding. These can normally be dumped with Non-User-Mode (NUM mode) attacks, as documented by Sean Riddle.

The 68HC705 series processors have a programmable EPROM program memory. Clearly there needs to be a way to program and verify this: to that end, the 68HC705C8S has an onboard ROM bootloader in the last few hundred bytes of program memory. Applying a high voltage to one pin while shifting others in level causes the CPU to shift the reset vector down by 16 bytes, entering the bootloader.

The bootloader would normally read bytes from an external EPROM and program them into the internal ROM. Some commercial programmers worked like EPROM emulators, with a RAM which could be disconnected from the 68HC705 and loaded with data, then connected and used to load the 68HC705's program memory.

I started by looking for as much information as I could find on previous attacks, and found that there was a previous known attack which involved launching a timing attack on the 68HC05 microcontroller Test ROM's Verify ROM function. Unfortunately this isn't viable on the 68HC705C8, because these have the Bootstrap ROM in place of the Test ROM.

The bootloader code for later mask sets (1C11C, 2C11C, 3C11C, 6C11C, 7C11C, and 9C11C) is given in the MC68HC705C8,C8A Technical Update.

At the start of execution, it runs this code sequence:

START   EQU     *
*
* FIRST CHECK FOR SECURITY AND HANG IF ENABLED
*
        LDA     OPTION
        AND     #%00001000
        BEQ     NOSEC
        STOP
*
* THEN CHECK PORT D, BIT 2, TO SEE IF USER WISHES TO JUMP TO
* RAM OR JUMP INTO THE BOOTLOADER PROGRAM.
*
*
NOSEC   BRCLR   TEST,PORTD,BOOT
        JMP     RAM+1                GO TO RAM PROGRAM AT $0051

Essentially this checks the security bit in the OPTION register, and stops the processor if it is set.

This leaves a point of attack: if we can make the CPU skip the STOP instruction, we will fall into the NOSEC path (MCU not secured). Motorola MCUs have long been known to be vulnerable to clock and power fault-injection attacks (see Skorobogatov, 2005); clock faults in particular can cause instructions to be skipped.

Execution of a STOP instruction is also leaked externally in two ways:

  • The CPU will stop executing instructions until it is reset or receives an interrupt. This means the power consumption will drop to a maximum of 50μA – far less than the 4.7mA typical operating current.
  • The internal oscillator will also be stopped by disabling the oscillator gate (MC68HC705C8/D fig. 2-1), causing the OSC2 output to go idle.

The loss of the OSC2 output is very easy to detect, without the need to monitor the supply current of the 68HC05C8. For that reason, I chose to use it as a monitor.

I started by enabling security on a UV-erasable 68HC705C8, and counted the number of instruction cycles (clock pulses) it took between releasing RESET to the OSC2 output shutting down. I was expecting around fifty clocks at most but actually measured around four-thousand. Worst of all, it was inconsistent: the reset pin timing affected it, among other things.

I quickly noticed that if I held the reset line active for more than 4096 CLK1 clocks, this variability went away. This led me to realise there was a power-up timer in the reset path, and some things about its implementation:

  • Its reset was edge-triggered, meaning an active-going edge on the RESET pin would reset the timer, but holding the line active would not.
  • Its output was logically ORed with the incoming level-sensitive reset pin.
  • It had a period of around 1024 clocks.

After reviewing the MC68HC705C8 technical datasheet, I found the answer. Section 3.1.1 “Poweron reset” shows the power-on timer circuitry, and explains that it is active for 4096 CPU execution cycles. This is 8192 external clock cycles, but also explains the variability. The CPU cycle divider is not reset when the CPU is reset, so its state is neither known or controllable externally.

Now I had the explanation, I felt comfortable leaving the workaround (holding RESET active for more than 1024 external clock cycles) in place.

I found that the Arduino microcontroller I was using couldn't generate the glitch pulses I wanted, so I dug out an old FPGA Arcade CPLD demo board. This had a MAX7000S FPGA which could accept and generate 5V signals. On it, I implemented an SPI buffer to store the timing values, a state machine to sequence the glitch, and a trigger based around the microcontroller being released from reset.

The glitch search is done with brute force, but with narrowed coverage: I calculated the expected position for the glitch by adding up the cycle counts of the instructions which were executed. I expected that breaking either the LDA, AND or BEQ instructions would be required for a successful glitch. The goal was to always take the BEQ jump or cause another 1-cycle instruction to execute in place of the STOP instruction. These would give the same outcome either from taking the jump, or falling through.

The final glitcher code clocks the microcontroller to somewhere close to the point required, then varies the number of clocks, glitch phase (relative to the clock) and glitch width until the MCU skips past the security check. Thankfully this is easy to spot: it starts sending the program code over the serial port.

I found that one MCU glitched successfully at 25 clocks, while the other did at 27 clocks. For both the successful glitch was at zero phase to the clock. Curiously the 27-clock chip also needed a wider glitch (8 ticks) whereas the 25-clock chip succeeded with 3 ticks. Clearly there is some variability between chips from different batches.

The processor actually stops executing instructions after 30-31 clocks if we don't glitch. Looking at the instruction cycle timings in the datasheet, we have the following timings:

Instruction Cycles
LDA OPTION (LDA $1FDF) 4
AND #%00001000 2
BEQ NOSEC 3
STOP 2

Going by the 3-to-6 clock cycle difference (30 or 31 clocks less 27 or 25), the glitch is likely hitting the AND or BEQ instruction. Without seeing the internal state of the CPU during the glitch, it's hard to say with certainty what happened. There are many options, which include:

  • The glitch was in the AND opcode fetch stage: an incorrect instruction was executed which cleared the zero flag.
  • Glitch was in the AND instruction operand fetch stage: the value read in was a zero, or a value which had set bits which didn't line up with set bits in the OPTION byte.

The 68HC05C8 (Mask ROM) has a Test ROM in place of the Bootstrap.

Triggering the Test ROM is covered in “68HC05C8 Advance Information”, section 2.5 (PDF page 21, page 2-9). It's performed by applying 9V to /IRQ via a 4k7 resistor, and 5V to TCAP via another 4k7. Triggering a reset will start the selftest.

The 68HC705 and 68HC805 series microcontrollers have a Bootstrap in place of the Test ROM.

The PM48 expects to have a dump of the entire 68HC05C8 memory map loaded in. It expects I/O and RAM areas to be set to zero, which will cause them to be skipped. If any of the bytes are set to a non-zero value, the programming process will fail (specifically, a verification failure).

If an unprotected device is read with the PM48, the process will take a fairly long time (about 30 seconds), and data will be present in the buffer. In contrast, a read of a protected device will return almost immediately.

In short – if you read an unknown 68HC05C8 with the PM48 and the process returns almost immediately, then the device is protected. PROMDRIVER will not generate an error message for this: you're left to figure it out by yourself.

Find me on Mastodon
  • Last modified: 2024/11/24 01:13
  • by philpem