Changes

391 bytes added ,  00:24, 18 January 2022
→‎How it works: seems to be controlling OSThread actually
Line 2: Line 2:  
| title      = FlashHax
 
| title      = FlashHax
 
| image      = [[File:Flashhax.png|200px]]
 
| image      = [[File:Flashhax.png|200px]]
| type        = Exploit
+
| type        = exploit
| author      = [[User:Fullmetal5]]
+
| author      = [[User:Fullmetal5 | Fullmetal5]]
 
| download    =  
 
| download    =  
| website    = [http://www.flashhax.com/ Link]
+
| website    = http://www.flashhax.com/
| peripherals = {{Wiimote}} {{Internet}}
+
| source      = https://github.com/Fullmetal5/FlashHax
 +
| peripherals = {{Wiimote}} {{Internet}}  
 
}}
 
}}
   Line 43: Line 44:  
Unfortunately, because of how the garbage collector works, it will also attempt to follow a "pointer" at the value previously there, which means it is important to make sure the chain does not go past there. It turns out that the chain handles 6 objects at a time, which means the 6th object needs to be at the place to overwrite. Because the beginning of the object is overwritten with a zero, while the second integer is overwritten with a previous pointer, the location of this "object" must be placed 4 bytes before the address to be overwritten. The 5th object must then have the address to be overwritten, followed directly by the data that should be present when the overwritten pointer is dereferenced. With this, there are still 4 more iterations that must be done. The first iteration is when the garbage collector handles the trashed text field and moves toward the custom chain, leaving 3 more that require attention. For these three, a simple chain of pointers pointing to the next object are put to use up the remaining parts of the loop. A buffer of junk bytes is placed in between to prevent the garbage collector from overwriting the pointer after it, providing a method to overwrite a single address.
 
Unfortunately, because of how the garbage collector works, it will also attempt to follow a "pointer" at the value previously there, which means it is important to make sure the chain does not go past there. It turns out that the chain handles 6 objects at a time, which means the 6th object needs to be at the place to overwrite. Because the beginning of the object is overwritten with a zero, while the second integer is overwritten with a previous pointer, the location of this "object" must be placed 4 bytes before the address to be overwritten. The 5th object must then have the address to be overwritten, followed directly by the data that should be present when the overwritten pointer is dereferenced. With this, there are still 4 more iterations that must be done. The first iteration is when the garbage collector handles the trashed text field and moves toward the custom chain, leaving 3 more that require attention. For these three, a simple chain of pointers pointing to the next object are put to use up the remaining parts of the loop. A buffer of junk bytes is placed in between to prevent the garbage collector from overwriting the pointer after it, providing a method to overwrite a single address.
   −
