Friday, 7 March 2014

AES on the Wii U bootrom

[Update 2]

Ok, it's not an 'obfuscation' as i said. I'm an idiot! as a man, i am, i make mistakes. This post was about the problem i had on finding where the aes function was called, and i just wanted to share with the people!
Errors makes people happy! :D

So these are the correct things: They save some addresses into the memory somewhere after this offset 0xE0000000 then when they call a function to save the address of the AES implementation, then they call it via a function as a function pointer.



AES obfuscation on the Wii U bootrom

I've read the whole bootrom code and i have to admit, that big N has done a good job on hiding where and how it calls the AES code.
Finding the AES implementation is easy, it's just before the ancast header check function and after the most useless function.
Finding how the AES implementation is called, is a little bit hard, for two reasons:
  • there are no cross references in the text segment; This means you will not see something like:
    • bl AES_Decrypt
  • there are no addresses saved in the data segment:
    • AES_offset: .long AES_Decrypt
So how to find it? you have to read the code, because the value is hardcoded and saved into a memory on an unknown address (like 0xE0000000); then a function will load that addresses to the count (CTR) register and jumps there.
I'll make an example:


How normally should be:


#---------------------------------------------
AES_Decrypt: # (r3, r4, r5)
.set LR_old,  4
 mfspr     r0, LR            #  r0 = LR
 stwu      r1, -4(r1)        #  SP = SP-4
 stw       r0, 4+LR_old(r1)  # *SP = r0
 # AES code
 lwz       r0, 4+LR_old(r1)  # r0 = *SP
 addi      r1, r1, 4         # SP = SP+4
 mtspr     LR, r0            # LR = r0
 blr 
#---------------------------------------------
main: 
.set LR_old,  4
 mfspr     r0, LR            #  r0 = LR
 stwu      r1, -4(r1)        #  SP = SP-4
 stw       r0, 4+LR_old(r1)  # *SP = r0

 # Fill r3, r4, r5
 lis       r5, 0x20F0        # key
 lis       r3, 0x2100        # AES Context
 li        r4, 0x0080        # key size = 128
 bl        AES_Decrypt

 lwz       r0, 4+LR_old(r1)  # r0 = *SP
 addi      r1, r1, 4         # SP = SP+4
 mtspr     LR, r0            # LR = r0
 blr 

How is obfuscated on the Wii U:

#---------------------------------------------
set_AES_call:
 lis       r30, -0x2000       # 0xE0000000
 li        r31,  0x0010       # relative location
 stw       r31,  0x000A (r30) # 0xE000000A
 blr 
#---------------------------------------------
AES_Decrypt: # (r3, r4, r5)
.set LR_old,  4
 mfspr     r0, LR             #  r0 = LR
 stwu      r1, -4(r1)         #  SP = SP-4
 stw       r0, 4+LR_old(r1)   # *SP = r0
 # AES code
 lwz       r0, 4+LR_old(r1)   # r0 = *SP
 addi      r1, r1, 4          # SP = SP+4
 mtspr     LR, r0             # LR = r0
 blr 
#---------------------------------------------
call_AES: # (r3, r4, r5)
.set LR_old,  4
 mfspr     r0, LR             #  r0 = LR
 stwu      r1, -4(r1)         #  SP = SP-4
 stw       r0, 4+LR_old(r1)   # *SP = r0
 lis       r30, -0x2000       # 0xE0000000
 lwz       r0 ,  0x000A (r30) # 0xE000000A
 nop
 mtspr     CTR, r0            # CTR = r0
 nop 
 bctrl                        # jump to AES
 lwz       r0, 4+LR_old(r1)   # r0 = *SP
 addi      r1, r1, 4          # SP = SP+4
 mtspr     LR, r0             # LR = r0
 blr  
#---------------------------------------------
main: 
.set LR_old,  4
 mfspr     r0, LR             #  r0 = LR
 stwu      r1, -4(r1)         #  SP = SP-4
 stw       r0, 4+LR_old(r1)   # *SP = r0
 # Obfuscate AES
 bl        set_AES_call
 
 # Fill r3, r4, r5
 lis       r5, 0x20F0        # key
 lis       r3, 0x2100        # AES Context
 li        r4, 0x0080        # key size = 128
 bl        call_AES
 
 lwz       r0, 4+LR_old(r1)  # r0 = *SP
 addi      r1, r1, 4         # SP = SP+4
 mtspr     LR, r0            # LR = r0
 blr 

The last thing:

I had a lot of fun on reverse the whole bootrom. You'll find interesting stuff, there (but not keys :P).

[Update 1]

Some said that it's a function pointer. Yes, it's true, but the 'obfuscation' that i'm talking about is quite different.
When you create a function pointer, you can have the following things:
#---------------------------------------------
AES_Decrypt: # (r3, r4, r5)
.set LR_old,  4
 mfspr     r0, LR             #  r0 = LR
 stwu      r1, -4(r1)         #  SP = SP-4
 stw       r0, 4+LR_old(r1)   # *SP = r0
 # AES code
 lwz       r0, 4+LR_old(r1)   # r0 = *SP
 addi      r1, r1, 4          # SP = SP+4
 mtspr     LR, r0             # LR = r0
 blr 
#---------------------------------------------
#stored in the data segment
.long AES_Decrypt

#stored in register
lis       r0,     AES_Decrypt@h
addi      r0, r0, AES_Decrypt@l

On the Wii U ths is a little bit different. The address is stored in the register, but it's relatively static to the copy of the bootrom, not to the bootrom itself. this means, the addresses was coded by thinking that the rom was going to be loaded at another offset. In this simple way you obscurate partially of the code. There is no reason to make a function pointer that you are going to use just once. Function pointers are useful, if you are going to use callbacks, arrays, etc., but not in this case. In fact if you change the loading offset to the 'suitably one' of the bootrom you will get the cross references..

By the idiot who has wrote a stupid thing :P

4 comments:

  1. I'm a big noob when it comes to this stuff but what does this actually meant to the oblivious idiots such as myself and the rest of the people anticipating a hack at some point? Have you hit a wall? I'm confused by what you posted. :)

    ReplyDelete
    Replies
    1. this was for those who wants to give a look to the wii u bootrom. nothing interesting for normal users

      Delete
  2. ok yeah that's what I thought. Thanks for looking into this regardless. :)

    ReplyDelete