Sponsored Links

Sponsored Links

PS JailBreak PS3 Exploit Reverse Engineering is Detailed!


Sponsored Links
224w ago - Earlier today we reported on the open-source PS JailBreak PS3 exploit from Mathieulh's PlayStation 3 hacking team dubbed PSGroove, and as promised the reverse-engineering details are now available linked above and posted below, as follows:

Analysis of the PSJailbreak Exploit

Intro

The PSJailbreak dongle is a modchip for the PlayStation 3 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.

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 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 gamefreax.de suggested that it was a Stack overflow attack. After further analist it turns out that this exploit is a 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 ps3 also changes the configuration the 2nd time it is read so 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:

04 21 B4 2F

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.

.. .. 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

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:

ROM:00000018 ld %r4, -0x10(%r3)
ROM:0000001C ld %r3, -8(%r3)
ROM:00000020
ROM:00000020 loc_20: # CODE XREF: sub_18+14j
ROM:00000020 ld %r5, 0x18(%r3)
ROM:00000024 addi %r3, %r3, 0x1000
ROM:00000028 cmpw %r4, %r5
ROM:0000002C bne loc_20
ROM:00000030 addi %r6, %r3, -0xFE0
ROM:00000034 mtctr %r6
ROM:00000038 bctr

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.

F.A.Q.

What firmware versions will this work with?

The exploit should work on any firmware version, but the current payload only works on 3.41.

As i read it is not needed to have the dongle plugged in the whole time? My Question is what happens after rebooting the ps3? will homebrews still be installed and bootable?

They will be still installed, but unless you boot with the exploit you can't run them. This might change at a later date, think back to the original xbox softmods.

How hard would it be for Sony to patch this exploit in the next firmware release? If trivial, does that mean that basically this exploit will be useless in a few weeks unless we never update ever again?

Semi-trivial. but yes, in a few weeks don't upgrade your console.

Can this exploit and having full access to lvl 2 faciliate research of other vulnerabilities in the system, or does this not give us more than what dev consoles already have?

I think dev consoles only give access to lvl 2 applications. Besides only a few people have dev consoles, so just having it in reach of more people increases the odds of finding exploits.

Export to other devices like BlackBerry

I think this can be exported to other devices with USB port access, in example, Blackberry phones. Imagine a Blackberry application conected to de PS3 via usb cable runing a java app that do the magic work. Can you help me with tech specs about a similar port? i dont know the abstraction level of the USB BlackBerry Libs, cold be sufficient a serial read/write to the port? thanks!



Stay tuned for more PS3 Hacks and PS3 CFW news, follow us on Twitter, Facebook and be sure to drop by the PS3 Hacks and PS3 Custom Firmware Forums for the latest PlayStation 3 scene and PlayStation 4 scene updates and fresh homebrew releases!

Comments 30 Comments - Go to Forum Thread »

• Please Register at PS3News.com or Login to make comments on Site News articles.
 
#30 - almeida68 - 223w ago
almeida68's Avatar
Great job guys, keep it up!

#29 - emsi - 223w ago
emsi's Avatar
Quote Originally Posted by CodeKiller View Post

in this regards, it theoretically can be used with v-usb (software usb for atmega) as it only bind to 8 bytes-packets: slow-speed usb

bad text-align... sorry, forgot to preview.


Great! I'm highly interested in the posibility to port it to v-usb. This would push down the price of the device to around 10-15$.

#28 - Hugh Jarce - 223w ago
Hugh Jarce's Avatar
Quote Originally Posted by Jes03 View Post
Isn't this just telling $ony how its done so now they know exactly how to patch it?

I certainly hope not. Things are just starting to take off now.

#27 - PS3 News - 224w ago
PS3 News's Avatar
Quote Originally Posted by tragedy View Post
Here's a better disassembly than the previous one:

Very nice job tragedy- Thanks for sharing it here and +Rep!

#26 - tragedy - 224w ago
tragedy's Avatar
Here's a better disassembly than the previous one:
[code]0000000000000000 :

usb_config_desc:.byte 9, 2, 0x12, 0, 1, 0, 0, 0x80, 0xFA
# wTotalLength = 0x0012
# bNumInterfaces = 1
# bConfigurationValue = 0
# iConfiguration = 0
# bmAttributes = not self powered, no remote wakeup
# bMaxPower = 500mA

