Editing PSJailbreak Exploit Payload Reverse Engineering

Jump to navigation Jump to search
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
= Writeup by phire =
=== Mathieulh @ http://ps3wiki.lan.st/index.php?title=PSJailbreak_Payload_Reverse_Engineering ===
 
''' Source: phire at [https://web.archive.org/web/20120829232220/http://ps3wiki.lan.st/index.php/PSJailbreak_Exploit_Reverse_Engineering ps3wiki.lan.st]'''
----
----
here's my understanding of what the exploit playload does:


== Analysis of the PSJailbreak Exploit ==
#it gets control at exploit_entry, which copies the rest of the payload to the fixed address 0x8000000000700000 and jumps to exploit_main.
 
#exploit_main copies a resident part of the payload to another location, creates virutal usb device driver called "mod" with 3 functions, hooks some vsh functions via toc entry and does some permanent in-ram patching. when the work is done it zeroes itself out.
=== Intro ===
#the resident part has basically 3 purposes: it manages virtual usb device, it does some on-the-fly patching and it hooks all the game disk file accesses from the vsh.
 
##the virtual usb device is needed to make sure the original ps3jb device in plugged in. once the correct device is plugged (the one with the AAAAC0DE) device driver initializes the variable INITIALIZED to 1 (see kmod_func1 - probably "identify device", and kmod_func2 - "initialize device"). if one pluggs the device out, the function kmod_func3_call_panic "term device" is called which causes a kernel panic. all the virtual usb device code can be removed completely from the open psjb implementation since it's just a way of protection for the original ps3jb.
The PSJailbreak dongle is a modchip for the PlayStation3 that allows users to backup and play games off the harddrive. Unlike the modchips of the Previous generation, or the modchips so far for the Xbox360 and Wii, this modchip simply plugs into the USB port on the front of the PS3, avoiding the need for complex soldering and voiding of your warranty.
##the on-the-fly patching part of the code is probably called on virtual memory page remapping and does additional patching in-place. it identifies if the pages requires patching byt calculating it's "hash" and comparing to the table entries. one of the patches enables developer menu/settings called "category_game_tool2.xml#root" which probably enables support of the pkgs and other dev stuff.
 
