========================
The WODE just got HACKED
========================
Ever wondered what the WODE for the Wii was all about?
I'll give you a rather "short" journey that I had about ~1 year of investigation of what's "hidden" or even running inside.
Due to my experience with embedded devices in the past and after dumping the firmware off a WDTVLiveHub, while porting the Linux Kernel and therefore the DVD drive's driver as of v5.1 to the Wii, by mid of 2021, I decided to go for another project: the WODE. I absolutely had no idea what it contained at all or what I even would have to face with. A search at Google gave enough information about it running a Linux Kernel and coming across a site labeled as "YouAreRoot" by "WODE.ObeyGravity.de" gave enough information on how to access the internal terminal.
But..., how do you start with hacking an embedded device...?
=====================================================
At first, I had to get familiar with the hardware like the MCU which is a LPC3143 by NXP and therefore, read it's manual (which btw. is about 600 pages). According to it's information, it supported multiple boot options like from NAND, SPI, UART, DFU etc. and I had several memory regions available which were of interest for dumping but that's not what you would go for at first. Instead, I had to find out what actual firmware was running on it so I copied the so called "ROOTFS" (root filesystem) to a USB-thumbstick attached to the LCD-PCB of the WODE and then investigated all the files which turned out, it being some OpenWRT firmware derivative. More on that Google search also turned out it actually was some random KAMIKAZE release, ported to the LPC3143 MCU. I had to find out the actual timespan when the WODE was in development so it would fit the code and libraries (as of their respective versions) containing the actual firmware running on this thing with the purpose of writing a memory dumper in C-language using libraries which are almost available within the root filesystem. And I had success with that but before anything else, I dumped the whole SPI-NOR flash memory which actually contained the encrypted bootloader and encrypted Kernel as well.
Security flaws
============
The WODE, starting by firmware v1.21, supports UART terminal access to the Kernel. After I had accomplished writing and compiling a memory dumper using the almost existing libraries within the ROOTFS, I went for dumping the internal RAM area (ISRAM) of the MCU where the bootloader resides after decryption and image verification of the MCU's BOOTROM and got a nice decrypted image dump available for further investigation. Using IDA it turned out that the bootloader sets security (read-protection) BITS on some memory area which turned out to be OTP of the MCU and that's where the bootloader AES key is stored. I wanted to have that AES key soooo much... (as it would allow much more ROOT access than I already had back at the time). There also were some suspicious byte ranges in some function of the dumped bootloader binary which I couldn't explain to myself but after reading the MCU's manual again and compairing where these bytes get written into, it turned out to be the Linux Kernel AES key (YES! you're definitely reading correctly - the Linux Kernel AES key is stored within the WODE bootloader binary). But this key and the Kernel crypto was almost completely useless and I'll tell you why if you read on. Anyway, I then went for dumping the DRAM area instead. DRAM is where the bootloader (once running) decrypts the Kernel into and after verification, jumps to. Holding the Kernel in my hands (without the actual Kernel header) was depressing but I found out that parts of the bootloader area read the Kernel header into the bootloader BSS area of ISRAM, so it was just a matter of time to fix that and after hex-editing very, very less bytes of the actual Kernel image, the header CRC and data CRC of the Kernel would just match the original CRC's within the Kernel header data. This was a whole success for further hacking.
This also lead to dumping the BOOTROM of the MCU which is located, starting at offset 0x12000000. For some unknown reason, this area is completely unprotected from reading it's data out. Without it, there wouldn't have been a chance to hack the WODE as the BOOTROM told me where to insert the glitch attack at and it also contains the AES initialization vector required for decrypting boot images like the actual bootloader running on it.
For the fun fact, I also desoldered the SPI-NOR flash memory from the main PCB of the WODE and dumped it's contents. But once connected back to the WODE, I investigated the data transfers on the MOSI and MISO lines using a logic analyzer:
THERE'S A HOLE!
For transferring the decrypted Kernel to the DRAM area, as of it's size, the developers of the WODE are using DMA mode on the MCU as it speeds up things pretty fast. Once decryption is started, this almost exposes a decrypted data block to the MOSI line at the same time an encrypted data block is going in on the MISO line. This security flaw is not just present on the WODE but also on other ODE's with this very same boot mode and data transfer mode used.
PROFIT: Decrypted Kernel just dumped!
For that security flaw, it would have been better the developers had used MEMCPY instead of SPI-DMA data transfer when doing crypto stuff as that's what I'm doing on my own:
First, read the whole image from the SPI-NOR flash into DRAM.
Then MEMCPY an AES block of encrypted data from DRAM into the NAND controller RAM0 buffer.
Enable interrupts, decrypt the data and wait for the interrupt to disable.
Then MEMCPY the decrypted data from the NAND controller RAM0 buffer to it's destination.
Repeat the whole process until the whole image has been decrypted.
This wouldn't have exposed anything like what I figured out on the MOSI line by the way they implemented it.
There was absolutely no reason for the use of SPI-DMA data transfers. It's just a security risk. My own solution to this doesn't effect the use of DMA at all. The speed upon this is still acceptable.
Anyway, after that I then tried to find the OPENWODE archive which was supposed to be a repository for developing your own WODE apps which btw. was a total FAIL as the Wayback-Machine didn't cover this archive (which btw. was released on Jan, 23rd 2012). I had to stop there until (after months) a user by the name of "wildbomb" uploaded it to a random filehoster and shared the link over at GBATemp. After downloading, extracting and inspecting this particular archive, I came to the conclusion that it was NOT the full source code as it was missing the bootloader source code as well as the main binary source code which runs within the Kernel and does all the interaction like mounting ISO files or using the joystick for navigation through the WODE's menu. This gave even more motivation to me to actually hack it.
Even more and more weeks passed. Installing the existing OPENWODE update image to a WODE didn't turn out to my primary goal: gaining access to the bootloader AES key. I had to find another way around. Reading more and more into Google's search results gave me an inside view on how to hack an AES-128-CBC crypto implementation. This actually turned out to be an untold mystery as it took a really long excercise which depended on how this implementation was done: from either software or hardware side. For the WODE and it's MCU, to my surprise, it was done from the hardware side - meaning, the LPC3143 MCU contains an AES hardware crypto module for decryption of binaries. A so-called "differential-power-analysis" (DPA-attack) to gain the AES key using a ChipWhisperer, once decryption is started, turned out to be a FAIL at all levels. Anyway, to find out more, I had to buy a ChipWhisperer for that. Alongside with it, I also had to go for an oscilloscope to see what was going on at the power rail once the WODE is started and running.
Reading the MCU's manual over and over again, I had no choice but to find out how to trigger the UART boot mode (as the WODE on it's setup from factory uses "boot from SPI-NOR flash memory" instead). This wasn't that hard due to inspecting the J6 port and re-routing the boot mode pins (GPIO0, GPIO1 and GPIO2) to their respective state.
Still, weeks passed... hooking up the ChipWhisperer wasn't what I expected it to be like as there exist absolutely no tutorials for your target hardware. I tried as hard as I could and it was a fail after fail after fail journey. So I finally gave up and did absolutely nothing anymore about the WODE after all - until one day...
LPC3143 SkyEYE emulation
=======================
During the time of my rest and due to pure frustration I also used to try something different: port the very basics of the LPC3143 MCU into the SkyEYE source code, which is an ARM emulator. As a very basic setup, I've used some of the patches within the port of SkyEYE for Starlet (Wii). With this finally running, it was possible to actually emulate a running WODE firmware, though - I patched around the internal AES crypto code of the bootloader and BOOTROM running within and used the binaries I just dumped before which actually worked out quite good. This was right before the unexpected thing happened out of a sudden:
Some day I gave it another shot and tried hooking up different pins of the ChipWhisperer to even different solder points on the WODE's main PCB. Even that didn't give the expected results at first as upon injecting voltage glitches, the MCU would STILL execute the way it just should. So I decided to do what would mean the "death at the end" for the WODE: desolder all the capacitors which may filter out the glitching attack. This finally would have an effect on the output of the oscilloscope as the gaps between code execution and glitch insertion would be way wider.
Finding the right settings for the offset, width and repeats of the glitch insertion required writing my own Python script using the ChipWhisperer API without even using the actual GUI (graphical user interface). This would work out as a success within a few hours, though - the ChipWhisperer API still was not fast enough to gain the expected results, so I had to change timings within the API's Python scripts as well. After that it would just be a pleasure.
So, with the UART boot mode running and the MCU (once reset) requesting a protected (AES) boot image (because of the security running on the WODE's MCU) I got my Python script running, doing this:
- RESET the MCU
- Inject the glitch to the MCU for a request of UNPROTECTED (PLAINTEXT) binaries
- READ the request
- IF we have a SUCCESSFUL request, "download" an unprotected binary into the MCU. If it fails, restart the whole process
- FINGERS CROSSED: hope for anything good...
With all the capacitors on the WODE's main PCB desoldered, It wasn't just booting my "downloaded" code. I (per accident) happened to connect a capacitor once my (unprotected) boot image was just fully downloaded and compared right before execution. I wrote "per accident" here as I (at one point) totally forgot to remove this 1 capacitor for getting the glitch attack to work but for code execution, that 1 capacitor is definitely required which just has to be connected to the circuit at the right time after downloading the binary over UART has finished.
You know what: Even after finding the correct glitch settings using a second Python script which would just change all the stuff like repeats, offset, width etc. at runtime of the glitch-insertion script, it would turn out not to be just the bootloader AES key that I just dumped using my binary printing out stuff using UART. Instead, I was able to gain the whole (usually protected) OTP area of a WODE.
And this is what happens if you f*ck around with developers:
=====================================================
People like "TheArtificer" (in the past) pretended to say like "here's the source code for our ODE" whereby he / they never released the actual FULL code to all the development timeline. This is what made me more addicted and what turned into actually hacking the WODE.
"TheArtificer" - one of the developers behind the WODE once also stated this line:
"I wont be making the bootloader keys or the Wode App source code available, these aren't covered by the GPL. I may make some very basic example apps available though (rip, play, serve etc)."
...and even that failed at all. The OPENWODE archive contained nothing more than just the Kernel source code and a simple app on how to use the joystick including a simple framebuffer driver for the LCD screen.
So what's missing???
==================
For the current state, basically the WODE's firmware as of the bootloader and Kernel can be completely rewritten. On the other hand, there's absolutely no chance about the Actel ProASIC3 FPGA which holds the bitstream required for interfacing the internal drive of a Wii. Some investigation on what was done upon that resolved that the contents on the FPGA are AES-encrypted as well and even accessing it is not possible due to the fact that it is also password-protected. Hacking a FPGA like this is up to impossible to achieve. According to it's manual, the AES key for the FPGA data is stored within the FPGA itself. There were no references found within the bootloader / not even the Kernel. Aside from that situation, the FPGA bitstream (VHDL source code) was never released to the public like the previous missing stuff after the "END-OF-LIFE" of the WODE.
SHAME ON YOU, "TheArtificer"!!!
This is not the way you care about customers or even developers. You are restricting access to fully owned hardware customers paid for - for what manner...?
I finally decided to go for the hard way and reverse the WODE binary source code as of firmware v1.00 of the running Kernel, which (as of today) is a 100% reverse C code of about 87% of the whole image.
If you (the current reader of this topic) are interested in joining reversing the WODE binary source code of the Kernel: feel free to leave a mark.
Current state
============
Aside from reversing the code of the binary running within the Kernel, I'm currently into testing some things regarding the LCD screen on the WODE. If things work out as expected, there might be some more fun stuff but until that I rather not give too much info on it. It just might be worth a shot to look out for within the future.
Thank you and... this is NOT the end. There is still more to expect... Stay tuned!
Want to find out more about the WODE's internals and how stuff actually works?: make sure to visit WODE-RE
nitr8, >>Signing out<<
The WODE just got HACKED
========================
Ever wondered what the WODE for the Wii was all about?
I'll give you a rather "short" journey that I had about ~1 year of investigation of what's "hidden" or even running inside.
Due to my experience with embedded devices in the past and after dumping the firmware off a WDTVLiveHub, while porting the Linux Kernel and therefore the DVD drive's driver as of v5.1 to the Wii, by mid of 2021, I decided to go for another project: the WODE. I absolutely had no idea what it contained at all or what I even would have to face with. A search at Google gave enough information about it running a Linux Kernel and coming across a site labeled as "YouAreRoot" by "WODE.ObeyGravity.de" gave enough information on how to access the internal terminal.
But..., how do you start with hacking an embedded device...?
=====================================================
At first, I had to get familiar with the hardware like the MCU which is a LPC3143 by NXP and therefore, read it's manual (which btw. is about 600 pages). According to it's information, it supported multiple boot options like from NAND, SPI, UART, DFU etc. and I had several memory regions available which were of interest for dumping but that's not what you would go for at first. Instead, I had to find out what actual firmware was running on it so I copied the so called "ROOTFS" (root filesystem) to a USB-thumbstick attached to the LCD-PCB of the WODE and then investigated all the files which turned out, it being some OpenWRT firmware derivative. More on that Google search also turned out it actually was some random KAMIKAZE release, ported to the LPC3143 MCU. I had to find out the actual timespan when the WODE was in development so it would fit the code and libraries (as of their respective versions) containing the actual firmware running on this thing with the purpose of writing a memory dumper in C-language using libraries which are almost available within the root filesystem. And I had success with that but before anything else, I dumped the whole SPI-NOR flash memory which actually contained the encrypted bootloader and encrypted Kernel as well.
Security flaws
============
The WODE, starting by firmware v1.21, supports UART terminal access to the Kernel. After I had accomplished writing and compiling a memory dumper using the almost existing libraries within the ROOTFS, I went for dumping the internal RAM area (ISRAM) of the MCU where the bootloader resides after decryption and image verification of the MCU's BOOTROM and got a nice decrypted image dump available for further investigation. Using IDA it turned out that the bootloader sets security (read-protection) BITS on some memory area which turned out to be OTP of the MCU and that's where the bootloader AES key is stored. I wanted to have that AES key soooo much... (as it would allow much more ROOT access than I already had back at the time). There also were some suspicious byte ranges in some function of the dumped bootloader binary which I couldn't explain to myself but after reading the MCU's manual again and compairing where these bytes get written into, it turned out to be the Linux Kernel AES key (YES! you're definitely reading correctly - the Linux Kernel AES key is stored within the WODE bootloader binary). But this key and the Kernel crypto was almost completely useless and I'll tell you why if you read on. Anyway, I then went for dumping the DRAM area instead. DRAM is where the bootloader (once running) decrypts the Kernel into and after verification, jumps to. Holding the Kernel in my hands (without the actual Kernel header) was depressing but I found out that parts of the bootloader area read the Kernel header into the bootloader BSS area of ISRAM, so it was just a matter of time to fix that and after hex-editing very, very less bytes of the actual Kernel image, the header CRC and data CRC of the Kernel would just match the original CRC's within the Kernel header data. This was a whole success for further hacking.
This also lead to dumping the BOOTROM of the MCU which is located, starting at offset 0x12000000. For some unknown reason, this area is completely unprotected from reading it's data out. Without it, there wouldn't have been a chance to hack the WODE as the BOOTROM told me where to insert the glitch attack at and it also contains the AES initialization vector required for decrypting boot images like the actual bootloader running on it.
For the fun fact, I also desoldered the SPI-NOR flash memory from the main PCB of the WODE and dumped it's contents. But once connected back to the WODE, I investigated the data transfers on the MOSI and MISO lines using a logic analyzer:
THERE'S A HOLE!
For transferring the decrypted Kernel to the DRAM area, as of it's size, the developers of the WODE are using DMA mode on the MCU as it speeds up things pretty fast. Once decryption is started, this almost exposes a decrypted data block to the MOSI line at the same time an encrypted data block is going in on the MISO line. This security flaw is not just present on the WODE but also on other ODE's with this very same boot mode and data transfer mode used.
PROFIT: Decrypted Kernel just dumped!
For that security flaw, it would have been better the developers had used MEMCPY instead of SPI-DMA data transfer when doing crypto stuff as that's what I'm doing on my own:
First, read the whole image from the SPI-NOR flash into DRAM.
Then MEMCPY an AES block of encrypted data from DRAM into the NAND controller RAM0 buffer.
Enable interrupts, decrypt the data and wait for the interrupt to disable.
Then MEMCPY the decrypted data from the NAND controller RAM0 buffer to it's destination.
Repeat the whole process until the whole image has been decrypted.
This wouldn't have exposed anything like what I figured out on the MOSI line by the way they implemented it.
There was absolutely no reason for the use of SPI-DMA data transfers. It's just a security risk. My own solution to this doesn't effect the use of DMA at all. The speed upon this is still acceptable.
Anyway, after that I then tried to find the OPENWODE archive which was supposed to be a repository for developing your own WODE apps which btw. was a total FAIL as the Wayback-Machine didn't cover this archive (which btw. was released on Jan, 23rd 2012). I had to stop there until (after months) a user by the name of "wildbomb" uploaded it to a random filehoster and shared the link over at GBATemp. After downloading, extracting and inspecting this particular archive, I came to the conclusion that it was NOT the full source code as it was missing the bootloader source code as well as the main binary source code which runs within the Kernel and does all the interaction like mounting ISO files or using the joystick for navigation through the WODE's menu. This gave even more motivation to me to actually hack it.
Even more and more weeks passed. Installing the existing OPENWODE update image to a WODE didn't turn out to my primary goal: gaining access to the bootloader AES key. I had to find another way around. Reading more and more into Google's search results gave me an inside view on how to hack an AES-128-CBC crypto implementation. This actually turned out to be an untold mystery as it took a really long excercise which depended on how this implementation was done: from either software or hardware side. For the WODE and it's MCU, to my surprise, it was done from the hardware side - meaning, the LPC3143 MCU contains an AES hardware crypto module for decryption of binaries. A so-called "differential-power-analysis" (DPA-attack) to gain the AES key using a ChipWhisperer, once decryption is started, turned out to be a FAIL at all levels. Anyway, to find out more, I had to buy a ChipWhisperer for that. Alongside with it, I also had to go for an oscilloscope to see what was going on at the power rail once the WODE is started and running.
Reading the MCU's manual over and over again, I had no choice but to find out how to trigger the UART boot mode (as the WODE on it's setup from factory uses "boot from SPI-NOR flash memory" instead). This wasn't that hard due to inspecting the J6 port and re-routing the boot mode pins (GPIO0, GPIO1 and GPIO2) to their respective state.
Still, weeks passed... hooking up the ChipWhisperer wasn't what I expected it to be like as there exist absolutely no tutorials for your target hardware. I tried as hard as I could and it was a fail after fail after fail journey. So I finally gave up and did absolutely nothing anymore about the WODE after all - until one day...
LPC3143 SkyEYE emulation
=======================
During the time of my rest and due to pure frustration I also used to try something different: port the very basics of the LPC3143 MCU into the SkyEYE source code, which is an ARM emulator. As a very basic setup, I've used some of the patches within the port of SkyEYE for Starlet (Wii). With this finally running, it was possible to actually emulate a running WODE firmware, though - I patched around the internal AES crypto code of the bootloader and BOOTROM running within and used the binaries I just dumped before which actually worked out quite good. This was right before the unexpected thing happened out of a sudden:
Some day I gave it another shot and tried hooking up different pins of the ChipWhisperer to even different solder points on the WODE's main PCB. Even that didn't give the expected results at first as upon injecting voltage glitches, the MCU would STILL execute the way it just should. So I decided to do what would mean the "death at the end" for the WODE: desolder all the capacitors which may filter out the glitching attack. This finally would have an effect on the output of the oscilloscope as the gaps between code execution and glitch insertion would be way wider.
Finding the right settings for the offset, width and repeats of the glitch insertion required writing my own Python script using the ChipWhisperer API without even using the actual GUI (graphical user interface). This would work out as a success within a few hours, though - the ChipWhisperer API still was not fast enough to gain the expected results, so I had to change timings within the API's Python scripts as well. After that it would just be a pleasure.
So, with the UART boot mode running and the MCU (once reset) requesting a protected (AES) boot image (because of the security running on the WODE's MCU) I got my Python script running, doing this:
- RESET the MCU
- Inject the glitch to the MCU for a request of UNPROTECTED (PLAINTEXT) binaries
- READ the request
- IF we have a SUCCESSFUL request, "download" an unprotected binary into the MCU. If it fails, restart the whole process
- FINGERS CROSSED: hope for anything good...
With all the capacitors on the WODE's main PCB desoldered, It wasn't just booting my "downloaded" code. I (per accident) happened to connect a capacitor once my (unprotected) boot image was just fully downloaded and compared right before execution. I wrote "per accident" here as I (at one point) totally forgot to remove this 1 capacitor for getting the glitch attack to work but for code execution, that 1 capacitor is definitely required which just has to be connected to the circuit at the right time after downloading the binary over UART has finished.
You know what: Even after finding the correct glitch settings using a second Python script which would just change all the stuff like repeats, offset, width etc. at runtime of the glitch-insertion script, it would turn out not to be just the bootloader AES key that I just dumped using my binary printing out stuff using UART. Instead, I was able to gain the whole (usually protected) OTP area of a WODE.
And this is what happens if you f*ck around with developers:
=====================================================
People like "TheArtificer" (in the past) pretended to say like "here's the source code for our ODE" whereby he / they never released the actual FULL code to all the development timeline. This is what made me more addicted and what turned into actually hacking the WODE.
"TheArtificer" - one of the developers behind the WODE once also stated this line:
"I wont be making the bootloader keys or the Wode App source code available, these aren't covered by the GPL. I may make some very basic example apps available though (rip, play, serve etc)."
...and even that failed at all. The OPENWODE archive contained nothing more than just the Kernel source code and a simple app on how to use the joystick including a simple framebuffer driver for the LCD screen.
So what's missing???
==================
For the current state, basically the WODE's firmware as of the bootloader and Kernel can be completely rewritten. On the other hand, there's absolutely no chance about the Actel ProASIC3 FPGA which holds the bitstream required for interfacing the internal drive of a Wii. Some investigation on what was done upon that resolved that the contents on the FPGA are AES-encrypted as well and even accessing it is not possible due to the fact that it is also password-protected. Hacking a FPGA like this is up to impossible to achieve. According to it's manual, the AES key for the FPGA data is stored within the FPGA itself. There were no references found within the bootloader / not even the Kernel. Aside from that situation, the FPGA bitstream (VHDL source code) was never released to the public like the previous missing stuff after the "END-OF-LIFE" of the WODE.
SHAME ON YOU, "TheArtificer"!!!
This is not the way you care about customers or even developers. You are restricting access to fully owned hardware customers paid for - for what manner...?
I finally decided to go for the hard way and reverse the WODE binary source code as of firmware v1.00 of the running Kernel, which (as of today) is a 100% reverse C code of about 87% of the whole image.
If you (the current reader of this topic) are interested in joining reversing the WODE binary source code of the Kernel: feel free to leave a mark.
Current state
============
Aside from reversing the code of the binary running within the Kernel, I'm currently into testing some things regarding the LCD screen on the WODE. If things work out as expected, there might be some more fun stuff but until that I rather not give too much info on it. It just might be worth a shot to look out for within the future.
Thank you and... this is NOT the end. There is still more to expect... Stay tuned!
Want to find out more about the WODE's internals and how stuff actually works?: make sure to visit WODE-RE
nitr8, >>Signing out<<
Last edited by nitr8,