usb_iface_desc: .byte 9, 4, 0, 0, 0, 0xFE, 1, 2, 0
# bInterfaceNumber = 0
# bAlternateSetting = 0
# bNumEndpoints = 0
# bInterfaceClass = 0xfe (app specific)
# bInterfaceSubclass = 0x01 (DFU)
# bInterfaceProtocol = 0x02 (???)
# iInterface = 0

loc_12: .short 0
.long 0

# this is the marker for the start of the shellcode

18: fa ce b0 03 .long 0xfaceb003
1c: aa bb cc dd .long 0xaabbccdd

# shellcode entered here, r3 = r0+0x1000, nothing else assumed

20: 38 63 f0 00 addi r3,r3,-4096 # fffffffffffff000
24: 38 a0 10 00 li r5,4096 # 1000
28: 38 80 00 01 li r4,1
2c: 78 84 f8 06 rldicr r4,r4,63,0
30: 64 84 00 70 oris r4,r4,112 # r4=0x8000000000700000

# r3=start of shellcode, r4=reloc address, r5=0x1000 (length)
# copy memory block

reloc1_loop:
34: 38 a5 ff f8 addi r5,r5,-8
38: 7c c3 28 2a ldx r6,r3,r5
3c: 7c c4 29 2a stdx r6,r4,r5 # reloc[--index] = shellcode[index]
40: 28 25 00 00 cmpldi r5,0
44: 40 82 ff f0 bne reloc1_loop # more to do, loop

48: 38 84 00 80 addi r4,r4,128
4c: 7c 89 03 a6 mtctr r4
50: 4e 80 04 20 bctr # jump to offset 0x80 in relocated shellcode

################################################################################################

...

8000000000700000 :

# on entry here, the shellcode is now at a known address

# standard stack prologue
8000000000700080: 7c 08 02 a6 mflr r0
8000000000700084: f8 21 ff 61 stdu r1,-160(r1) # ffffffffffffff60
8000000000700088: fb 61 00 78 std r27,120(r1) # 78
800000000070008c: fb 81 00 80 std r28,128(r1) # 80
8000000000700090: fb a1 00 88 std r29,136(r1) # 88
8000000000700094: fb c1 00 90 std r30,144(r1) # 90
8000000000700098: fb e1 00 98 std r31,152(r1) # 98
800000000070009c: f8 01 00 b0 std r0,176(r1) # b0

# set up r31 to base of RAM
80000000007000a0: 3b e0 00 01 li r31,1
80000000007000a4: 7b ff f8 06 rldicr r31,r31,63,0

# relocate the shellcode again
80000000007000a8: 7f e3 fb 78 mr r3,r31
80000000007000ac: 64 63 00 05 oris r3,r3,5
80000000007000b0: 60 63 0b 3c ori r3,r3,2876 # b3c
#r3 = 0x8000 0000 0005 0b3c
80000000007000b4: 7f e4 fb 78 mr r4,r31
80000000007000b8: 64 84 00 70 oris r4,r4,112 # 70
80000000007000bc: 60 84 01 ac ori r4,r4,428 # 1ac
#r4 = 0x8000 0000 0070 01ac = patch_block
80000000007000c0: 38 a0 04 fa li r5,reloc2_end - patch_block #1274 # 4fa
80000000007000c4: 4b 97 bf 59 bl 800000000007c01c
#memcpy( r31+0x50b3c, patch_block, 1274)

#patch a vtable?
80000000007000c8: 7f e3 fb 78 mr r3,r31
80000000007000cc: 64 63 00 05 oris r3,r3,5
80000000007000d0: 60 63 0b 3c ori r3,r3,2876 # b3c
#r3 = 0x8000 0000 0005 0b3c = patch_block
80000000007000d4: 38 63 00 20 addi r3,r3,32 # 20
#r3 = 0x8000 0000 0005 0b5c = vtable
80000000007000d8: 4b 9d 22 01 bl 80000000000d22d8
# ???

