Wii system flaws
|Summary||Description||Successful exploitation result||Fixed in hardware revision||Discovered||Discovered by|
|HW_BOOT0 not clear-only||To prevent boot0 from being dumped, boot2 clears register HW_BOOT0 that allows the boot0 ROM to be read. However, Nintendo forgot to make this register clear-only, so simply re-enabling it allows boot0 to be dumped from 0xFFFE0000 or 0xFFFF0000 in memory.||boot0 can be obtained on consoles that do not support custom boot2 installations.||Unfixed||Unknown||fail0verflow|
|DVD-Video support is inadequately protected||While the Wii was initially meant to support DVD playback, it was scrapped to avoid needing to pay licensing fees. This support was removed in later revisions of the disc drive. However, when the Hollywood register ahbprot is disabled (e.g. by Homebrew Channel), homebrew can be used to read DVDs.||DVDs can be read on the Wii.||Unknown||December 2006||tmbinc|
|No mechanism to verify markings in disc BCA||GameCube discs are not signed; instead, they have 6 dents in the BCA region that are carefully checked by the GameCube IPL. This was done by checking for null bytes in that region, a result of the dents, and was easily bypassed by just overwriting those areas of the disc with null bytes. This was not fixed with the Wii for either GameCube or Wii discs; MIOS and the System Menu do the same null byte check, which makes it still accept unauthorized discs.||Loading homebrew discs on Wii without illegal equipment.||Unfixed||November 2006||Everyone|
|Disc drive UTS port was not completely blocked||The GameCube's disc drive had an unused port on the disc drive that allowed commands to be sent to the drive as if they were coming from the Gekko. Instead of removing it from the Wii, Nintendo simply used a different type of port, which means Broadway commands can still be sent from the outside.||GameCube drivechips can be slightly modified for the Wii.||Unknown||December 2006||tmbinc|
|Starlet is vulnerable to glitching attacks||A certain glitching pattern in boot0 allows any installed boot1 to load. An attack can be found here.||Arbitrary boot1 loading||Unfixed||November 2019||shinyquagsire23|
|Summary||Description||Successful exploitation result||Fixed in boot1 version||Discovered||Discovered by|
|strncmp used to compare hashes||boot1 verifies the signature of boot2 before booting it, however, the signing bug is present, allowing a fake boot2 to be loaded.||A custom bootloader can be installed, such as BootMii.||boot1c||January 2008||tmbinc|
|HW_BOOT0 is not cleared until boot2||When the Wii boots, boot2 clears HW_BOOT0 to unmap boot0 and prevent it from being dumped. However, when boot2 is replaced through the signing bug, HW_BOOT0 is not yet cleared.||Dumping of boot0||Unfixed||January 2008||tmbinc|
|Summary||Description||Successful exploitation result||Fixed in boot2 version||Discovered||Discovered by|
|No signature checks||Unlike boot1, boot2 does not check the signature of titles it launches, which means they can be freely modified.||Modifying the System Menu or System Menu IOS does not brick the system, and a custom MIOS can be loaded this way.||Unfixed||Unknown||fail0verflow|
|Module||Summary||Description||Successful exploitation result||Fixed in system update||Discovered||Discovered by|
|Kernel||No sanity checks on arguments passed to get_kernel_flavor and get_unk_flavor||System calls get_kernel_flavor and get_unk_flavor do not check to ensure that the pointers passed are appropriate to write to; they will write to any addresses.||If IOS code execution is gained, any address can be overwritten to some specific values by passing those addresses into get_kernel_flavor or get_unk_flavor.||Unknown||Unknown||fail0verflow|
|Kernel||Default keys exist in the kernel binary.||The Wii includes an OTP bank of memory, which contains securely stored keys. However, IOS includes a copy of these keys, which it falls back to if the OTP keys are missing. Because these keys are identical, the OTP keys can easily be extracted from the IOS kernel binary if it is dumped.||Most OTP keys can be obtained.||Unfixed[check]||December 2007||tmbinc|
|Kernel||IOS_CreateMessageQueue does not verify the address||The IOS_CreateMessageQueue syscall does not call the verifyRange function that many syscalls call, despite taking a pointer and causing data to be written to it. Because data can be written there with IOS_SendMessage, this allows for arbitrary writes.||Arbitrary writes to IOS memory (possibly used in HackMii Installer 0.5-0.6)||4.3||Unknown||Unknown|
|Kernel||/dev/sha does not correctly validate the destination vector||/dev/sha does not check the length of an output vector for ioctlv 0 (SHA_Init), allowing the IOS memory bounds check to be bypassed by setting the length to 0. SHA_Init will attempt to initialise a context into the destination address regardless, and in doing so sets a few values within to 0. By providing the thread context of the kernel idle thread as the destination vector, IOS's kernel will branch to memory address 0.||Running IOS kernel-mode code in memory controllable via the PowerPC.||Unfixed||May 2021||TheLordScruffy|
|ES||Trucha bug||The Wii used the strncmp function to check signatures, which always stopped at the first null byte, weakening the security. More information can be found at signing bug.||Custom titles can be installed, and fakesigned discs can be played.||3.3 (IOS30 only), October 23 Update (still exploitable by IOS16 pirates), 4.0||Unknown||segher and xt5 (independently)|
|ES||Title signatures are only checked at installation time.||NAND title signatures are checked on install, but never on launch. This means that if a title can be installed, it can be launched without further exploitation. This applies to both IOSes and Broadway apps, including the System Menu.
IOS4v3 does not seem to have this issue; when it loads the requested TMD on startup, it opens /sys/cert.sys. Because IOS4v3 likely predates all other IOSes, it is not known why other IOSes do not do this verification.
|One-time exploitation leads to trivial persistence.||Unfixed||June 2008||bushing|
|ES||No address check in ES_GetTitles||One of the parameters of ES_GetTitles is a buffer address for the titles to be written, however, this address is not checked to ensure that it is a Broadway-accessible address. By passing an address to overwrite, the titles fetched will be placed there.||Any address accessible from the ES module can be overwritten.||Unfixed||February 2020||metaconstruct|
|ES||ES_DiVerify does not check the calling module||ES contains no checks when ES_DiVerify is called, responding to any module that calls it. By sending this call from the Broadway over IPC, ES will receive this from the PPCBOOT process, and proceed normally.||Homebrew can identify as any title.||3.3rev03 (most IOSes), 3.4 (IOS30, IOS31, IOS37), 4.0 (IOS16, the last IOS)||March 2008||dhewg|
|ES||ES_AddTitleFinish does not check signatures||ES_AddTitleFinish does not check the signature of the title passed to ES_AddTitleStart, as it expects the signature to be valid by that point. By changing the contents of /import before calling ES_AddTitleFinish, any title can be installed.||Installation of any title||4.3||Unknown||WiiPower|
|ES||/tmp/title.tmd does not have protection flags set||When installing a title, ES writes most contents to /import, and moves them to the real directory when the ES_AddTitleFinish is called. However, it forgets to actually set permissions on this file, so it can easily be deleted and replaced. By changing the version when replacing this, titles can easily be downgraded.||Downgrading titles||Unknown||Unknown||WiiPower|
|ES||No out-of-bounds check when determining the common key from the ticket||Korean titles have a byte that is set to 0 to use the normal common key, and 1 to use the Korean key. This value is used as an index in an array containing the locations of both common keys. However, the value is never sanity checked, so any value can be inserted.||Arbitrary common key usage||Unknown||September 2008||bushing|
|ES||ES_GetTicketViews does not limit the ticket view count||Because a ticket view is 0xD8 bytes, ES_GetTicketViews verifies that every address between
||ES code execution (used by Riivolution and HackMii Installer)||Unfixed||March 2010||tueidj|
|FS||/dev/flash is unprotected||Permission checks in IOS exist for files, but the FS module does not check for permissions when reading the raw NAND contents. If the NAND key is obtained, the NAND can be freely modified.||Arbitrary NAND modification||3.3rev03 (most IOSes), 3.4 (IOS30, IOS31, IOS37), 4.0 (IOS16, the last IOS)||Unknown||Unknown|
|DI||DVD access can be trivially enabled||In a TMD's "access rights" field, there is a bit that controls DVD access, and code for handling DVDs. When it was decided that DVD support should not be present on the Wii, this code was not removed from IOS, and was in fact active code as well. (see hardware bug)||DVD access provided by IOS (used by DVDX)||Unfixed||July 2008||bushing|
|DI||Title ID in disc header is not checked against ID in TMD||On Wii discs, the title ID is present several times; once in the header, once in the TMD, and once in the ticket. While the latter two are coverer by a signature and therefore cannot be changed, the instance in the disc header is not, and is instead used by the System Menu to determine things such as refusing to boot the Wii Startup Disc. Although it does not make sense for this to be signed, it is nonetheless a flaw because it could have been compared to the value in the TMD.
This could be used to load the Wii Startup Disc a second time by changing the title ID (or load a different disc on the Startup Disc Menu, which is already possible with fakesigning), but the more practical use is to change a game's ID to start with a 0 or 1, and therefore boot with a SaveMii Dongle.
|Autobooting of any disc without fakesigning||Unfixed||July 2010||giantpune|
|SDI||Register access IOCTLs use ints for register IDs||IOCTLs 1 and 2 in /dev/sdio devices are used to write or read register values. When passing 4 at offset 0xC in the in buffer, this manipulation appears to happen in some cached register set linked to the file descriptor. If an index outside this pool is passed, it becomes possible to access arbitrary memory that SDI can access.
This was fixed by adding a cast to a short to to these IOCTLs, likely a result of the parameters themselves being changed to shorts.
|Leaking or rewriting memory as SDI. Possibly used by HackMii Installer 0.5 and 0.6.||4.2rev04||Unknown (documented in May 2022)||Unknown|
|ETH||Ethernet functionality was not removed from Wii Mini||While WiFi was removed from the Wii Mini, ethernet functionality is still present within the IOSes. By setting the appropriate internal setting, USB Ethernet can be used freely.||Ethernet use on Wii Mini||Unfixed||September 2019||Fullmetal5|
|STM||STM release bug||The state transition manager checks if a handle is invalid before releasing it, but forgets to actually refuse to release it if it is invalid. More information can be seen at STM Release Exploit||Control over IOS can be gained.||4.0||Unknown||fail0verflow, Anonymous person (from reverse engineering Homebrew Channel installer)|
|STM||STM_EventHook output size is not checked||When releasing an event hook through /dev/stm/immediate, STM writes a 0 word to the output buffer for the STM_EventHook request that was waiting. This code does not check whether the output buffer has the right amount of space, meaning if the size is set to 0, the kernel will not verify any addresses when passing an output address, and an arbitrary pointer accessible by STM can be zeroed by releasing the hook.||Zeroing any memory as STM. Possibly used in the pre-0.5 versions of the HackMii Installer.||4.2||Unknown (documented in May 2022)||Unknown|
|Summary||Description||Successful exploitation result||Fixed in system update||Discovered||Discovered by|
|Update downloader uses HTTP||The System Menu uses HTTP requests to download updates. By adding a MITM, it becomes possible to analyze and/or intercept the requests.||Tampering with update downloads||2.0||November 2006||roto|
|Buffer overflow in mail parser||When parsing a message saved to the SD Card, the Wii Message Board has a buffer overflow bug when copying the message body. By overwriting the memory allocation table this way, the next allocation address can be placed on the stack, allowing code to be returned to. LetterBomb and Wilbrand exploit this.||Code execution in the System Menu||vWii 1.0.0||August 2011||fail0verflow and giantpune (independently)|
|Twilight Hack check only checks one zeldaTp.dat||The savefile check to prevent Twilight Hack returns after checking one zeldaTp.dat. By placing a legitimate zeldaTp.dat somewhere else in the file, the real zeldaTp.dat can bypass the check.||A new version of the Twilight Hack works.||3.4||June 2008||tmbinc and tehpola|
|Twilight Hack check allows all unaligned zeldaTp.dat sizes||The savefile check that prevents Twilight Hack checks the number of bytes read against the file size, aligned to 32 bytes. By leaving the size misaligned, the checker will go past it without deleting it.||The new Twilight Hack survives Broadway resets.||3.4||June 2008||tmbinc and tehpola|
|Twilight Hack check only looks at the last file||When fixing the 3.3 bugs in the Twilight Hack checker, Nintendo started only checking the final file in the WAD. By placing a dummy file later in the WAD, the check can be bypassed.||Another Twilight Hack works on 3.4.||4.0||November 2008||marcan|
|Disc executable cache is not padded or truncated when writing a new executable over the old one||For speed, every time a disc is inserted, the System Menu writes the main executable to /title/00000001/00000002/data/cache.dat. However, overwriting the file may require relocation if the area allocated is too small, and there may be remnants of the old file if the allocated space is larger than what is needed. To prevent their repair discs (e.g. Check Disk for Pre-Repair Process) from being leaked, Nintendo inserts a normal game disc afterward, however, because this disc is almost guaranteed to not be the same size as the repair disc, remnants of the repair disc will remain on the NAND.||Partial dumping of repair disc executables after the console returns to the consumer||Unfixed[check]||April 2010||bushing|
|Icon.bin in content.bin is not verified||Channels stored on the SD card have their banner icon.bin stored outside of the main WAD for convenience. This section is not covered by any signature, which allows a hacked banner to be used without illegal keys.||Custom banners on SD channels||Unfixed||March 2009||comex|
|Summary||Description||Successful exploitation result||Fixed in BC version||Discovered||Discovered by|
|strncmp used to compare hashes||BC verifies the signature of boot2 before booting it, however, the signing bug is present, allowing a fake boot2 to be loaded.||If a fakesigned boot2 is installed, GameCube mode will launch it fine.||v4||January 2008||tmbinc|
|Summary||Description||Successful exploitation result||Fixed in MIOS version||Discovered||Discovered by|
|Memory not cleared before booting GC game||When MIOS loads a GameCube game, it never clears the 48MB of memory that the game should not have access to. By using a pair of tweezers to change the address lines, the entire memory can be dumped.||MIOS and the rest of memory can be dumped using GameCube homebrew.||v8||December 2007||tmbinc|
|Default keys are left in the binary||Like IOS, MIOS falls back on a certain set of keys if it cannot locate them in OTP. These keys are usually the same as the OTP ones, providing easy extraction when dumping MIOS through the Tweezer Attack.||Internal encryption keys can be dumped.||Unfixed||December 2007||tmbinc|
|No boot2 signature check||When the power button is pressed in GameCube mode, MIOS loads boot2 in a shutdown state. However, it has no signature verification, so it is easy to reboot into software such as BootMii this way.||The Wii will not hang on shutdown from MIOS if a custom boot2 is installed.||Unfixed||May 2009||Everyone|
|Homebrew disc blocker only checks title GNHE||To prevent Datel's discs from being played, 3.0 updates MIOS to ensure the apploader behavior of any disc with title ID GNHE is normal. Because this check only exists for title GNHE, although it could have applied for all discs, Datel could simply move their discs to another title ID.||Playing GameCube homebrew discs||Unfixed||December 2007||Datel|
|No check to prevent homebrew discs from being played by disc swap||While the 3.0 update changes the GameCube IPL to check for title GNHE, and ensure the apploader behaves as expected if so, it does not ensure other discs loaded by games (multi-disc games) follow these rules. By inserting the first disc of a multi-disc game, then inserting a homebrew disc instead of the second disc when prompted, the homebrew disc will boot.||Using GameCube homebrew discs||Unfixed||August 2007||knivez|
Because every game includes its own copy of the SDK, these flaws cannot be fixed globally.
|Summary||Description||Successful exploitation result||Discovered||Discovered by|
|No upper bound to CCB array||The Fluoride Bluetooth stack includes a function to get a CCB from an ID. This function checks whether the ID is below the lower bound, however, no upper bound is enforced.
By carefully crafting an ID, a fake CCB entry can be placed in the handles array. Sending a packet to free this struct causes it to "unlink" from its adjacent entries, which can be used to get an arbitrary write, and therefore code execution.
|PPC code execution (used in Bluebomb)||September 2019||Fullmetal5|
|No size limit to BigInts in Opera||In Opera, the dtoa module includes a number of functions operating on big integers with a maximum size, however, any sizes passed in are never checked. By passing in a value too large, the BigInt allocation table will return a smaller BigInt, which leads to a buffer overflow.||PPC code execution (used in str2hax)||December 2018||Fullmetal5|
|Use-after-free in Flash objects||Flash includes a feature to watch certain properties and get notified when they change, with the ability to easily change it again by returning a value from the event handler. If the event handler decides to delete the object holding that property, the caller still sets the value at that address.
With some manipulation of the garbage collector and thread-switching systems, the stack pointer can be changed, allowing ROP to begin.
|ROP in the PPC (used in FlashHax)||March 2018||Fullmetal5|