Notes from inside your Wii

HackMii header image 2


May 31st, 2008 by bushing · 26 Comments

This post is part of a several-part series on fixing a “bricked” Wii:

  • UnBrickMii – Introduction, explanation of a 4-part plan to unbrick any Wii
  • amoxiflash – Part 1, a way to modify the NAND Flash of a bricked Wii
  • Mario-Kart Autopsy 1 and 2 – Part 2, a (partial) analysis of what happens to the filesystem of a Wii to make it “brick”
  • (tbd) – Part 3, a way to recover the necessary per-console unique keys (NAND AES, NAND HMAC) using a hacked boot2 on a bricked Wii
  • (tbd) – Part 4, software to modify the contents of the Wii’s filesystem on a host computer, making use of those two NAND keys.

I’ve focused my recent energy and time into Part 4.  It’s turned out to be more difficult than I’d feared.  In order to modify the filesystem to unbrick a Wii, we need to do the following things:

  • Isolate an existing file in the NAND dump (done)
  • Decrypt it using the proper AES key, modify it, and then encrypt it again using the same key (done, doable, and straightforward)
  • Sign each 0x4000-byte block using the correct HMAC key, so that the Wii will recognize it as valid.

The HMAC has proven to be the most difficult part.  HMAC is a standard algorithm, and I know the HMAC key for my Wii, but I can’t get my calculated HMAC to match the Wii’s stored HMAC.   This means I can’t modify the filesystem, which is a fairly serious obstacle.

I’ve spent weeks staring at the disassembly of boot2 — the first piece of code that performs the HMAC check — and I can’t figure out what it’s doing by pure static analysis.  Unfortunately, we don’t have any (useful) debug facilities.

It’s time to fall back to first principles.   Marcan and I have been working on modifying SkyEye to emulate the Starlet core.  It’s a very frustrating and tedious process, because we have no documentation for how most of this works, so we’re guessing and seeing how well code ends up running.  I don’t think it is something that will ever be useful for, say, a Wii emulator — there are far easier ways to emulate IOS — but I’m hoping I will be able to use it to debug the HMAC algorithm, and also perhaps firmware patches.