#add lv2 syscall
80000000007000dc: 7f e3 fb 78 mr r3,r31
80000000007000e0: 64 63 00 05 oris r3,r3,5
80000000007000e4: 60 63 0b 3c ori r3,r3,2876 # b3c
#r3 = 0x8000 0000 0005 0b3c = patch_block
80000000007000e8: 7f e4 fb 78 mr r4,r31
80000000007000ec: 64 84 00 2e oris r4,r4,46 # 2e
80000000007000f0: 60 84 b1 28 ori r4,r4,45352 # b128
#r4 = 0x8000 0000 002e b128 = syscall function table?
80000000007000f4: 38 63 00 10 addi r3,r3,16
#r3 = 0x8000 0000 0005 0b4c = set_prefix_desc
80000000007000f8: f8 64 01 20 std r3,288(r4) # 120
#syscall_table[0x24] = set_prefix_desc

#patch up various parts of the gameos
80000000007000fc: 7f e5 fb 78 mr r5,r31
8000000000700100: 64 a5 00 70 oris r5,r5,112 # 70
8000000000700104: 60 a5 01 50 ori r5,r5,336 # 150
#r5 = 0x8000 0000 0070 0150 = patch_table
8000000000700108: 80 65 00 00 lwz r3,0(r5)
800000000070010c: 28 03 00 00 cmplwi r3,0
#r3 = address to patch
8000000000700110: 41 82 00 18 beq 8000000000700128
8000000000700114: 80 85 00 04 lwz r4,4(r5)
#r4 = data to put in there
8000000000700118: 7c 63 fa 14 add r3,r3,r31
800000000070011c: 90 83 00 00 stw r4,0(r3)
#add ram base address, store r4 in ram[r3]
8000000000700120: 38 a5 00 08 addi r5,r5,8
8000000000700124: 4b ff ff e4 b 8000000000700108
#loop

patch1_done:
8000000000700128: 48 00 05 88 b patch1_exit

################################################################################################

# this looks like a patch that's never used, very similar to 8000000000050f4c
unused_patch1:
800000000070012c: f8 21 ff 51 stdu r1,-176(r1) # ffffffffffffff50
8000000000700130: 7c 08 02 a6 mflr r0
8000000000700134: fb c1 00 a0 std r30,160(r1) # a0
8000000000700138: fb e1 00 a8 std r31,168(r1) # a8
800000000070013c: fb a1 00 98 std r29,152(r1) # 98
8000000000700140: f8 01 00 c0 std r0,192(r1) # c0
8000000000700144: 3b c0 07 d0 li r30,2000 # 7d0
8000000000700148: 3b e0 00 c8 li r31,200 # c8
800000000070014c: 4b 90 a9 b8 b 800000000000ab04
#sets r30=2000, r31=200, jumps into some function

################################################################################################

#this table is a list of memory addresses (32 bit, turned into 64 bit with high bit set) and values
#to poke into them
patch_table:
#8000000000700150: 00 04 90 e0 .long 0x490e0
#8000000000700154: e8 82 0f 08 ld r4,3848(r2) # f08
#8000000000700158: 00 04 90 e4 .long 0x490e4
#800000000070015c: e8 7c 00 20 ld r3,32(r28) # 20
#8000000000700160: 00 04 90 e8 .long 0x490e8
#8000000000700164: f8 64 00 00 std r3,0(r4)

#patch modifies gameos:
#big leap of faith that this saves the base self address for later patching purposes
80000000000490e0: e8 82 0f 08 ld r4,3848(r2) # f08
80000000000490e4: e8 7c 00 20 ld r3,32(r28) # 20
80000000000490e8: f8 64 00 00 std r3,0(r4)
#globals_self_ptr = 28->ofs_20

#8000000000700168: 00 04 f0 a8 .long 0x4f0a8
#800000000070016c: 48 00 1a 9d bl 8000000000701c08

#patch modifies gameos:
800000000004f0a8: 48 00 1a 9d bl b_patch_self #8000000000050b44

#8000000000700170: 00 2a af c8 .long 0x2aafc8
#8000000000700174: 4b da 5b 80 b 80000000004a5cf4

#patch modifies gameos:
80000000002aafc8: 4b da 5b 80 b b_open_file #8000000000050b48