Now, an address to overwrite must be chosen. It makes sense to overwrite a pointer, since a pointer will be put in place of it. At first, it seems like a function pointer or return address should be overwritten to pass code execution to FlashHax, however, Opera does enforce DEP, so a code buffer cannot simply be added. A more useful place to overwrite is a thread context pointer. The thread context holds all register states of a thread, and is updated every time the thread switches. If this is overwritten, almost all registers can be controlled.
+
Now, an address to overwrite must be chosen. It makes sense to overwrite a pointer, since a pointer will be put in place of it. At first, it seems like a function pointer or return address should be overwritten to pass code execution to FlashHax, however, Opera does enforce DEP, so a code buffer cannot simply be added. A more useful place to overwrite is a pointer to an [[Revolution OS#Threads|OSThread]].
   −
With the thread context in control, one might think to set up a ROP chain by overwriting the stack pointer. However, this is not possible, because the stack pointer is stored in register r1, which is overwritten by the trash bytes that come after the previous pointer on the garbage collector chain. In fact, r6 is the first register that can be controlled. Luckily, the other special-purpose registers such as the program counter and the link register are higher up in the context, so they can be controlled. The program counter holds the address of the instruction currently being executed, so it can be placed at the start of a ROP gadget, allowing for a single ROP gadget to be executed. A second one can be executed by placing it in the link register, as that holds the return address that will be jumped to after the current ROP gadget is finished. However, no more ROP gadgets can be run this way, so a way to load a longer ROP chain is needed.
+
With OSThread (and therefore [[Revolution OS#Context saving|OSContext]]) in control, one might think to set up a ROP chain by overwriting the stack pointer. However, this is not possible, because the stack pointer is stored in register r1, which is overwritten by the trash bytes that come after the previous pointer on the garbage collector chain. In fact, r6 is the first register that can be controlled. Luckily, the other special-purpose registers such as the program counter and the link register are higher up in the context, so they can be controlled. The program counter can be used to load one gadget, and the link register can hold a second gadget assuming the first gadget is not from a function that saves and loads the link register (i.e. a function that calls another function). However, no more ROP gadgets can be run this way, so a way to load a longer ROP chain is needed.
   −
The problem is now reduced to placing the stack pointer at a controlled location, using up to two ROP gadgets. The stack pointer is currently set at a low value due to the garbage collector setting r1 to that, so it may appear that starting a ROP gadget in the middle of a function is not useful, since it will attempt to free the stack into negative memory. This is actually not the case, because on PowerPC, the stack grows downward, meaning there is actually plenty of space for the stack to be freed, but not much to grow. Because of this, the first ROP gadget can be at the part of a function that is freeing however much of the stack it previously allocated, which is stored in the r28 register, one that FlashHax has control over. Once this is done, the stack pointer is in control. Before a stack ROP chain can be used, the link register must be returned to. Here, a single return instruction can be used to reach the ROP chain.
+
The problem is now reduced to placing the stack pointer at a controlled location, using up to two ROP gadgets. The stack pointer is currently set at a low value due to the garbage collector setting r1 to that, so it may appear that starting a ROP gadget in the middle of a function is not useful, since it will attempt to free the stack into negative memory. This is actually not the case, because on PowerPC, the stack grows downward, meaning there is actually plenty of space for the stack to be freed, but not much to grow. Because of this, the first ROP gadget can be at the part of a function that is freeing however much of the stack it previously allocated, which is stored in r28, one in the controllable area. Once this is done, the stack pointer is in control. The function chosen happens to save and load the link register, which means the link register can be preloaded with dummy data.
   −
With this in mind, a sequence of bytes can be crafted to meet the needs stated above. First, there needs to be a chain of 3 pointers that point forward to the next. After this, the address to be overwritten must be present, which is the thread context, and the last pointer in the previous chain points to this pointer. When the pointer is overwritten, it points directly at the target address, meaning the rest of the thread context, after the trash bytes, need to be placed there. Finally, after the thread context, the ROP chain is present, which the first two ROP gadgets from the thread context load.
+
At this point, the OSContext is complete; the other part of the OSThread that must be properly set is the pointer to an OSThreadQueue when context switching. This is simply set to 0x80000004, the location of a few disc metadata values that are not relevant to the Internet Channel, as the queue is only written to in an attempt to move the old thread to the end of the linked list.
   −
Now that a hax sequence is built, there needs to be a way to place it directly in memory. Flash does not keep array elements together in memory, so an array is not an option. The other option is a string, which is available, but it has its own issues. Similar to C strings, Flash strings are terminated by null characters, but unlike in C, characters are 2 bytes wide in Flash, meaning strings are terminated by double null bytes. There are several points in the hax string that require padding, such as between the garbage collector iterations, that would normally be set to 0. Since this is not possible here, the [code]\u4141[/code] and [code]\u4242[/code] characters are used instead. These values are also placed into all of the unused registers in the thread context to prevent the string from terminating prematurely.
+
With this in mind, a sequence of bytes can be crafted to meet the needs stated above. First, there needs to be a chain of 3 pointers that point forward to the next. After this, the address to be overwritten must be present, which is the fake OSThread, and the last pointer in the previous chain points to this pointer. When the pointer is overwritten, it points directly at the target address, meaning the rest of OSThread, after the trash bytes, need to be placed there. Finally, after the fake OSThread, the ROP chain is present, which the ROP gadget in OSContext loads.
   −
While the Wii itself does not do any ASLR, Flash does not place its variables in deterministic points in memory. To get around this, a heap spray must be done, which seems like something that will not consistently work. Luckily, when the bookmark bar in the Internet Channel is used to load a page, there is a location in memory that is almost always used, so the exploit must be run from the bookmarks bar. To detect whether the page was loaded using the bookmark bar or another way, a `#stop` parameter is put onto the URL. The Wii removes this tag when adding it to the bookmark bar, so detecting the absence of the `#stop` parameter is enough to make sure the exploit can run consistently.
+
Now that a payload is built, there needs to be a way to place it directly in memory. Flash does not keep array elements together in memory, so an array is not an option. The other option is a string, which is available, but it has its own issues. Similar to C strings, Flash strings are terminated by null characters, but unlike in C, characters are 2 bytes wide in Flash, meaning strings are terminated by double null bytes. There are several points in the hax string that require padding, such as between the garbage collector iterations, that would normally be set to 0. Since this is not possible here, the <code>\u4141</code> and <code>\u4242</code> characters are used instead. These values are also placed into all of the unused registers in OSContext to prevent the string from terminating prematurely.
   −
To make the heap spray work, an array is first built to contain a string byte for every index in the heap spray array to be built. Then, each of these unique string bytes is appended to the hax string to create a new copy of it, placing it many times in memory to make the garbage collector locate it. The address that is usually filled by the hax string is then put into the event listener in the text field from above, making it reach the hax string.
+
While the Wii itself does not do any ASLR, Flash does not place its variables in deterministic points in memory. To get around this, a heap spray must be done, which seems like something that will not consistently work. Luckily, when the bookmark bar in the Internet Channel is used to load a page, there is a location in memory that is almost always used, so the exploit must be run from the bookmarks bar. To detect whether the page was loaded using the bookmark bar or another way, a <code>#stop</code> parameter is put onto the URL. The Wii removes this tag when adding it to the bookmark bar, so detecting the absence of the <code>#stop</code> parameter is enough to make sure the exploit can run consistently.
   −
Now, to make code execution happen, the ROP chain must load some payload into memory. To do so, it calls three ROP gadgets for each integer loaded: one to load the target value into a register, one to load the write address into another register, and one to write to that address using the value. There is a pointer that automatically increments every time this writing is done, easily allowing some code to be loaded. Since this is all in the hax string, however, there cannot be any pair of null bytes in the same word. In the ROP constants, this is done by padding everything with <code>\u4141</code>, but the payload itself cannot be handled this way, limiting what it can do.
+
To make the heap spray work, an array is first built to contain a string byte for every index in the heap spray array to be built. Then, each of these unique string bytes is appended to the hax string to create a new copy of it, placing it many times in memory to make the garbage collector locate it. The address that is usually filled by the hax string is then put into the event listener in the text field from above, making it reach the hax string. The actual collector is triggered by wasting memory to create a need to recycle the memory occupied by the text field.
   −
To solve this, the Flash loader also downloads a second payload as a video, so it is not subject to the string limitations. This second payload starts with an "egg" that is located by the first payload. The first payload then copies the beginning of the second payload into lower memory, where DEP is not present. The second payload then makes high memory executable, and executes the rest of itself, which is actually a modified version of [[Savezelda]] that is capable of downloading the HackMii Installer from online.
+
Now, to make code execution happen, the ROP chain must load some payload into memory. To do so, it calls three ROP gadgets for each integer loaded: one to load the target value into a register, one to load the write address into another register, and one to write to that address using the value. There is a pointer that automatically increments every time this writing is done, easily allowing some code to be loaded. Since this is all in the hax string, however, there cannot be any pair of null bytes in the same word. In the ROP constants, this is done by padding everything with <code>\u4141</code>, but the payload itself cannot be handled this way, limiting what it can do. After all of these writes, the final gadget in the chain is the payload itself, which is jumped to by returning.
 +
 
 +
To solve this, the Flash loader also downloads a second payload as a video, so it is not subject to the string limitations. This second payload starts with an "egg" that is located by the first payload. The first payload then copies the beginning of the second payload into lower memory, where DEP is not present. The second payload then makes high memory executable, and executes the rest of itself, which is actually a modified version of [[Savezelda]] that has the HackMii Installer bundled with it.
5,579

edits