boot0 is the first part of the Starlet boot chain.  It is hardcoded in mask rom in every Hollywood chip; it will never change.   It is designed to be small and simple, because it’s impossible to fix any bugs that are found there.   I’ve chosen to start there in trying to emulate the chip — although it is only about 1300 bytes of code, it manages to talk to:

  • OTP storage area (to retrieve a hash to compare boot1 against
  • NAND Flash controller (to read the encrypted boot1)
  • SRAM (to store the decrypted boot1)
  • AES engine (to decrypt boot1)
  • SHA engine (to authenticate boot1)

I don’t expect this to be of much use to people, but if you’re curious, take a look at my analysis of boot0.   If you see anything i missed, please let me know!

Future articles will discuss boot1 and boot2.

Tags: Wii

26 responses so far ↓

  • 1 James B. // May 31, 2008 at 5:43 am

    OK – So is it likely that each Wii is going to have its own, different, set of keys?

    That would suck :\.

  • 2 marcan // May 31, 2008 at 6:55 am

    It’s not likely, it’s a known fact. Each Wii uses its own set of NAND key, HMAC key, and ECC signature keys, and possibly others. They’re all unique to each particular Wii.

  • 3 nIxx // May 31, 2008 at 6:57 am

    Nice Work.
    Hopefully you find a way to unbrick any wii

  • 4 Jayden // May 31, 2008 at 8:08 am

    It’s just amazing what you are doing. Please accept my sincere thanks.

  • 5 Christian Kurti // May 31, 2008 at 12:39 pm

    When he manages to modify the wii file system, the Wii will be pretty much unlocked at that point… almost anything the hardware can handle would be possible given the proper understanding of it…

    So this has many applications other than just unbricking! Like when several people found out how to obtain the Xbox 1 Hard drive lockout code.

  • 6 wowfunhappy // May 31, 2008 at 1:01 pm

    Now, I’m aware this is one of those questions which comes from an “annoying noob who has no idea what he’s talking about,” but if I may, I’ve been reading all your posts about unbricking wiis, and in this post, there’s only one thing I don’t understand:

    “I know the HMAC key for my Wii, but I can’t get my calculated HMAC to match the Wii’s stored HMAC.”

    That doesn’t make sense. If you know you’re Wii’s HMAC key, why wouldn’t it match you Wii’s stored HMAC key? Aren’t they one in the same?

    I’m aware that each Wii has a unique HMAC key, and that knowing your Wii’s HMAC key won’t help in the long run if you want to unbrick other people’s Wii’s, but since it’s YOUR Wii we’re talking about here…

  • 7 SquidMan // May 31, 2008 at 1:13 pm

    wowfunhappy: He means that when he generates his HMAC code, it doesn’t match the real one. And this actually would allow us to obtain ANYBODYs HMAC key, because he is generating the key.

    And MANY kudos to you guys! You guys work so hard, and everything 🙂 I especially thank you for the decompiled boot0, so now I can try and figure it out 😛
    Well, I guess what I’m trying to say is, you guys are awesome, and you do so much awesome stuff for so many people!

  • 8 TobiX // May 31, 2008 at 4:06 pm

    SquidMan: WRONG. Since the keys of each Wii are (for all we know) random, so is the HMAC key. Look at the pretty picture on the Wikipedia article. We know k, that is a key stored in each Wii. This is different for each Wii. The problem is that the Wii uses a HMAC to verify that each block on the NAND hasn’t been tampered with. Now when we try to calculate the HMAC for any block in the Wii NAND, the result is different from the one Nintendo calculated. This most likely means that Nintendo modified the HMAC algorithm to do some strange things which a “standard” HMAC does not do… Hope that made sense somehow…

  • 9 azeazezar // May 31, 2008 at 4:15 pm

    Correct me if I’m wrong, but wouldn’t it be more useful to look at code doing the hmac signing rather then the decrypting part?

  • 10 CaitSith2 // May 31, 2008 at 4:40 pm

    In order to look at the HMAC signing code, we first have to decrypt the contents of BOOT1, and analyze its contents. BOOT1 handles decryption, RSA signature verification, and running, of BOOT2. BOOT2, is what finally leads to executing of the system menu itself. It is true that there is a fake signing bug in BOOT1, which allows us to execute our own BOOT2. however, Nintendo is NOT able to fix that bug in BOOT1, at least not on Wii’s that are already out, because of a SHA1 hash of BOOT1 stored in OTP. (They could fix the fake-signing bug in future production runs though.)

  • 11 Enze // May 31, 2008 at 10:33 pm

    I enjoy reading these things. Thanks a lot, bushing. Keep up the good work.

  • 12 bushing // Jun 1, 2008 at 12:22 am

    TobiX is correct; we know (or can discover) ‘k’ for any Wii, but Nintendo’s calculations don’t match ours.

    @azeazear: I’ve spent weeks staring at the signing code, without much luck. So, I’m taking a different approach, and trying to run all of the code — including that signing code, eventually — inside an emulator. CaitSith2 is right in describing the roles of BOOT0/1/2 — I plan to write about boot1 next, and then finally boot2 (where the signing code is kept). We’re making “baby steps” here. 🙂

  • 13 Newbie // Jun 1, 2008 at 9:07 am

    Execution sequence is BOOT0/1/2
    B0 cannot call B1/2. It can jump to B1 once it’s verified
    B0 calculate ECC internally only. It calls some external engine(s) to calculate AES/SHA/HMAC
    All above means “B2 signing code” is another copy of the code.
    Where is the first one kept then? Could it be analyzed side by side with B2?

    I admit, I’m a complete noob and have no clue what I’m talking about… 🙁

  • 14 Newbie // Jun 1, 2008 at 10:55 am

    I was wondering if “IDA Pro Decompiler Plugin” supports ARM processors already?
    Is it any useful?

  • 15 Phredreeke // Jun 1, 2008 at 3:58 pm

    Interestind. I look forward to reading the next parts about boot1 and 2.

  • 16 Starlet // Jun 2, 2008 at 6:22 am

    Good job bushing and marcan! I will analyze this code snippet today and give in a few todays a comment to it. Only one question: How you get the boot code, and disassemble it? The NAND dump is crypted, but how can I encrypt it?

    The code was disassembled in ASM; i understand ASM good, but encryption…^^


  • 17 superdave // Jun 2, 2008 at 7:22 am

    So from this, it looks like the OTP (in the Starlet memory map, anyway) is at 0x80000000, but the boot1 key/IV is hardcoded in the mask ROM (0xFFFF05Fc)? That would imply to me that the boot1 key is console-invariant, unless I’m mistaken.

  • 18 boot0 / skyeye // Jun 12, 2008 at 5:26 am

    […] (This is a continuation of boot0) […]

  • 19 slang // Jan 5, 2010 at 10:00 am

    Maybe a stupid question, what security would fail if the ARM core was to be replaced? (Leaving the OTP with zeros..)

    As I’ve understood the consequence would be:

    Boot0 -> Boot1 hask check skipped

    Which could make way for unencrypted code to load:

    Boot1 -> modified or replaced with boot1b
    Boot2 -> modified or BootMii

    Has the Boot0 been updated?

  • 20 bushing // Jan 5, 2010 at 10:03 pm

    If you can make the OTP read as all zeroes, you win. I have not found a way to do that — I don’t really know what you mean by “replacing the ARM core”.

    boot0 has never, to my knowledge, been updated — but I haven’t really checked. there’s not much reason for them to ever do so.

  • 21 slang // Jan 6, 2010 at 5:22 am

    I see. To win you can a) zero out (or make OTP read as all zeroes) the OTP. Or b) modify / replace boot0, right?

    I don’t know what kind of memory the OTP is, but some memory is erasable by UV.

    I mean fysically removing the ARM core and put in a new one. I just imagined the core to be the bga type, but I don’t know this of course.

    Also where exactly is the boot0 located?
    Is it in the SEEPROM on the Hollywood?

  • 22 slang // Jan 6, 2010 at 6:30 am

    Now I see our misunderstanding, my bad. I don’t mean to replace the ‘core’, but the ARM926EJ-S itself on the Hollywood.
    In theory.

  • 23 twelvebaud // Jan 27, 2010 at 11:24 pm


    The ARM9 “Starlet” core is physically part of the Hollywood, and cannot be separated or removed in such a way that a replacement could be grafted on. That’d be like going “Gee, I don’t like one of the cores on my new AMD thingy, so I’m gonna rip one out and put a fresh one in its place.”

    It is possible to remove and replace the entire Hollywood from the console, but unless you have access to ATI’s factory and can nab one before they hit it with whatever they use to program the OTP, it’s not gonna do you much good; you’ll have a different, but still non-zero, key, and if you want to use your Wii normally after that… I heard a rumor about a program called “betwiin” that bushing did, but other than that, you’re not gonna have any luck.

    I haven’t seen anything specific, but I imagine the Wii uses eFuse technology like several other consoles, irrecoverably destroying transistors within the processor. Once it’s burned, it can’t be unburned, and if they’re smart it burns to FF rather than 00.

    boot0 is located on Hollywood, etched into a ROM area.

  • 24 jrod54 // Feb 13, 2010 at 11:58 am

    You got me to thinking-I wonder if the boot process makes a call to external storage during the authentication process? The reason I ask is that it makes sense to me that Nintendo would not worry about bricking if the boot routine included a search for a common fixed key burnt into the Starlet if the initial key failed, a “back door” to be used by the factory to recover a bricked motherboard for reuse.

  • 25 bushing // Feb 13, 2010 at 5:24 pm

    It’s a nice thought, but the whole point of this series of articles on the boot process of the Wii was to exhaustively search for such a call to external storage. It doesn’t exist.

  • 26 jrod54 // Feb 15, 2010 at 9:11 pm

    Did notice something, tho. I’m playing with a bsod wii m’board, and it queries a usb key I have plugged in port 2 every thirty seconds. Don’t know if that is of any importance.

You must log in to post a comment.