#8000000000700178: 00 04 ed 18 .long 0x4ed18
#800000000070017c: 38 80 00 00 li r4,0
#8000000000700180: 00 04 ed 1c .long 0x4ed1c
#8000000000700184: 90 83 00 00 stw r4,0(r3)
#8000000000700188: 00 04 ed 20 .long 0x4ed20
#800000000070018c: 4e 80 00 20 blr

#patch modifies gameos:
800000000004ed18: 38 80 00 00 li r4,0
800000000004ed1c: 90 83 00 00 stw r4,0(r3)
800000000004ed20: 4e 80 00 20 blr

#8000000000700190: 00 3b a8 90 .long 0x3ba890
#8000000000700194: 01 00 00 00 .long 0x1000000

#patch modifies gameos:
80000000003ba890: 01 00 00 00 .long 0x1000000

#8000000000700198: 00 05 05 d0 .long 0x505d0
#800000000070019c: 38 60 00 01 li r3,1
#80000000007001a0: 00 05 05 d4 .long 0x505d4
#80000000007001a4: 4e 80 00 20 blr

#patch modifies gameos:
80000000000505d0: 38 60 00 01 li r3,1
80000000000505d4: 4e 80 00 20 blr

#end of table
80000000007001a8: 00 00 00 00 .long 0x0

################################################################################################

8000000000050990 :

patch_block:
80000000007001ac:

# return true
8000000000050b3c: 38 60 00 01 li r3,1
8000000000050b40: 4e 80 00 20 blr

# indirection to patch_self
b_patch_self:
8000000000050b44: 48 00 02 78 b patch_self

# indirection to open_file
b_open_file:
8000000000050b48: 48 00 01 ec b open_file

set_prefix_desc:
8000000000050b4c: .longlong set_prefix # set_prefix
.longlong 0x800000000033e720 # this looks like the r2 reg

vtable:
8000000000050b5c: .longlong str_mod
.longlong check_aaaac0de_desc
.longlong setup_set_prefix_desc
.longlong reset_desc

check_aaaac0de_desc:
8000000000050b7c: .longlong check_aaaac0de
.longlong 0x800000000033e720 # this looks like the r2 reg

setup_set_prefix_desc:
8000000000050b8c: .longlong setup_set_prefix
.longlong 0x800000000033e720 # this looks like the r2 reg

reset_desc:
8000000000050b9c: .longlong reset
.longlong 0x800000000033e720 # this looks like the r2 reg

set_prefix_valid_desc:
8000000000050bac: .longlong set_prefix_valid
.longlong 0x800000000033e720 # this looks like the r2 reg

################################################################################################

prefix_structure:
8000000000050bbc: .longlong 0 # prefix_structure.start
.longlong 0 # prefix_structure.end
.long 0 # prefix_structure.valid

8000000000050bd0: .long 0

################################################################################################

# calls func_d2998(0,1) and checks the PID/VID of the USB device returned.
# if it's 0xaaaa/0xc0de, it returns 0 otherwise it returns -1

check_aaaac0de:
8000000000050bd4: f8 21 ff 81 stdu r1,-128(r1) # ffffffffffffff80
8000000000050bd8: 7c 08 02 a6 mflr r0
8000000000050bdc: f8 01 00 90 std r0,144(r1) # 90
#standard prologue

8000000000050be0: 38 80 00 00 li r4,0
8000000000050be4: 38 a0 00 01 li r5,1
8000000000050be8: 48 08 1d b1 bl 80000000000d2998
#func_d2998(0,1) -> struct

8000000000050bec: 80 a3 00 08 lwz r5,8(r3)
#r5 = PID/VID
8000000000050bf0: 38 60 00 00 li r3,0
8000000000050bf4: 3c 80 aa aa lis r4,-21846 # ffffffffffffaaaa
8000000000050bf8: 60 84 c0 de ori r4,r4,49374 # c0de
#r4 = 0xaaaac0de
8000000000050bfc: 7c 04 28 40 cmplw r4,r5
8000000000050c00: 41 82 00 08 beq 8000000000050c08
8000000000050c04: 38 60 ff ff li r3,-1
8000000000050c08: 7c 63 07 b4 extsw r3,r3
#r3 = 0 if PID/VID == 0xaaaaac0de, -1 otherwise

