Notes from inside your Wii

HackMii header image 2


June 15th, 2008 by bushing · 13 Comments

boot1 is the second stage of the Wii’s bootloader. It lives at the beginning of flash; it is encrypted by AES, using a fixed key. It is hashed using SHA1, and verified against a hash that is burned into OTP memory inside the Hollywood during manufacturing. Therefore, boot1 can be changed in a Wii before it leaves the factory, and new Wiis could have a new version of boot1 — but it’s not possible to upgrade or modify boot1 in an existing Wii.

Fortunately, there is at least one bug in boot1 — the strncmp / hash verification bug — and this is what makes all of our firmware hackery possible.

If you want to look at boot1 yourself (to follow along), grab the first few kilobytes of any Wii NAND Flash dump, strip out the spare data (0x40 of ECC data after every 0x800 block), and then decrypt it with a command like:

openssl enc -d -aes-128-cbc -K 9258a75264960d82676f904456882a73 -iv 0 -nopad -i boot1-encrypted.bin -o boot1-decrypted.bin

You should end up with 17184 bytes. This is much much larger than boot0, and is already to the point where it’s difficult to follow all of the code by just staring at a disassembly. That space is broken down about like so:

1167: initialization code; AES, SHA, signature checking, NAND, ECC functions
2336 bytes: main(), described below
6134 bytes: low-level hardware setup code (to configure the DRAM, talk to the SEEPROM, initialize GPIO pins, etc)
3850 bytes: RSA verification code
2816 bytes: Library code: strncmp, memcpy, printf (!)
872 bytes: Data, including jumptables, the common key (why?!) and the public half of the Root key.

boot1 is interesting to us because it is the first vulnerable code in the Wii. It’s what decides whether or not a hacked boot2 will run. So, we must understand all of the checks it makes if we want to construct a boot2 that will be allowed to run.

[… several days pass …]
Analyzing boot1 has proven much more difficult than I had feared, so I’m just going to post my disassembly for those who are interested. I’ll follow up soon with the output of SkyEye, which I will post with an explanation of what is actually happening.

Disassembly: boot1.txt

Update: I’ve had some requests for it, so here’s the binary of boot1: boot1-dec.bin

And here’s an IDC file: boot1.idc

Load boot1-dec.bin into IDA Pro (I use 5.2) as an “unknown” file, set processor type to ARMB (ARM Big-Endian), and set it to load the file to 0x0d400000. Once it has loaded, run the IDC file, and you should have something resembling my IDB file. Feel free to post with any questions or ideas.

Tags: Wii

