sighax and boot9strap
Presentation by SciresM
A Short Summary
At 33c3, we learned the following from derrek:
- boot9 has a broken RSA verification implementation.
- It's broken because the ASN.1 parser incorrectly verifies at least one of the length fields.
- We can't perform sighax ourselves, because we can't get the details required from boot9's parser, because we don't have boot9.
What can we do with that?
A Blast from the Past
- Nintendo loves reusing concepts and code. Firmware has to parse RSA signatures, too.
- Initial examinations of NATIVE_FIRM, TWL_FIRM and AGB_FIRM look not vulnerable – though the ASN.1 parser looks very similar to what was described at 33c3, there are stringent padding checks in place.
- Checks against the sighax vulnerability are present in firmware as early as 0.14 (1.0.0-0), from January 2011.
- The checks aren't present in firmware earlier than that, including 0.13, which is factory firmware.
- Factory firmware is vulnerable to sighax.
Factory firmware RSA verification
The checks were added in firmware 1.0.0-0.
This means Nintendo knew about the vulnerability when making the New 3DS, and did not fix it.
Exploiting a parser, blindly
- The parser in factory firmware isn't exactly the same as the one in boot9, as learned when a "perfect" signature for factory firmware's parser failed on boot9. What's next?
- Testing a signature that overflows the factory firmware parser into data-aborting causes the console to show a black screen instead of bootrom error. This means we can crash the bootrom.
- On factory firmware, the "calculated" hash is on the stack near the signature being parsed. This is probably the case for boot9.
Exploiting a parser, blindly
- There are only 128 possible locations, relative to the signature, that can be brute forced in reasonable time. It has to be one of those.
- Sure enough, brute forcing signatures for each location shows the "calculated" hash is immediately after the signature on the stack. So we have sighax.
- For those interested in the (complex) math behind optimizing the sighax brute-force, Myria made an additional presentation.
The bad ASN.1 Parser
How it looks to the parser
So we have sighax. Now what?
We dump the bootroms, of course!
Exfiltrating boot9
- So we can fakesign our own FIRMs.
- Meaning we can copy our payload almost anywhere.
- boot9 has a blacklist of ranges... but we know it's not perfect.
- From 33c3, only the boot9 data regions are blacklisted.
- Can we find a region that isn't a boot9 data region but is still dangerous?
ARM9 Memory Map
Region | Address | Size | Description |
0 | 0x20000000 | 0x08000000 | FCRAM |
1 | 0x10000000 | 0x10000000 | I/O Registers |
2 | 0x08000000 | 0x00100000 | ARM9-only internal memory ("arm9mem") |
3 | 0x08000000 | 0x00000400 | arm9mem (different permissions, details irrelevant) |
4 | 0xFFF00000 | 0x00004000 | Data tightly-coupled memory (DTCM) |
5 | 0x07FF8000 | 0x00008000 | Instruction tightly-coupled memory (ITCM) |
6 | 0xFFFF0000 | 0x00010000 | Boot9 |
7 | 0x1FFFE000 | 0x00000800 | AXI WRAM |
NDMA
- We can copy anything almost anywhere.
- This includes I/O registers.
- The NDMA engine is a memory mapped I/O register. This means we can copy data over the NDMA registers, triggering DMA, letting us copy anywhere.
Oh.
NDMA Parameters
For an NDMA copy request, we need to set:
- the global control register to
high priority
,
- the source address (
0xFFFF8000
, the address of the protected boot9),
- the destination address (any safe place in arm9mem will do),
- how much data to transfer (32 KiB, or 8192 words)
- some timing data
- how much to transfer per cycle
- And now we just copy that to
0x10002000
for a copy request!
Works for me, too
SHA-512 (boot9):
5addf30ecb46c624fa97bf1e83303ce5
d36fabb4525c08c966cbaf0a397fe4c3
3d8a4ad17fd0f4f509f547947779e1b2
db32abc0471e785cacb3e2dde9b8c492
boot9strap: Reliable boot9/boot11 code execution
- We can copy data anywhere during firm loading.
- Including:
- the exception vectors (using NDMA to bypass the blacklist), and
- NULL.
- That's all we need for a data abort, isn't it?
- It is!
boot9strap: Big picture idea
- Section 0: Copy an ARM11 payload into AXI WRAM.
- Section 1: Copy an ARM9 payload into arm9mem.
- Section 2: Copy a payload over the NDMA registers that overwrites the data abort vector in arm9mem.
- Section 3: Load anything to NULL.
- ???
- Profit!
boot9strap: Technical implementation
- Getting execution during boot9 via data abort is really cool. But it'd also be nice to get execution under boot11. How can we?
- boot9 dereferences some function pointers from DTCM, and calls them if they aren't NULL (they normally are).
- Our poisoned data abort vector can overwrite two of these to point at our code, then return to boot9 and let it resume normally.
boot9strap: Technical implementation
- Later on, boot9 will call the first of those function pointers (
0xFFF00058
). This will wait for boot11 to finish a task by watching axiwram, then overwrite a function pointer (0x1FFE802C
) it will call later.
- Immediately before lockout, boot9/boot11 will each dereference function pointers we have poisoned (
0xFFF0005C
, 0x1FFE802C
respectively).
- We can execute arbitrary code before bootrom lockout under both boot9 and boot11.
- Bootrom dumps for all!
Works for me, 2: Electric Boogaloo
SHA-512 (boot11):
c3f5044321f1ec5a33e09dd021e1117b
1b663e37673222944a06b119ea70af92
fc6de8547129582131fb9f8896edef7e
9a8ef77295c627e0f1cb360b15b533b4
Bonus fail
- Upon disassembling boot9, we notice another huge flaw in the bootrom that wasn't mentioned at 33c3.
- Before trying to boot from NAND, the bootrom checks to see if a key combination (Start + Select + X) is being held, and whether the shell is closed.
- If so, it tries to boot from an inserted NTR (Nintendo DS) cartridge.
Bonus fail
- Combined with sighax/boot9strap, this allows one to make a malicious fake DS cartridge, so that holding down a button combination on boot gives you bootrom code execution.
- Nintendo tried to make it not possible to abuse by requiring the shell to be closed...
- But you can just use a magnet.
- This, like sighax, is also not fixable.
- The NTR cartridge was likely meant to be used for either the factory setup or as a means of recovering bricked NANDs. However, we'll never know for sure.