8000000000050c0c: e8 01 00 90 ld r0,144(r1) # 90
8000000000050c10: 7c 08 03 a6 mtlr r0
8000000000050c14: 38 21 00 80 addi r1,r1,128 # 80
8000000000050c18: 4e 80 00 20 blr
#standard epilogue

################################################################################################

#not really sure what this does. maybe the 0x21aa is sending the 0xaa payload back to the dongle
#for confirmation that it all worked...

setup_set_prefix:
8000000000050c1c: f8 21 ff 81 stdu r1,-128(r1) # ffffffffffffff80
8000000000050c20: 7c 08 02 a6 mflr r0
8000000000050c24: f8 01 00 90 std r0,144(r1) # 90
#standard prologue

8000000000050c28: 38 80 00 00 li r4,0
8000000000050c2c: 48 08 1d 99 bl 80000000000d29c4
#r3 = func_d29c4(0)

8000000000050c30: 38 81 00 70 addi r4,r1,112 # 70
8000000000050c34: 38 a0 00 00 li r5,0
#r5 = 0
8000000000050c38: f8 a4 00 00 std r5,0(r4)
8000000000050c3c: 38 c0 21 aa li r6,8618 # 21aa
8000000000050c40: b0 c4 00 00 sth r6,0(r4)
8000000000050c44: 38 c0 00 00 li r6,0
8000000000050c48: b0 c4 00 06 sth r6,6(r4)
#r4 = temporary struct on stack
#contents: 0x21aa,0x0000,0x0000
8000000000050c4c: 38 c0 00 01 li r6,1
8000000000050c50: 78 c6 f8 06 rldicr r6,r6,63,0
8000000000050c54: 64 c6 00 05 oris r6,r6,5
8000000000050c58: 60 c6 0b ac ori r6,r6,2988 # bac
#r6 = 0x8000 0000 0005 0bac = set_prefix_valid_desc
8000000000050c5c: 38 e0 00 00 li r7,0
8000000000050c60: 48 08 1c cd bl 80000000000d292c
#func_d292c(r3, &struct, 0, &set_prefix_valid_desc, 0)
8000000000050c64: 38 60 00 00 li r3,0
#return 0

8000000000050c68: e8 01 00 90 ld r0,144(r1) # 90
8000000000050c6c: 7c 08 03 a6 mtlr r0
8000000000050c70: 38 21 00 80 addi r1,r1,128 # 80
8000000000050c74: 4e 80 00 20 blr
#standard epilogue

################################################################################################

reset:
8000000000050c78: 38 60 00 00 li r3,0
8000000000050c7c: 39 60 00 ff li r11,255 # ff
8000000000050c80: 44 00 00 22 sc 1
#lv1_panic(0) - reset ps3

################################################################################################

# if paramater is 0, then set prefix_structure.valid = 1
# looks designed to parse the result from check_aaaac0de so that the /dev_bdvd mapping only
# happens if everything worked ok

set_prefix_valid:
8000000000050c84: 2c 03 00 00 cmpwi r3,0
8000000000050c88: 40 82 00 1c bne 8000000000050ca4
#if r3 != 0, skip this code
8000000000050c8c: 38 60 00 01 li r3,1
8000000000050c90: 78 63 f8 06 rldicr r3,r3,63,0
8000000000050c94: 64 63 00 05 oris r3,r3,5
8000000000050c98: 60 63 0b bc ori r3,r3,3004 # bbc
#r3 = 0x8000 0000 0005 0bbc = prefix_structure
8000000000050c9c: 38 80 00 01 li r4,1
8000000000050ca0: 90 83 00 10 stw r4,16(r3)
#prefix_structure.valid = 1
8000000000050ca4: 4e 80 00 20 blr

################################################################################################

set_prefix:
8000000000050ca8: f8 21 ff 31 stdu r1,-208(r1) # ffffffffffffff30
8000000000050cac: 7c 08 02 a6 mflr r0
8000000000050cb0: f8 01 00 e0 std r0,224(r1) # e0
8000000000050cb4: fb e1 00 c8 std r31,200(r1) # c8
#standard prologue

8000000000050cb8: 38 81 00 70 addi r4,r1,112 # 70
8000000000050cbc: 48 16 2e 81 bl 80000000001b3b3c
#func_1b3b3c(&var)