13 responses so far ↓

  • 1 LittleStevie // Jun 16, 2008 at 4:21 am

    This is very interesting,

    unfortunatly i dont understand ARM assembly 🙁

    The biggest question i have here is the legalities behind hosting the IDC, Disassembly TXT, and the Binary

  • 2 HyperHacker // Jun 20, 2008 at 1:19 am

    printf? So where does it print to?

  • 3 factory 2 // Jul 7, 2008 at 8:43 pm

    […] at the contents of the NAND flash, boot1 is unchanged on both units.  This is great news — Nintendo has now shipped 28+ million […]

  • 4 cloned // Mar 24, 2009 at 12:56 pm

    first of all i’d like to thank you for the infos collected here n there about wii boot chain ..

    Reading here ‘n’ there about bootmii stuff,
    I got the information (don’t know if it’s wrong) and where it came from (somebody got a boot zero dump ? can I have a look to it ?? )

    Well, the point is ..
    1) boot0 checks boot1 against the hash inside OTP
    2)if hash in OTP is ZERO the check is skipped
    3) and if theres no protection about write more than once the OTP (didn’t see anything about that)

    then is just matter to write all zero in place of the OTP hash and is done.. easy isn’it ?

    my assumption is .. standard OTP bits are default to 1 … (was common to leave some space as FF in early processors working only with OTP as ROM , so you can done changes later bay changing these virgins locations )

    if theres no protection against write OTP more than once and the magic string is all ZERO then would be fantastic ..

  • 5 bushing // Mar 25, 2009 at 3:06 am

    OTP is “One-Time Programmable” memory. By definition, we can’t write OTP more than once…

  • 6 cloned // Mar 25, 2009 at 10:57 am

    Sorry , but I don’t agree …

    I don’t know how old you are .. so don’t take it wrong please .. and maybe just take it as a tip if you didn’t investigate already this way

    I did write many times over and over to many OTP devices , then I got others OTP were that wasn’t possible but usually because an additional LOCK (fuse or whatever)

    as background ..

    first OTPs devices were PROMs
    (guess you already know the meaning of)

    then came the era of EPROMs then the one of EE2PROMs and EE2 devices in general (FLASH)

    at least some years ago you could get as sort of PROM a OTP device, which in turns results in a lot of fuse pulled to a pullUp resistor giving to the corresponding BIT the meaning of 1 unless you blow the fuse …

    today you can still get OTP as a lot of fuse to blow or as a EE2 chip with a lock to make the further writes impossible ,
    but in any case if the OTP is made of a lot of fuse they use to be pulled up to 1 as default,
    which in turns let you can blow their fuse unless all of their fuse are blowedup
    (this was an usefull trik for developers of firmware stored in OTPs because in fact let u write many version of programs in the same OTP as long there is enaugh space free space to blow as 00 wich in many case result to be equivalent of a NOP opcode)

    so my question in fact was
    1) is the wii OTP made of fuse or what ?
    2) theres a lock to block further writes to it
    3) if yes , it’s really locked or not ?
    4) anybody try to rewrite some bit of it ?

    many thanks,

  • 7 marcan // Mar 25, 2009 at 11:07 am

    1) probably
    2) almost certainly
    3) almost certainly
    4) no, since you’d probably brick your Wii

    There’s a difference between OTP devices used for program storage, and OTP areas used for secure key storage. The latter tend to have security mechanisms like (gasp) a write protect fuse that when blown prevents further writes.

    It is almost certain that the OTP is burned early during the manufacturing process and then a fuse is blown to lock it. But even IF you could flip bits from 0 to 1, it’s of no use because you’d still need to brute force half of the boot1 SHA-1 bits, which is infeasible.

    If boot0 checks for an all-zero OTP hash then zero is almost certainly the blank state for this OTP.

    Conclusion: maybe there’s a way to exploit this, but the chances are very slim. If someone wants to provide 5 or 6 Wiis to attempt to perform OTP write experiments, we’ll gladly try it out.

  • 8 cloned // Mar 25, 2009 at 2:39 pm

    thanX ,

    this was +/- the answer was looking for …

    don’t worry about my knowledge with OTP devices, I’m proud to be the designer of a board for ISA BUS tha only (ONLY) using OTP devices (PLA) (very old stuff hehe) can let you introduce hardware breakpoints in any x86 uP mounted in any ISA (old stuff as well ) compliant motherboard

    as complement to my CV , I’m an ARM enthusiast ,which owns a Archimedes A310 since 1987 (wow 22 year ARM story ,shit i’m getting old)

    and finally I do manage crypto stuff each day,so I know very well the math meaning of SHA-any

    so my idea ,was not ,of course , to act as kamikaze and to go stright to change directly the SHA-1 hash
    (BTW , why do they check correctly SHA1 in boot0 then use a flawed check in boot1 ?)

    I saw in a wiki a list of locations which is suposed
    they are in the OTP area, inside this list ther is at least 1 which maybe can allow you to check if OTP protection is really ON

    (9 NG id , for example looks like a place where you can try to flip a bit without briking your wiii)

    as you state , if the default of OTP looks like to be ZERO , then probably isn’t made of fuse and instead is a protected EE2 area, so if you try to flip an innocent BIT without risk of briking the wii then later you can write all ZERO in SHA1 hash ..

    Ok, I know, looks like too much speculation, but also boot1 flaw to anybody knowing SHA1 looks like to be impossible , isn’it ?

    so why do they can’t have also leaved de lock of OTP open

  • 9 marcan // Mar 25, 2009 at 3:13 pm

    The problem is we don’t know how to write to OTP, or how the write-addressing would work. It also seems to be addressed in 32-bit words so a problem could corrupt an entire word. We could try randomly poking registers, but we don’t know nearly enough to guarantee that we won’t overwrite the wrong part. And that would mean a brick.

    OTP is read by writing the address to one register OR 0x80000000 and reading another register which contains the read 32-bit word. The reading register seems to be read-only (not a holding register) so that’s probably not how you write to OTP.

  • 10 cloned // Mar 25, 2009 at 3:42 pm

    many thanks for the additional info ,

    I don’t have so much time to do it all by myself so , any help to find out if is there any real way to use the ZERO-hash back door will be apreciated very much

    as soon as I have time i’ll have a look to boot0 first then to boot1 , looking for some clue wasn’t noticed yet , then maybe i’ll try it by myself
    (or not
    ,if I finally feel it as too much risky as U say)

  • 11 PeterMacGonagan // Dec 9, 2009 at 3:59 pm

    “boot1 is the second stage of the Wii’s bootloader. It lives at the beginning of flash; it is encrypted by AES, using a fixed key. ”

    I suppose it’s that key: 9258a75264960d82676f904456882a73

    How did you find it?

  • 12 PeterMacGonagan // Dec 10, 2009 at 7:21 am

    Ok, I answer to myself. If you look at boot0 code your see the variable boot1_key:
    boot0:FFFF05FC boot1_key DCD 0x9258A752,0x64960D82,0x676F9044,0x56882A73

    Is it stored as it in NAND??? Why isn’t it stored in OTP of Hollywood chip?

  • 13 marcan // Dec 23, 2009 at 4:03 am

    The key is in boot0. Boot0 is in an internal Hollywood ROM that cannot be dumped externally, but you can dump it if you can run Starlet code. It was dumped using a replacement boot2 early on.

You must log in to post a comment.