##the hooks from the vsh are intended to redirect all on-bdvd file requests (or probably just "open") from vsh to the hdd saved backup. the launcher saves the base directory of the game started and after that all the file names are prepended with it. that's how the backup feature works. the lv1 still needs bdvd auth to launch the game, so the original disc in bdvd is still required.<br>
As the time of writing this document, the final PSJailbreak has not been released, but a number of samples were given out and at least one fell into the hands of someone who owned a USB sniffer. This analysis of the exploit is based on those USB sniffer logs, issues encountered during the development of the opensource [http://github.com/psgroove/psgroove PSGroove] version of the exploit and a number of educated guesses. It will probably be updated as new information comes in.
 
The initial analysis by [http://www.gamefreax.de/psjailbreak-reverse-engineered.html gamefreax.de] suggested that it was a Stack overflow attack. After further analist it turns out that this exploit is a [http://en.wikipedia.org/wiki/Heap_overflow Heap Overflow] attack. The exploit carefully manipulates the heap by plugging and unplugging fake usb devices with large device descriptors until the device on port 4 which misreports its size to overwrite one of malloc's boundary tags.
 
----
 
=== The state of the PS3 ===
 
The exploit takes place while the PS3 is looking for the Jig (triggered by pressing eject within 200ms of pressing power). It is suspected that the ps3 spends around 5 seconds doing nothing but initializing devices on the USB bus, so there is little extra code running to mess the exploit up.
 
=== Setting up the heap ===
 
The PSJailbreak dongle emulates a 6 port USB hub. By attaching and detaching fake devices to the ports of the hub the dongle has control over the mallocing and freeing of various blocks of memory that hold the device and configuration descriptors.
 
==== Port one ====
 
After the hub has been initialized, a device is plugged into port one with a pid/vid of 0xAAAA/0x5555, It has 4 configurations with each one is 0xf00 bytes long. This is just under the size of 4k page, so malloc will have probably have request a new page for each one, unless it already has enough free space, but at least one will be aligned at the start of a page.
 
The dongle also changes the configuration the 2nd time it is read so that the configuration in the ps3 memory is only 18 bytes long.
 
It just so happens that that this data contains the payload that the exploit will jump to after gaining control of the execution, but that is not important for the exploit.
 
==== Port two ====
 
After the PS3 has finished reading the port one device descriptors, the dongle switches back to the address of the hub and reports that a device has been plugged into port two.
 
This device has a pid/vid of 0xAAAA/0xBBBB, and it has 1 configuration descriptor which is 22 bytes long. Only the first 18 bytes are real usb data and the remaining 4 bytes are:
<pre>  04 21 B4 2F 
</pre>
With a length of 04 and an invalid type byte, anything interpreting it as USB descriptor will probably skip over it and the last 2 bytes. It is suspected that this is just here to make this descriptor take up an exact amount of heap space.
 
==== Port Three ====
 
The port three device has a pid/vid of 0xAAAA/0x5555, the same as port one. Unlike the port one device it has 2 configuration descirptors, each 0xa4d bytes long The data that fills them is junk but it may or may not be relevant that if you treat the data as descriptors they will have valid lengths. These descriptors will probably be allocated to the start of a fresh 4kb page that follows the page with the last port one descriptor and port three descriptors.
 
==== Port Two Disconnect ====
 
After port three is connected, port two will be disconnected, this will cause the port two descriptors to be freed, which frees up some space between the Port One and Port Three descriptors.
 
----
 
=== The exploit ===
 
The heap is now prepared for our exploit.
 
==== Port Four Connection ====
 
A device is connected to port 4, with a pid/vid of 0xAAAA/0x5555 and 3 configurations.
 
===== Configuration A =====
 
This is a normal configuration, 18 bytes long
 
===== Configuration B =====
 
This configuration is the same as Configuration A, except it changes its total length from 18 bytes to to zero bytes after the PS3 has read it the first time and allocated space for it.
 
This is where things get vague, this is key to the exploit and will somehow cause the the extra data at the end of Configuration C to overwrite one of malloc's boundary tag, most likely the one belonging to Port Three.
 
But the exact reason for this buffer overrun is hard to guess without actually seeing the exploited code.
 
===== Configuration C =====
 
This starts the same as configuration A, but has 14 bytes of extra data at the end.
<pre>.. .. 3e 21 00 00 00 00
fa ce b0 03 aa bb cc dd
80 00 00 00 00 46 50 00
80 00 00 00 00 3d ee 70
</pre>
The first 6 are just padding (but the 3e might be important if this ever gets interpreted as a USB descriptor.) Then there are 3 u64 values, each 8 bytes long.
 
The first two values are stored for use by the shell code later just before malloc's boundary tag.
 
The 3rd value overwrites the first value of the boundary tag, which is pointer to the next free section of memory. The replacement pointer will point to a function somewhere. This will cause a malloc to allocate memory in the wrong place, sometime in the future, allowing the exploit to overwrite an existing function.
 
==== Port Five ====
 
The dongle plugs the fake Jig into Port Five right after Port Four has done its job. It uses the same PID/VID that the original Sony Jig uses (0x054C/0x02EB) and probably the same configuration with the same end points.
 
It is suspected that because the Jig is a known device that the PS3 was waiting for, it's device and configuration descriptors will not be malloced into the heap.
 
The PS3 sends a 64 byte challenge to the fake Jig to authenticate it, and the dongle replies with 64 bytes of static data. The PS3 will malloc space for this response, and because the boundary tags have been modified by Port Four, malloc will return a pointer to 24 bytes before a function that has something to do with free and the 64 bytes of data will be written over top of the function.
 
At the point, no code has been patched yet, so the Jig's static response will fail to authenticate the jig.
 
==== Unplug Port Three ====
 
The dongle now sends a message that port 3 has been unplugged. This will cause the PS3 to free the Port Three's configuration data, the very same buffer which had its boundary tag overwritten by Port Four.
 
So our shellcode gets called, with R3 pointing to the boundary tag before Port Three's Configuration data.
 
==== The Shellcode ====
 
PPC Assembly:
<pre> ROM:00000018                ld    &nbsp;%r4, -0x10(%r3)
ROM:0000001C                ld    &nbsp;%r3, -8(%r3)
ROM:00000020
ROM:00000020 loc_20:                                # CODE XREF: sub_18+14�j
ROM:00000020                ld    &nbsp;%r5, 0x18(%r3)
ROM:00000024                addi  &nbsp;%r3,&nbsp;%r3, 0x1000
ROM:00000028                cmpw  &nbsp;%r4,&nbsp;%r5
ROM:0000002C                bne    loc_20
ROM:00000030                addi  &nbsp;%r6,&nbsp;%r3, -0xFE0
ROM:00000034                mtctr  &nbsp;%r6
ROM:00000038                bctr
</pre>
This takes a pointer to the corrupted boundary tags in r3.
 
r4 is loaded with the 0xFACEB003AABBCCDD tag, then r3 is loaded with 0x8000000000465000, both of these values are stored just before the boundary tag.
 
The shell code then scans every 4KB block (0x1000 bytes) starting at 0x8000000000465000, checking for 0xFACEB003AABBCCDD tag in the u64 at 0x18 in each page.
 
When it finds it, the shellcode will jump to offset 0x20 in the payload.
 
----
 
=== After the exploit ===
 
==== Cleanup ====
 
The exploit is now completed: Port Five, Port Four then Port One will be unplugged.
 
Hopefully the Payload will have copied itself out of the heap before Port One is unplugged.
 
==== Port Six ====
 
The device that gets plugged into Port Six has nothing to do with the exploit. It has a vid/pid of 0xAAAA/0xDEC0 (on the PPC, which is big endian, the pid is 0xC0DE).
 
The payload sends it a single byte (0xAA) control transfer so that the dongle will know that the exploit was successful so it can turn the green LED on to signal the user.
 
A function in the original PSJailbreak Payload will make sure that this device stays plugged in. If it is ever unplugged then it will call LV1_Panic and your PS3 will shutdown. PSGroove has removed this 'feature'.
 
----
 
=== The Payload ===
 
The actual payload is outside the scope of this document (There might be a 2nd document discussing the original PSJailbreak payload), but we will discuss the environment.
 
The payload will start in an unknown position, aligned to a 4KB boundary, it should either use position independent code, or copy itself to a known location. The payload has full control over the lv2 (aka gameos) kernel and anything below it. It doesn't have any control over lv1 (aka the hypervisor) without a 2nd exploit (the original Geohot exploit should still work.)
 
The Jig authentication code is most likely running in lv1 or an isolated SPU so it is not possible to patch it with this exploit.
 
The lv2 kernel is loaded at the time of the exploit, perfect for patching or you could replace it with something better like a linux kernel. A linux kernel running in this environment would have all the privilege of the regular gameos kernel.
 
----
 
''Written up by phire (aka phiren on EFnet). Thanks to Matt_P, subdub and others for helping develop this theory.''
 
''If you have any information to add, feel free to edit this document or use the discussion page.''
 
= Writeup by Mathieulh =
 
Here is my understanding of what the exploit payload does:
 
#It gets control at exploit_entry, which copies the rest of the payload to the fixed address 0x8000000000700000 and jumps to exploit_main.
 
#exploit_main copies a resident part of the payload to another location, creates virtual usb device driver called "mod" with 3 functions, hooks some vsh functions via toc entry and does some permanent in-ram patching. When the work is done it zeroes itself out.
 
#The resident part has basically 3 purposes: it manages virtual usb device, it does some on-the-fly patching and it hooks all the game disk file accesses from the vsh.
 
##The virtual usb device is needed to make sure the original ps3jb device is plugged in. Once the correct usb device is plugged (the one with the AAAAC0DE), device driver initializes the variable INITIALIZED to 1 (see kmod_func1 - probably "identify device", and kmod_func2 - "initialize device"). If one plugs the device out, the function kmod_func3_call_panic aka "term device" is called which causes a kernel panic. All the virtual usb device code can be removed completely from the open PSJB implementation since it is just a way of protection for the original ps3jb.
 
##The on-the-fly patching part of the code is probably called on virtual memory page remapping and does additional patching in-place. It identifies if the pages require patching but calculating its "hash" and comparing to the table entries. One of the patches enables developer menu/settings called "category_game_tool2.xml#root" which probably enables support of the pkgs and other dev stuff.
 
##The hooks from the vsh are intended to redirect all on-bdvd file requests (or probably just "open") from vsh to the hdd saved backup. The launcher saves the base directory of the game started and after that all the filenames are prepended with it. That is how the backup feature works. The lv1 still needs bdvd auth to launch the game, so the original disc in bdvd is still required.<br>
 
#Adds a Syscall (Syscall 36) which will be called by Backup Loader to activate the virtual bluray drive with the correct backed upped disk.
#Adds a Syscall (Syscall 36) which will be called by Backup Loader to activate the virtual bluray drive with the correct backed upped disk.
#Patches the return value from hypercall 99 so that we can launch unsigned apps.
#Patches the return value from hypercall 99 so that we can launch unsigned apps.


The code below is from my idb of the payload:
the code below is from my idb of the payload.
   
   
<pre>
<pre># ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
struct_patch_table struc # (sizeof=0x8)
struct_patch_table struc # (sizeof=0x8)
addr_offset: .long&nbsp;? # offset
addr_offset: .long&nbsp;? # offset
Line 886: Line 718:
ROM:00000000007006E4                b      memset          # we exit by zeroing the payload in mem
ROM:00000000007006E4                b      memset          # we exit by zeroing the payload in mem
ROM:00000000007006E4 # End of function exploit_main
ROM:00000000007006E4 # End of function exploit_main
</pre>
 
</pre>




{{Custom Firmware}}<noinclude>[[Category:Main]]</noinclude>
{{Custom Firmware}}<noinclude>[[Category:Main]]</noinclude>
Please note that all contributions to PS3 Developer wiki are considered to be released under the GNU Free Documentation License 1.2 (see PS3 Developer wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To protect the wiki against automated edit spam, we kindly ask you to solve the following hCaptcha:

Cancel Editing help (opens in new window)