8000000000050cc0: 3b e0 00 01 li r31,1
8000000000050cc4: 7b ff f8 06 rldicr r31,r31,63,0
8000000000050cc8: 67 ff 00 05 oris r31,r31,5
8000000000050ccc: 63 ff 0b bc ori r31,r31,3004 # bbc
#r31 = 0x8000 0000 0005 0bbc = prefix_structure

8000000000050cd0: e8 7f 00 00 ld r3,0(r31)
8000000000050cd4: 2c 23 00 00 cmpdi r3,0
8000000000050cd8: 41 82 00 0c beq 8000000000050ce4
#if prefix_structure.start != 0
8000000000050cdc: 38 80 00 27 li r4,39 # 27
8000000000050ce0: 48 01 17 e9 bl 80000000000624c8
#func_624c8(prefix_structure.start, 0x27)

8000000000050ce4: 38 80 00 27 li r4,39 # 27
8000000000050ce8: 38 60 08 00 li r3,2048 # 800
8000000000050cec: 48 01 13 9d bl 8000000000062088
8000000000050cf0: f8 7f 00 00 std r3,0(r31)
#prefix_structure.start = func_62088(2048,0x27)

8000000000050cf4: e8 81 00 70 ld r4,112(r1) # 70
8000000000050cf8: 4b ff c5 f9 bl 800000000004d2f0
#func_4d2f0(prefix_structure.start, var)

8000000000050cfc: e8 61 00 70 ld r3,112(r1) # 70
8000000000050d00: 38 80 00 27 li r4,39 # 27
8000000000050d04: 48 01 17 c5 bl 80000000000624c8
#func_624c8(var, 0x27)

8000000000050d08: e8 7f 00 00 ld r3,0(r31)
8000000000050d0c: 4b ff c6 0d bl 800000000004d318
#r3 = func_4d318(prefix_structure.start)
8000000000050d10: e8 9f 00 00 ld r4,0(r31)
8000000000050d14: 7c 64 1a 14 add r3,r4,r3
8000000000050d18: f8 7f 00 08 std r3,8(r31)
#prefix_structure.end = prefix_structure.start + strlen(prefix_structure.start)

8000000000050d1c: 38 60 00 00 li r3,0
8000000000050d20: eb e1 00 c8 ld r31,200(r1) # c8
8000000000050d24: e8 01 00 e0 ld r0,224(r1) # e0
8000000000050d28: 38 21 00 d0 addi r1,r1,208 # d0
8000000000050d2c: 7c 08 03 a6 mtlr r0
8000000000050d30: 4e 80 00 20 blr
#standard epilogue

################################################################################################

open_file:
8000000000050d34: f8 21 ff 61 stdu r1,-160(r1) # ffffffffffffff60
8000000000050d38: 7c 08 02 a6 mflr r0
8000000000050d3c: fb 81 00 80 std r28,128(r1) # 80
8000000000050d40: fb a1 00 88 std r29,136(r1) # 88
8000000000050d44: fb e1 00 98 std r31,152(r1) # 98
8000000000050d48: fb 41 00 70 std r26,112(r1) # 70
8000000000050d4c: fb 61 00 78 std r27,120(r1) # 78
8000000000050d50: f8 01 00 b0 std r0,176(r1) # b0
#standard prologue

8000000000050d54: 7c 9c 23 78 mr r28,r4
8000000000050d58: 7c 7d 1b 78 mr r29,r3
#save params in (r29,r28)

8000000000050d5c: 3b e0 00 01 li r31,1
8000000000050d60: 7b ff f8 06 rldicr r31,r31,63,0
8000000000050d64: 7f a3 eb 78 mr r3,r29
#r3 = filename
8000000000050d68: 7f e4 fb 78 mr r4,r31
8000000000050d6c: 64 84 00 05 oris r4,r4,5
8000000000050d70: 60 84 10 28 ori r4,r4,4136 # 1028
#r4 = 0x8000 0000 0005 b1028 = str_bdvd = "/dev_bdvd\0"
8000000000050d74: 38 a0 00 09 li r5,9
8000000000050d78: 4b ff c5 cd bl 800000000004d344
#r3 = func_4d344(filename, "/dev_bdvd", 9) - assuming this is strncmp

8000000000050d7c: 28 23 00 00 cmpldi r3,0
8000000000050d80: 40 82 00 34 bne 8000000000050db4
#no match with /dev_bdvd, skip the patch code (remember r29 holds original filename)

8000000000050d84: 67 ff 00 05 oris r31,r31,5
8000000000050d88: 63 ff 0b bc ori r31,r31,3004 # bbc
#r31 = 0x8000 0000 0005 0bbc = prefix_structure

8000000000050d8c: 80 7f 00 10 lwz r3,16(r31)
8000000000050d90: 28 03 00 00 cmplwi r3,0
8000000000050d94: 41 82 00 20 beq 8000000000050db4
#if prefix_structure.valid == 0, skip the patch code (dongle not initialised)

8000000000050d98: e8 7f 00 00 ld r3,0(r31)
8000000000050d9c: 28 23 00 00 cmpldi r3,0
8000000000050da0: 41 82 00 14 beq 8000000000050db4
#if prefix_structure.start == 0, skip the patch (prefix not set up)

8000000000050da4: e8 7f 00 08 ld r3,8(r31)
8000000000050da8: 38 9d 00 09 addi r4,r29,9
8000000000050dac: 4b ff c5 45 bl 800000000004d2f0
#func_4d2f0(prefix_structure.end, filename+9) - assuming this is strcpy

8000000000050db0: eb bf 00 00 ld r29,0(r31)
#r29 = prefix_structure.start - change the filename we're gonna use

8000000000050db4: 7f a3 eb 78 mr r3,r29
8000000000050db8: 48 25 a2 38 b 80000000002aaff0
#update r3 with our updated string and jump back into the original code

################################################################################################

# this looks like it's patching a self file once it's been loaded, but it's possible that it's
# actually patching arbitrary data files... will need more investigation when i get my hardware and from
# that get myself and lv2 dump

patch_self:
8000000000050dbc: 7c 08 02 a6 mflr r0
8000000000050dc0: f8 21 fe 61 stdu r1,-416(r1) # fffffffffffffe60
8000000000050dc4: fb 61 00 78 std r27,120(r1) # 78
8000000000050dc8: fb 81 00 80 std r28,128(r1) # 80
8000000000050dcc: fb a1 00 88 std r29,136(r1) # 88
8000000000050dd0: fb c1 00 90 std r30,144(r1) # 90
8000000000050dd4: fb e1 00 98 std r31,152(r1) # 98
8000000000050dd8: f8 01 01 b0 std r0,432(r1) # 1b0
#standard prologue

8000000000050ddc: 7c 7d 1b 78 mr r29,r3
8000000000050de0: 7c 9e 23 78 mr r30,r4
#save input params in (r29,r30)
8000000000050de4: 3b e0 00 01 li r31,1
8000000000050de8: 7b ff f8 06 rldicr r31,r31,63,0
#r31 = 0x8000 0000 0000 0000 = base of ram

8000000000050dec: eb 82 96 00 ld r28,-27136(r2) # ffffffffffff9600
8000000000050df0: eb 9c 00 68 ld r28,104(r28) # 68
8000000000050df4: eb 9c 00 18 ld r28,24(r28) # 18
#r28 = globals_ffff9600->ofs_68->ofs_24

8000000000050df8: eb 62 0f 08 ld r27,3848(r2) # f08
#r27 = globals_self_ptr

8000000000050dfc: e9 3d 00 18 ld r9,24(r29) # 18
8000000000050e00: 81 29 00 30 lwz r9,48(r9) # 30
8000000000050e04: 79 29 84 02 rldicl r9,r9,48,16
#r9 = param1->ofs_18->ofs_30 >> 16

8000000000050e08: 2c 09 00 29 cmpwi r9,41 # 29
8000000000050e0c: 40 82 00 58 bne 8000000000050e64
#if r9=='\'' {
8000000000050e10: e8 9c 00 10 ld r4,16(r28)
8000000000050e14: 78 85 c1 e4 rldicr r5,r4,24,39 # > 56, shift back down 24 + 32 bits
#if ( ((r28->ofs_16 >> 32) & 255) == 255) {
8000000000050e1c: 2c 05 00 ff cmpwi r5,255 # ff
8000000000050e20: 41 82 00 18 beq 8000000000050e38

8000000000050e24: 60 84 00 03 ori r4,r4,3
8000000000050e28: f8 9c 00 10 std r4,16(r28)
#r28->ofs_16 |= 3
8000000000050e2c: 38 60 00 06 li r3,6
8000000000050e30: 90 7e 00 00 stw r3,0(r30)
#*param2=6
8000000000050e34: 48 00 00 14 b 8000000000050e48
#} else {
8000000000050e38: 60 84 00 02 ori r4,r4,2
8000000000050e3c: f8 9c 00 10 std r4,16(r28)
#r28->ofs_16 |= 3
8000000000050e40: 38 60 00 2c li r3,44 # 2c
8000000000050e44: 90 7e 00 00 stw r3,0(r30)
#*param2=44
#}

8000000000050e48: 80 bc 00 04 lwz r5,4(r28)
8000000000050e4c: e8 9c 00 08 ld r4,8(r28)
8000000000050e50: e8 7b 00 00 ld r3,0(r27)
#r3= *globals_self_ptr = address to write to
#r4 = r28->ofs_8 = source
#r5 = r28->ofs_4 = length
8000000000050e54: 7d 23 2a 14 add r9,r3,r5
8000000000050e58: f9 3b 00 00 std r9,0(r27)
#*globals_self_ptr += r28->ofs_4
8000000000050e5c: 48 02 b1 c1 bl 800000000007c01c
#memcpy(r3, r28->ofs_8, r5) - nb r5 before the +=

8000000000050e60: 48 00 00 c4 b 8000000000050f24
#skip to prologue
#} else {

8000000000050e64: 7f a3 eb 78 mr r3,r29
8000000000050e68: 7f c4 f3 78 mr r4,r30
8000000000050e6c: 4b ff d9 b1 bl 800000000004e81c
#func_4e81c(param1,param2)

8000000000050e70: 7f fd fb 78 mr r29,r31
8000000000050e74: 67 bd 00 05 oris r29,r29,5
8000000000050e78: 63 bd 0b d0 ori r29,r29,3024 # bd0
#r29 = 0x8000 0000 0005 0bd0 = unknown

8000000000050e7c: 80 7d 00 00 lwz r3,0(r29)
8000000000050e80: 80 bc 00 04 lwz r5,4(r28)
8000000000050e84: 7c 63 2a 14 add r3,r3,r5
8000000000050e88: 90 7d 00 00 stw r3,0(r29)
*r29 += r28->ofs_4

8000000000050e8c: e8 9c 00 10 ld r4,16(r28)
8000000000050e90: 78 85 c1 e4 rldicr r5,r4,24,39 # > 56, shift back down 24 + 32 bits
8000000000050e98: 2c 05 00 ff cmpwi r5,255 # ff
8000000000050e9c: 40 82 00 88 bne 8000000000050f24
#if ( ((r28->ofs_16 >> 32) & 255) == 255) {

8000000000050ea0: e8 7b 00 00 ld r3,0(r27)
#r3 = addr = *globals_self_ptr
8000000000050ea4: 38 80 00 00 li r4,0
#r4 = offset = 0
8000000000050ea8: 38 c0 00 00 li r6,0
#r6 = hash =0

hash_loop:
8000000000050eac: 7c e3 22 14 add r7,r3,r4
8000000000050eb0: 80 a7 00 00 lwz r5,0(r7)
8000000000050eb4: 7c c6 2a 78 xor r6,r6,r5
8000000000050eb8: 38 84 00 04 addi r4,r4,4
#hash ^= r3[offset++]
8000000000050ebc: 28 24 04 00 cmpldi r4,1024 # 400
8000000000050ec0: 40 82 ff ec bne 8000000000050eac
#repeat until offset < 1024 bytes / 256 words

8000000000050ec4: 80 7d 00 00 lwz r3,0(r29)
8000000000050ec8: 78 c6 07 c6 rldicr r6,r6,32,31 # 1f
8000000000050ecc: 7c c6 1b 78 or r6,r6,r3
#r6 = (hash

 

Sponsored Links

Sponsored Links
Sponsored Links

Sponsored Links







Advertising - Affiliates - Contact Us - PS3 Downloads - Privacy Statement - Site Rules - Top - © 2015 PlayStation 3 News