PS4 News on Facebook! PS4 News on Twitter! PS4 News on YouTube! PS4 News RSS Feed!

Home PS4 News - Latest PlayStation 4 and PS3 News

September 15, 2010 // 8:58 pm - A few weeks back we reported on the PS JailBreak PS3 exploit reverse engineering followed by the PSJailBreak PS3 exploit payload, and today naehrwert has focused on the PSJailBreak payload itself, as follows:

PSJailbreak Payload Reverse Engineering

Here's my understanding of what the exploit playload does:

1. it gets control at exploit_entry, which copies the rest of the payload to the fixed address 0x8000000000700000 and jumps to exploit_main.

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

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

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

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

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

4. Adds a Syscall (Syscall 36) which will be called by Backup Loader to activate the virtual bluray drive with the correct backed upped disk.

5. Patches the return value from hypercall 99 so that we can launch unsigned apps.

the code below is from my idb of the payload.

# ---------------------------------------------------------------------------
struct_patch_table struc # (sizeof=0x8)
addr_offset: .long ? # offset
patch_value: .long ? # value
struct_patch_table ends

# ===========================================================================
ROM:0000000000050B3C # This looks like an existing function being overwritten to return 1 and use its content's space
ROM:0000000000050B3C # to add the payload.. any idea what was in it ?
ROM:0000000000050B3C sub_50B3C:
ROM:0000000000050B3C li %r3, 1
ROM:0000000000050B40 blr
ROM:0000000000050B40 # End of function sub_50B3C
ROM:0000000000050B44 # ---------------------------------------------------------------------------
ROM:0000000000050B44 b some_additional_patching_on_the_fly
ROM:0000000000050B48 # ---------------------------------------------------------------------------
ROM:0000000000050B48 b hook_open
ROM:0000000000050B48 # ---------------------------------------------------------------------------
ROM:0000000000050B4C .quad 0x8000000000050CA8 # 50CA8 - ptr to Syscall 36
ROM:0000000000050B54 .quad 0x800000000033E720
ROM:0000000000050B5C .quad 0x8000000000051032 # 51032 - structure for add_kmod {char* name, = "mod"
ROM:0000000000050B64 .quad 0x8000000000050B7C # 50B7C struct func *probe,
ROM:0000000000050B6C .quad 0x8000000000050B8C # 50B8C struct func *initialize,
ROM:0000000000050B74 .quad 0x8000000000050B9C # 50B9C struct func *disconnect}
ROM:0000000000050B7C .quad 0x8000000000050BD4 # 50BD4 - struct func {function_ptr, = kmod_func1
ROM:0000000000050B84 .quad 0x800000000033E720 # user_data?}
ROM:0000000000050B8C .quad 0x8000000000050C1C # 50C1C - struct func {function_ptr, = kmod_func2
ROM:0000000000050B94 .quad 0x800000000033E720 # user_data?}
ROM:0000000000050B9C .quad 0x8000000000050C78 # 50C78 - struct func {function_ptr, = kmod_func3
ROM:0000000000050BA4 .quad 0x800000000033E720 # user_data?}
ROM:0000000000050BAC .quad 0x8000000000050C84 # 50C84 - ptr to set_initialized_flag (unused)
ROM:0000000000050BB4 .quad 0x800000000033E720 # user_data?}
ROM:0000000000050BBC GAME_NAME_PTR: .quad 0
ROM:0000000000050BC4 GAME_MOUNTPOINT_PTR:.quad 0
ROM:0000000000050BCC INITIALIZED: .long 0
ROM:0000000000050BD0 .byte 0
ROM:0000000000050BD1 .byte 0
ROM:0000000000050BD2 .byte 0
ROM:0000000000050BD3 .byte 0
ROM:0000000000050BD4 # =============== S U B R O U T I N E =======================================
ROM:0000000000050BD4 kmod_func1:
ROM:0000000000050BD4 .set var_80, -0x80
ROM:0000000000050BD4 .set arg_90, 0x90
ROM:0000000000050BD4 stdu %sp, var_80(%sp)
ROM:0000000000050BD8 mflr %r0
ROM:0000000000050BDC std %r0, arg_90(%sp)
ROM:0000000000050BE0 li %r4, 0
ROM:0000000000050BE4 li %r5, 1
ROM:0000000000050BE8 bl unk_D2998
ROM:0000000000050BEC lwz %r5, 8(%r3)
ROM:0000000000050BF0 li %r3, 0
ROM:0000000000050BF4 lis %r4, -0x5556 # 0xAAAAC0DE
ROM:0000000000050BF8 ori %r4, %r4, -0x3F22 # 0xAAAAC0DE
ROM:0000000000050BFC cmplw %r4, %r5
ROM:0000000000050C00 beq loc_50C08
ROM:0000000000050C04 li %r3, -1
ROM:0000000000050C08 loc_50C08: # CODE XREF: kmod_func1+2Cj
ROM:0000000000050C08 extsw %r3, %r3
ROM:0000000000050C0C ld %r0, arg_90(%sp)
ROM:0000000000050C10 mtlr %r0
ROM:0000000000050C14 addi %sp, %sp, 0x80
ROM:0000000000050C18 blr
ROM:0000000000050C18 # End of function kmod_func1
ROM:0000000000050C18 # ---------------------------------------------------------------------------
ROM:0000000000050C18 kmod_func1 (arg1):
ROM:0000000000050C18 {
ROM:0000000000050C18 char *desc = unk_D2998(arg1, 0, 1); /* get_device_descriptor? */
ROM:0000000000050C18 if(*(uint32_t *)(desc+8) == 0xAAAAC0DE) /* sorry for the ugly cast */
ROM:0000000000050C18 return 0;
ROM:0000000000050C18 else
ROM:0000000000050C18 return -1;
ROM:0000000000050C18 }
ROM:0000000000050C1C # =============== S U B R O U T I N E =======================================
ROM:0000000000050C1C kmod_func2:
ROM:0000000000050C1C .set var_80, -0x80
ROM:0000000000050C1C .set arg_70, 0x70
ROM:0000000000050C1C .set arg_90, 0x90
ROM:0000000000050C1C stdu %sp, var_80(%sp)
ROM:0000000000050C20 mflr %r0
ROM:0000000000050C24 std %r0, arg_90(%sp)
ROM:0000000000050C28 li %r4, 0
ROM:0000000000050C2C bl unk_D29C4
ROM:0000000000050C30 addi %r4, %sp, arg_70
ROM:0000000000050C34 li %r5, 0
ROM:0000000000050C38 std %r5, 0(%r4)
ROM:0000000000050C3C li %r6, 0x21AA
ROM:0000000000050C40 sth %r6, 0(%r4)
ROM:0000000000050C44 li %r6, 0
ROM:0000000000050C48 sth %r6, 6(%r4)
ROM:0000000000050C4C li %r6, 1
ROM:0000000000050C50 rldicr %r6, %r6, 63,0
ROM:0000000000050C54 oris %r6, %r6, 5
ROM:0000000000050C58 ori %r6, %r6, 0xBAC # 50bac, desc for set_initialized_flag
ROM:0000000000050C5C li %r7, 0
ROM:0000000000050C60 bl unk_D292C
ROM:0000000000050C64 li %r3, 0
ROM:0000000000050C68 ld %r0, arg_90(%sp)
ROM:0000000000050C6C mtlr %r0
ROM:0000000000050C70 addi %sp, %sp, 0x80
ROM:0000000000050C74 blr
ROM:0000000000050C74 # End of function kmod_func2
ROM:0000000000050C74 # ---------------------------------------------------------------------------
ROM:0000000000050C74 kmod_func2 (arg1):
ROM:0000000000050C74 {
ROM:0000000000050C74 uint64 buf;
ROM:0000000000050C74 unk_D29C4 (arg1, 0);
ROM:0000000000050C74 buf = 0;
ROM:0000000000050C74 ((short *)&buf)[0] = 0x21AA;
ROM:0000000000050C74 ((short *)&buf)[3] = 0;
ROM:0000000000050C74 unk_D292C (arg1, buf, 0, ptr_to_set_initialized_flag, 0) /* send 0xAA class-type SETUP request to the device */
ROM:0000000000050C74 return 0;
ROM:0000000000050C74 }
ROM:0000000000050C78 # =============== S U B R O U T I N E =======================================
ROM:0000000000050C78 kmod_func3_call_panic:
ROM:0000000000050C78 li %r3, 0
ROM:0000000000050C7C li %r11, 0xFF
ROM:0000000000050C80 hvsc
ROM:0000000000050C80 # End of function kmod_func3_call_panic
ROM:0000000000050C80 # ---------------------------------------------------------------------------
ROM:0000000000050C80 kmod_func3:
ROM:0000000000050C80 {
ROM:0000000000050C80 hvsc(-1, 0); /* LV1 panic */
ROM:0000000000050C80 }
ROM:0000000000050C84 # =============== S U B R O U T I N E =======================================
ROM:0000000000050C84 set_initialized_flag:
ROM:0000000000050C84 cmpwi %r3, 0
ROM:0000000000050C88 bne locret_50CA4
ROM:0000000000050C8C li %r3, 1
ROM:0000000000050C90 rldicr %r3, %r3, 63,0
ROM:0000000000050C94 oris %r3, %r3, 5
ROM:0000000000050C98 ori %r3, %r3, 0xBBC # 50bbc
ROM:0000000000050C9C li %r4, 1
ROM:0000000000050CA0 stw %r4, 0x10(%r3) # INITIALIZED
ROM:0000000000050CA4 locret_50CA4: # CODE XREF: set_initialized_flag+4j
ROM:0000000000050CA4 blr
ROM:0000000000050CA4 # End of function set_initialized_flag
ROM:0000000000050CA4 # ---------------------------------------------------------------------------
ROM:0000000000050CA4 set_initialized_flag:
ROM:0000000000050CA4 {
ROM:0000000000050CA4 ptr_to_initialized = 1;
ROM:0000000000050CA4 }
ROM:0000000000050CA8 # =============== S U B R O U T I N E =======================================
ROM:0000000000050CA8 Syscall_36_activate_virtual_bluray_drive:
ROM:0000000000050CA8 .set var_D0, -0xD0
ROM:0000000000050CA8 .set arg_70, 0x70
ROM:0000000000050CA8 .set arg_C8, 0xC8
ROM:0000000000050CA8 .set arg_E0, 0xE0
ROM:0000000000050CA8 stdu %sp, var_D0(%sp)
ROM:0000000000050CAC mflr %r0
ROM:0000000000050CB0 std %r0, arg_E0(%sp)
ROM:0000000000050CB4 std %r31, arg_C8(%sp)
ROM:0000000000050CB8 addi %r4, %sp, arg_70
ROM:0000000000050CBC bl unk_1B3B3C # strdup %r3 into %r4 (pointing to arg_70 on the stack)
ROM:0000000000050CC0 li %r31, 1
ROM:0000000000050CC4 rldicr %r31, %r31, 63,0
ROM:0000000000050CC8 oris %r31, %r31, 5
ROM:0000000000050CCC ori %r31, %r31, 0xBBC # 50bbc
ROM:0000000000050CD0 ld %r3, 0(%r31)
ROM:0000000000050CD4 cmpdi %r3, 0
ROM:0000000000050CD8 beq loc_50CE4
ROM:0000000000050CDC li %r4, 0x27 # we free previous redirected name if we must
ROM:0000000000050CE0 bl free
ROM:0000000000050CE4 loc_50CE4: # CODE XREF: +30j
ROM:0000000000050CE4 li %r4, 0x27
ROM:0000000000050CE8 li %r3, 0x800 # alloc new one
ROM:0000000000050CEC bl alloc
ROM:0000000000050CF0 std %r3, 0(%r31)
ROM:0000000000050CF4 ld %r4, arg_70(%sp) # and copy new one here
ROM:0000000000050CF8 bl strcpy
ROM:0000000000050CFC ld %r3, arg_70(%sp) # we free the passed one
ROM:0000000000050D00 li %r4, 0x27
ROM:0000000000050D04 bl free
ROM:0000000000050D08 ld %r3, 0(%r31)
ROM:0000000000050D0C bl byte_4D318
ROM:0000000000050D10 ld %r4, 0(%r31) # we get strlen of game name
ROM:0000000000050D14 add %r3, %r4, %r3
ROM:0000000000050D18 std %r3, 8(%r31) # and save the game path + strlen (the end of the string) in the mount path var
ROM:0000000000050D1C li %r3, 0
ROM:0000000000050D20 ld %r31, arg_C8(%sp)
ROM:0000000000050D24 ld %r0, arg_E0(%sp)
ROM:0000000000050D28 addi %sp, %sp, 0xD0
ROM:0000000000050D2C mtlr %r0
ROM:0000000000050D30 blr
ROM:0000000000050D30 # End of function Syscall_36_activate_virtual_bluray_drive
ROM:0000000000050D30 Syscall_36_activate_virtual_bluray_drive (path):
ROM:0000000000050D30 {
ROM:0000000000050D30 char *tmp = strdup (path);
ROM:0000000000050D30 if (global_game_path)
ROM:0000000000050D30 free(global_game_path);
ROM:0000000000050D30 global_game_path = malloc (2048);
ROM:0000000000050D30 strcpy(global_game_path, tmp);
ROM:0000000000050D30 free (tmp);
ROM:0000000000050D30 global_game_path_end = global_game_path + strlen(global_game_path);
ROM:0000000000050D30 }
ROM:0000000000050D34 # =============== S U B R O U T I N E =======================================
ROM:0000000000050D34 hook_open:
ROM:0000000000050D34 # CODE XREF: ROM:0000000000050B48j
ROM:0000000000050D34 .set var_A0, -0xA0
ROM:0000000000050D34 .set arg_70, 0x70
ROM:0000000000050D34 .set arg_78, 0x78
ROM:0000000000050D34 .set arg_80, 0x80
ROM:0000000000050D34 .set arg_88, 0x88
ROM:0000000000050D34 .set arg_98, 0x98
ROM:0000000000050D34 .set arg_B0, 0xB0
ROM:0000000000050D34 stdu %sp, var_A0(%sp)
ROM:0000000000050D38 mflr %r0
ROM:0000000000050D3C std %r28, arg_80(%sp)
ROM:0000000000050D40 std %r29, arg_88(%sp)
ROM:0000000000050D44 std %r31, arg_98(%sp)
ROM:0000000000050D48 std %r26, arg_70(%sp)
ROM:0000000000050D4C std %r27, arg_78(%sp)
ROM:0000000000050D50 std %r0, arg_B0(%sp)
ROM:0000000000050D54 mr %r28, %r4
ROM:0000000000050D58 mr %r29, %r3
ROM:0000000000050D5C li %r31, 1
ROM:0000000000050D60 rldicr %r31, %r31, 63,0
ROM:0000000000050D64 mr %r3, %r29
ROM:0000000000050D68 mr %r4, %r31
ROM:0000000000050D6C oris %r4, %r4, 5
ROM:0000000000050D70 ori %r4, %r4, 0x1028 # 51028
ROM:0000000000050D74 li %r5, 9
ROM:0000000000050D78 bl strncmp # we check if the file was requested from the bdvd
ROM:0000000000050D7C cmpldi %r3, 0
ROM:0000000000050D80 bne proceed
ROM:0000000000050D84 oris %r31, %r31, 5
ROM:0000000000050D88 ori %r31, %r31, 0xBBC # 50bbc
ROM:0000000000050D8C lwz %r3, 0x10(%r31) # we check if we initialized
ROM:0000000000050D8C # see INITIALIZED set by a usb device kmod
ROM:0000000000050D8C #
ROM:0000000000050D8C # probably can remove this check without any consequences
ROM:0000000000050D90 cmplwi %r3, 0
ROM:0000000000050D94 beq proceed
ROM:0000000000050D98 ld %r3, 0(%r31) # we check if we have GAME_NAME buffer allocated
ROM:0000000000050D9C cmpldi %r3, 0
ROM:0000000000050DA0 beq proceed
ROM:0000000000050DA4 ld %r3, 8(%r31) # GAME_MOUNTPOINT_PTR
ROM:0000000000050DA8 addi %r4, %r29, 9 # we copy the path (+9) into the GAME_NAME allocated buffer
ROM:0000000000050DAC bl strcpy
ROM:0000000000050DB0 ld %r29, 0(%r31) # Change the path to the GAME_NAME buffer
ROM:0000000000050DB4 proceed: # CODE XREF: calback_from_vsh_accessing_any_game_file+4Cj
ROM:0000000000050DB4 # calback_from_vsh_accessing_any_game_file+60j ...
ROM:0000000000050DB4 mr %r3, %r29
ROM:0000000000050DB8 b proceed_to_original_call
ROM:0000000000050DB8 # End of function hook_open
ROM:0000000000050DB8 hook_open (path, mode, etc...):
ROM:0000000000050DB8 {
ROM:0000000000050DB8 if (strncmp(path, "/dev_bdvd", 9) == 0 && initialized_flag == 1 && global_game_path != NULL) {
ROM:0000000000050DB8 strcpy (global_game_path_end, path + 9);
ROM:0000000000050DB8 path = global_game_path;
ROM:0000000000050DB8 }
ROM:0000000000050DB8 return original_open(path, mode, etc...);
ROM:0000000000050DB8 }
ROM:0000000000050DBC # =============== S U B R O U T I N E =======================================
ROM:0000000000050DBC some_additional_patching_on_the_fly: # CODE XREF: ROM:0000000000050B44j
ROM:0000000000050DBC .set var_1A0, -0x1A0
ROM:0000000000050DBC .set arg_78, 0x78
ROM:0000000000050DBC .set arg_80, 0x80
ROM:0000000000050DBC .set arg_88, 0x88
ROM:0000000000050DBC .set arg_90, 0x90
ROM:0000000000050DBC .set arg_98, 0x98
ROM:0000000000050DBC .set arg_1B0, 0x1B0
ROM:0000000000050DBC mflr %r0
ROM:0000000000050DC0 stdu %sp, var_1A0(%sp)
ROM:0000000000050DC4 std %r27, arg_78(%sp)
ROM:0000000000050DC8 std %r28, arg_80(%sp)
ROM:0000000000050DCC std %r29, arg_88(%sp)
ROM:0000000000050DD0 std %r30, arg_90(%sp)
ROM:0000000000050DD4 std %r31, arg_98(%sp)
ROM:0000000000050DD8 std %r0, arg_1B0(%sp)
ROM:0000000000050DDC mr %r29, %r3
ROM:0000000000050DE0 mr %r30, %r4
ROM:0000000000050DE4 li %r31, 1
ROM:0000000000050DE8 rldicr %r31, %r31, 63,0
ROM:0000000000050DEC ld %r28, -0x6A00(%rtoc)
ROM:0000000000050DF0 ld %r28, 0x68(%r28)
ROM:0000000000050DF4 ld %r28, 0x18(%r28)
ROM:0000000000050DF8 ld %r27, 0xF08(%rtoc)
ROM:0000000000050DFC ld %r9, 0x18(%r29)
ROM:0000000000050E00 lwz %r9, 0x30(%r9)
ROM:0000000000050E04 rldicl %r9, %r9, 48,16
ROM:0000000000050E08 cmpwi %r9, 0x29
ROM:0000000000050E0C bne loc_50E64
ROM:0000000000050E10 ld %r4, 0x10(%r28)
ROM:0000000000050E14 rldicr %r5, %r4, 24,39
ROM:0000000000050E18 rldicl %r5, %r5, 8,56
ROM:0000000000050E1C cmpwi %r5, 0xFF
ROM:0000000000050E20 beq loc_50E38
ROM:0000000000050E24 ori %r4, %r4, 3
ROM:0000000000050E28 std %r4, 0x10(%r28)
ROM:0000000000050E2C li %r3, 6
ROM:0000000000050E30 stw %r3, 0(%r30)
ROM:0000000000050E34 b loc_50E48
ROM:0000000000050E38 # ---------------------------------------------------------------------------
ROM:0000000000050E38 loc_50E38: # CODE XREF: some_additional_patching_on_the_fly+64j
ROM:0000000000050E38 ori %r4, %r4, 2
ROM:0000000000050E3C std %r4, 0x10(%r28)
ROM:0000000000050E40 li %r3, 0x2C
ROM:0000000000050E44 stw %r3, 0(%r30)
ROM:0000000000050E48 loc_50E48: # CODE XREF: some_additional_patching_on_the_fly+78j
ROM:0000000000050E48 lwz %r5, 4(%r28)
ROM:0000000000050E4C ld %r4, 8(%r28)
ROM:0000000000050E50 ld %r3, 0(%r27)
ROM:0000000000050E54 add %r9, %r3, %r5
ROM:0000000000050E58 std %r9, 0(%r27)
ROM:0000000000050E5C bl memcpy
ROM:0000000000050E60 b loc_50F24
ROM:0000000000050E64 # ---------------------------------------------------------------------------
ROM:0000000000050E64 loc_50E64: # CODE XREF: some_additional_patching_on_the_fly+50j
ROM:0000000000050E64 mr %r3, %r29
ROM:0000000000050E68 mr %r4, %r30
ROM:0000000000050E6C bl unk_4E81C
ROM:0000000000050E70 mr %r29, %r31
ROM:0000000000050E74 oris %r29, %r29, 5
ROM:0000000000050E78 ori %r29, %r29, 0xBD0 # 50bd0
ROM:0000000000050E7C lwz %r3, 0(%r29)
ROM:0000000000050E80 lwz %r5, 4(%r28)
ROM:0000000000050E84 add %r3, %r3, %r5
ROM:0000000000050E88 stw %r3, 0(%r29)
ROM:0000000000050E8C ld %r4, 0x10(%r28)
ROM:0000000000050E90 rldicr %r5, %r4, 24,39
ROM:0000000000050E94 rldicl %r5, %r5, 8,56
ROM:0000000000050E98 cmpwi %r5, 0xFF
ROM:0000000000050E9C bne loc_50F24
ROM:0000000000050EA0 ld %r3, 0(%r27) # here we probably are messing up with the htab entries
ROM:0000000000050EA0 # trying to patch the page on page change
ROM:0000000000050EA4 li %r4, 0
ROM:0000000000050EA8 li %r6, 0
ROM:0000000000050EAC loc_50EAC: # CODE XREF: some_additional_patching_on_the_fly+104j
ROM:0000000000050EAC add %r7, %r3, %r4
ROM:0000000000050EB0 lwz %r5, 0(%r7)
ROM:0000000000050EB4 xor %r6, %r6, %r5
ROM:0000000000050EB8 addi %r4, %r4, 4
ROM:0000000000050EBC cmpldi %r4, 0x400
ROM:0000000000050EC0 bne loc_50EAC # some kind of page hash
ROM:0000000000050EC4 lwz %r3, 0(%r29)
ROM:0000000000050EC8 rldicr %r6, %r6, 32,31
ROM:0000000000050ECC or %r6, %r6, %r3
ROM:0000000000050ED0 li %r3, 0
ROM:0000000000050ED4 stw %r3, 0(%r29)
ROM:0000000000050ED8 mr %r7, %r31
ROM:0000000000050EDC oris %r7, %r7, 5
ROM:0000000000050EE0 ori %r7, %r7, 0xF70 # 50f70
ROM:0000000000050EE4 loc_50EE4: # CODE XREF: some_additional_patching_on_the_fly+13Cj
ROM:0000000000050EE4 ld %r3, 0(%r7)
ROM:0000000000050EE8 cmpldi %r3, 0
ROM:0000000000050EEC beq loc_50F24
ROM:0000000000050EF0 addi %r7, %r7, 0x10 # we comapre the hash to the value in the table
ROM:0000000000050EF0 # and select a patch table accordingly
ROM:0000000000050EF4 cmpld %r3, %r6
ROM:0000000000050EF8 bne loc_50EE4
ROM:0000000000050EFC ld %r5, -8(%r7)
ROM:0000000000050F00 ld %r7, 0(%r27)
ROM:0000000000050F04 loc_50F04: # CODE XREF: some_additional_patching_on_the_fly+164j
ROM:0000000000050F04 lwz %r3, 0(%r5)
ROM:0000000000050F08 cmplwi %r3, 0
ROM:0000000000050F0C beq loc_50F24
ROM:0000000000050F10 lwz %r4, 4(%r5)
ROM:0000000000050F14 add %r3, %r3, %r7
ROM:0000000000050F18 stw %r4, 0(%r3)
ROM:0000000000050F1C addi %r5, %r5, 8 # we do the patching like we did it before
ROM:0000000000050F20 b loc_50F04
ROM:0000000000050F24 # ---------------------------------------------------------------------------
ROM:0000000000050F24 loc_50F24: # CODE XREF: some_additional_patching_on_the_fly+A4j
ROM:0000000000050F24 # some_additional_patching_on_the_fly+E0j ...
ROM:0000000000050F24 li %r3, 0
ROM:0000000000050F28 ld %r27, arg_78(%sp)
ROM:0000000000050F2C ld %r28, arg_80(%sp)
ROM:0000000000050F30 ld %r29, arg_88(%sp)
ROM:0000000000050F34 ld %r30, arg_90(%sp)
ROM:0000000000050F38 ld %r31, arg_98(%sp)
ROM:0000000000050F3C ld %r0, arg_1B0(%sp)
ROM:0000000000050F40 addi %sp, %sp, 0x1A0
ROM:0000000000050F44 mtlr %r0
ROM:0000000000050F48 blr
ROM:0000000000050F48 # End of function some_additional_patching_on_the_fly
ROM:0000000000050F4C # =============== S U B R O U T I N E =======================================
ROM:0000000000050F4C sub_50F4C:
ROM:0000000000050F4C .set var_B0, -0xB0
ROM:0000000000050F4C .set arg_98, 0x98
ROM:0000000000050F4C .set arg_A0, 0xA0
ROM:0000000000050F4C .set arg_A8, 0xA8
ROM:0000000000050F4C .set arg_C0, 0xC0
ROM:0000000000050F4C stdu %sp, var_B0(%sp)
ROM:0000000000050F50 mflr %r0
ROM:0000000000050F54 std %r30, arg_A0(%sp)
ROM:0000000000050F58 std %r31, arg_A8(%sp)
ROM:0000000000050F5C std %r29, arg_98(%sp)
ROM:0000000000050F60 std %r0, arg_C0(%sp)
ROM:0000000000050F64 li %r30, 0xFA0
ROM:0000000000050F68 li %r31, 0xC8
ROM:0000000000050F6C b 0xAB04
ROM:0000000000050F6C # End of function sub_50F4C
ROM:0000000000050F6C # ---------------------------------------------------------------------------
ROM:0000000000050F70 .quad 0xA0556F3D002CB8FD
ROM:0000000000050F78 .quad 0x8000000000050FB8 # 50FB8
ROM:0000000000050F80 .quad 0x8C0A948C000D99B1
ROM:0000000000050F88 .quad 0x8000000000050FE0 # 50FE0
ROM:0000000000050F90 .quad 0xA2BC1A5600052ADC
ROM:0000000000050F98 .quad 0x8000000000051004 # 51004
ROM:0000000000050FA0 .quad 0x6B70280200020017
ROM:0000000000050FA8 .quad 0x8000000000050FD4 # 50FD4
ROM:0000000000050FB0 .quad 0
ROM:0000000000050FB8 patch
ROM:0000000000050FC0 patch
ROM:0000000000050FC8 patch
ROM:0000000000050FD0 .byte 0
ROM:0000000000050FD1 .byte 0
ROM:0000000000050FD2 .byte 0
ROM:0000000000050FD3 .byte 0
ROM:0000000000050FD4 patch
ROM:0000000000050FDC .byte 0
ROM:0000000000050FDD .byte 0
ROM:0000000000050FDE .byte 0
ROM:0000000000050FDF .byte 0
ROM:0000000000050FE0 patch # here we patch vsh to use developer game_tool2.xml
ROM:0000000000050FE0 # instead of the retail xml
ROM:0000000000050FE8 patch
ROM:0000000000050FF0 patch
ROM:0000000000050FF8 patch
ROM:0000000000051000 .byte 0
ROM:0000000000051001 .byte 0
ROM:0000000000051002 .byte 0
ROM:0000000000051003 .byte 0
ROM:0000000000051004 patch # same here
ROM:000000000005100C patch
ROM:0000000000051014 patch
ROM:000000000005101C patch
ROM:0000000000051024 .byte 0
ROM:0000000000051025 .byte 0
ROM:0000000000051026 .byte 0
ROM:0000000000051027 .byte 0
ROM:0000000000051028 aDev_bdvd: .string "/dev_bdvd"
ROM:0000000000051028 .byte 0
ROM:0000000000051032 aMod: .string "mod"
ROM:0000000000051032 .byte 0

ROM:0000000000700000 USB_desc: .byte 9, 2, 0x12, 0, 1, 0, 0, 0x80, 0xFA, 9, 4, 0, 0, 0, 0xFE, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0xFA, 0xCE, 0xB0, 3, 0xAA, 0xBB, 0xCC, 0xDD
ROM:0000000000700020 # =============== S U B R O U T I N E =======================================
ROM:0000000000700020 exploit_entry:
ROM:0000000000700020 addi %r3, %r3, -0x1000 # copy code and jump to main
ROM:0000000000700024 li %r5, 0x1000
ROM:0000000000700028 li %r4, 1
ROM:000000000070002C rldicr %r4, %r4, 63,0
ROM:0000000000700030 oris %r4, %r4, 0x70
ROM:0000000000700034 loc_700034: # CODE XREF: exploit_entry+24j
ROM:0000000000700034 addi %r5, %r5, -8
ROM:0000000000700038 ldx %r6, %r3, %r5
ROM:000000000070003C stdx %r6, %r4, %r5
ROM:0000000000700040 cmpldi %r5, 0
ROM:0000000000700044 bne loc_700034
ROM:0000000000700048 addi %r4, %r4, 0x80 # exploit_main
ROM:000000000070004C mtctr %r4
ROM:0000000000700050 bctr
ROM:0000000000700050 # End of function exploit_entry
ROM:0000000000700050 # ---------------------------------------------------------------------------
ROM:0000000000700054 Shell code copy code:
ROM:0000000000700054 t_u64* src_addr_r3 = start section ROM Addr
ROM:0000000000700054 t_u64* dest_addr_r4 = 0x8000 0000 0070 0000
ROM:0000000000700054 t_u64 size_bytes_r5 = 0x1000 / 4096
ROM:0000000000700054 t_u64 temp_value;
ROM:0000000000700054 do
ROM:0000000000700054 {
ROM:0000000000700054 size_bytes_r5 -= 8;
ROM:0000000000700054 temp_value = *(t_u64*)(src_addr_r3+size_bytes_r5);
ROM:0000000000700054 *(t_u64*)(dest_addr_r4+size_bytes_r5) = temp_value;
ROM:0000000000700054 }while(size_bytes_r5 != 0)
ROM:0000000000700054 dest_addr_r4 = dest_addr_r4 + 0x80;
ROM:0000000000700054 jump dest_addr_r4;
ROM:0000000000700054 .byte 0
ROM:000000000070007F .byte 0
ROM:0000000000700080 # =============== S U B R O U T I N E =======================================
ROM:0000000000700080 exploit_main:
ROM:0000000000700080 .set var_B0, -0xB0
ROM:0000000000700080 .set var_A0, -0xA0
ROM:0000000000700080 .set arg_78, 0x78
ROM:0000000000700080 .set arg_80, 0x80
ROM:0000000000700080 .set arg_88, 0x88
ROM:0000000000700080 .set arg_90, 0x90
ROM:0000000000700080 .set arg_98, 0x98
ROM:0000000000700080 .set arg_A0, 0xA0
ROM:0000000000700080 .set arg_A8, 0xA8
ROM:0000000000700080 .set arg_B0, 0xB0
ROM:0000000000700080 .set arg_C0, 0xC0
ROM:0000000000700080 mflr %r0
ROM:0000000000700084 stdu %sp, var_A0(%sp)
ROM:0000000000700088 std %r27, arg_78(%sp)
ROM:000000000070008C std %r28, arg_80(%sp)
ROM:0000000000700090 std %r29, arg_88(%sp)
ROM:0000000000700094 std %r30, arg_90(%sp)
ROM:0000000000700098 std %r31, arg_98(%sp)
ROM:000000000070009C std %r0, arg_B0(%sp)
ROM:00000000007000A0 li %r31, 1
ROM:00000000007000A4 rldicr %r31, %r31, 63,0
ROM:00000000007000A8 mr %r3, %r31
ROM:00000000007000AC oris %r3, %r3, 5
ROM:00000000007000B0 ori %r3, %r3, 0xB3C # 50b3c
ROM:00000000007000B4 mr %r4, %r31
ROM:00000000007000B8 oris %r4, %r4, 0x70
ROM:00000000007000BC ori %r4, %r4, 0x1AC # 7001ac
ROM:00000000007000C0 li %r5, 0x4FA
ROM:00000000007000C4 bl memcpy # we copy a part of the shellcode
ROM:00000000007000C8 mr %r3, %r31
ROM:00000000007000CC oris %r3, %r3, 5
ROM:00000000007000D0 ori %r3, %r3, 0xB3C
ROM:00000000007000D4 addi %r3, %r3, 0x20 # 50b5c
ROM:00000000007000D8 bl add_kmod_ # here we probably add some kernel module
ROM:00000000007000D8 # called "mod" for some usb? device
ROM:00000000007000D8 #
ROM:00000000007000D8 # it has 3 functions, see 50b5c +8,+10,+18
ROM:00000000007000DC mr %r3, %r31
ROM:00000000007000E0 oris %r3, %r3, 5
ROM:00000000007000E4 ori %r3, %r3, 0xB3C # 50b3c
ROM:00000000007000E8 mr %r4, %r31
ROM:00000000007000EC oris %r4, %r4, 0x2E
ROM:00000000007000F0 ori %r4, %r4, -0x4ED8 # 2eb128, Address of syscall table
ROM:00000000007000F4 addi %r3, %r3, 0x10 # 50b4c
ROM:00000000007000F8 std %r3, 0x120(%r4) # 2eb248 - this is in the syscall table
ROM:00000000007000F8 # we add a system call so that Backup Manager can
ROM:00000000007000F8 # activate the virtual bluray drive.
ROM:00000000007000FC mr %r5, %r31
ROM:0000000000700100 oris %r5, %r5, 0x70
ROM:0000000000700104 ori %r5, %r5, 0x150 # 700150
ROM:0000000000700108 loc_700108: # CODE XREF: exploit_main+A4j
ROM:0000000000700108 lwz %r3, 0(%r5)
ROM:000000000070010C cmplwi %r3, 0
ROM:0000000000700110 beq loc_700128 # do patching by table
ROM:0000000000700114 lwz %r4, 4(%r5)
ROM:0000000000700118 add %r3, %r3, %r31
ROM:000000000070011C stw %r4, 0(%r3)
ROM:0000000000700120 addi %r5, %r5, 8
ROM:0000000000700124 b loc_700108
ROM:0000000000700128 # ---------------------------------------------------------------------------
ROM:0000000000700128 Patch table code:
ROM:0000000000700128 t_u64 base_addr_r31 = 0x8000 0000 0000 0000
ROM:0000000000700128 t_u32* src_addr_r5 = 0x80000000 00070150
ROM:0000000000700128 t_u32 offset_dest_addr_r3;
ROM:0000000000700128 t_u32* dest_addr_r3;
ROM:0000000000700128 t_u32 tmp_value;
ROM:0000000000700128 do
ROM:0000000000700128 {
ROM:0000000000700128 offset_dest_addr_r3 = src_addr_r5[0];
ROM:0000000000700128 if(offset_dest_addr_r3 == 0) /* End of Patch Tag */
ROM:0000000000700128 {
ROM:0000000000700128 break;
ROM:0000000000700128 }
ROM:0000000000700128 tmp_value = src_addr_r5[1];
ROM:0000000000700128 dest_addr_r3 = (t_u32*)((t_u64)offset_dest_addr_r3+base_addr_r31);
ROM:0000000000700128 *dest_addr_r3 = tmp_value;
ROM:0000000000700128 src_addr_r5 = src_addr_r5+8;
ROM:0000000000700128 }while(1);
ROM:0000000000700128 loc_700128: # CODE XREF: exploit_main+90j
ROM:0000000000700128 b loc_7006B0
ROM:000000000070012C # ---------------------------------------------------------------------------
ROM:000000000070012C stdu %sp, var_B0(%sp)
ROM:0000000000700130 mflr %r0
ROM:0000000000700134 std %r30, arg_A0(%sp)
ROM:0000000000700138 std %r31, arg_A8(%sp)
ROM:000000000070013C std %r29, arg_98(%sp)
ROM:0000000000700140 std %r0, arg_C0(%sp)
ROM:0000000000700144 li %r30, 2000
ROM:0000000000700148 li %r31, 200
ROM:000000000070014C b 0xAB04
ROM:000000000070014C # ---------------------------------------------------------------------------
ROM:0000000000700150 # struct struct_patch_table { uint32_t addr_offset, uint32_t patch_value; }
ROM:0000000000700150 # Final addr patch => *(t_u32*)(0x80000000 00000000 + addr_offset) = patch_value
ROM:0000000000700150 patch_table_data: struct_patch_table # ld r4,3848(r2) } Patches return from
ROM:0000000000700158 struct_patch_table # ld r3,32(r28) } Hypercall 99 so that
ROM:0000000000700160 struct_patch_table # std r3,0(r4) } we can launch unsigned apps.
ROM:0000000000700168 struct_patch_table # bl $+0x1a9c
ROM:0000000000700170 struct_patch_table # b $+0xffda5b80
ROM:0000000000700178 struct_patch_table # li r4,0
ROM:0000000000700180 struct_patch_table # stw r4,0(r3)
ROM:0000000000700188 struct_patch_table # blr
ROM:0000000000700190 struct_patch_table # .long 0x1000000
ROM:0000000000700198 struct_patch_table # li r3,1
ROM:00000000007001A0 struct_patch_table # Last Tag; blr
ROM:00000000007001A8 .long 0
ROM:00000000007001AC RELOCATED_CODE .byte 0x38, 0x60, 0, 1, 0x4E, 0x80, 0, 0x20, 0x48, 0, 2, 0x78, 0x48, 0, 1, 0xEC, 0x80, 0, 0, 0, 0, 5, 0xC, 0xA8, 0x80, 0, 0, 0, 0, 0x33,
ROM:00000000007001AC .byte 0x64, 0
ROM:00000000007006A6 .byte 0
ROM:00000000007006A7 .byte 0
ROM:00000000007006A8 .byte 0
ROM:00000000007006A9 .byte 0
ROM:00000000007006AA .byte 0
ROM:00000000007006AB .byte 0
ROM:00000000007006AC .byte 0
ROM:00000000007006AD .byte 0
ROM:00000000007006AE .byte 0
ROM:00000000007006AF .byte 0
ROM:00000000007006B0 # ---------------------------------------------------------------------------
ROM:00000000007006B0 loc_7006B0: # CODE XREF: exploit_main:loc_700128j
ROM:00000000007006B0 ld %r27, arg_78(%sp)
ROM:00000000007006B4 ld %r28, arg_80(%sp)
ROM:00000000007006B8 ld %r29, arg_88(%sp)
ROM:00000000007006BC ld %r30, arg_90(%sp)
ROM:00000000007006C0 ld %r31, arg_98(%sp)
ROM:00000000007006C4 ld %r0, arg_B0(%sp)
ROM:00000000007006C8 addi %sp, %sp, 0xA0
ROM:00000000007006CC mtlr %r0
ROM:00000000007006D0 li %r3, 1
ROM:00000000007006D4 rldicr %r3, %r3, 63,0
ROM:00000000007006D8 oris %r3, %r3, 0x70 # 700000
ROM:00000000007006DC li %r4, 0
ROM:00000000007006E0 li %r5, 0x6E8
ROM:00000000007006E4 b memset # we exit by zeroing the payload in mem
ROM:00000000007006E4 # End of function exploit_main

PSJailBreak PS3 Exploit Payload Reverse Engineering Detailed

Follow us on Twitter, Facebook and drop by the PS3 Hacks and PS3 CFW forums for the latest PlayStation 3 scene and PS4 Hacks & JailBreak updates with PlayStation 4 homebrew.

#31 - sapperlott - September 25, 2010 // 10:53 am
sapperlott's Avatar
My guess is that 0x8000000000000000 is only a mapping so that applications can make calls into kernel space (since they see 0x00000000 - 0xffffffff as their own private address space).

If you don't rebase it to 0x8000000000000000 all the interrupt vectors are where they're supposed to be (0x100, 0x200, ...). Take a look at the system reset interrupt vector at 0x100 - that should give away the entry point.

#30 - emsi - September 25, 2010 // 12:05 am
emsi's Avatar
Quote Originally Posted by sapperlott View Post
Don't forget to specify the endianness - you might get unexpected results otherwise.

The ppu-lv2-objdump supports Cell:PPU as architecture. So this would be the way to disassemble PPE memdumps with ppu-lv2-objdump:
ppu-lv2-objdump -b binary -m Cell:PPU -EB -D >

I got it. Thank you. Do you know what is the entry point for the gameOS?

BTW: adding --adjust-vma=0x8000000000000000 might be helpful.

#29 - Red 13 - September 24, 2010 // 4:11 am
Red 13's Avatar

I have a lot of question, and i hope some one here can help me answere them

The last week i have been playing around with xml files and xRegistry file. I think that i partly understand the xml files, and what they do. They are the connection between the GameOS and the FW files.

I have been able to add some "new shortcuts", move them around between the different category's and change there function.

But then there are the category_sysconf.xml file... it does nothing, you can delete it, and nothing happens. Why? Is it loaded during the booting, because it is alredy loaded when you enter the menu screen, and the other category's are not. Or are the file not in use any more, "leftovers" from an older FW? But then it shoulda contained the OtherOS launch command...

And the commands from category_sysconf.xml, wont run i any other category xml file. The icons wont showe up, you only see the loading circle on all the "shortcuts". And it is not possible to start them, but it is possible to "browse" two of them, total 18. There are 13 and 5 in twoes thats you can "browse". edyviewer and tool_debug_settings?

If it is loaded during booting, what needs to be done to enable the debug setting, xRegistry don't seme to do any thing... Or is this because the Settings menu is LV1.

How is the TEST fw different from the RETAIL, does it containe more files? Or do they containe the same files, but configurated different?

If they are completely different fw's, why does the Retail fw containe the referanses to the debug setting, in the category_sysconf.xml and in the xRegistry?

Does the retail containe a "light" version of the debug settings? Can even sony use the debug settings on a retail, has anybody heard aboute this being don?

Have anyone ever been able to extract the dev_flash and the xRegistry from a TEST unit? If so, does the xRegistry file contain the same options? And i haven't seen the otherOS any where in this files

If the "Settings" category needs LV1 to be changed, then no "sony OtherOS" in fw3.41. But if it is only loaded during the boot sequence, maybe PSGroove can be modyfied to do the same jobb as the "usb firm loader"? And we will be able to add and modify the Settings category.

#28 - sapperlott - September 23, 2010 // 5:48 pm
sapperlott's Avatar
Don't forget to specify the endianness - you might get unexpected results otherwise.

The ppu-lv2-objdump supports Cell:PPU as architecture. So this would be the way to disassemble PPE memdumps with ppu-lv2-objdump:
ppu-lv2-objdump -b binary -m Cell:PPU -EB -D >

#27 - emsi - September 23, 2010 // 10:00 am
emsi's Avatar
Thanks guys I think that I should have read man objdump before asking dumb questions

#26 - sapperlott - September 22, 2010 // 7:18 pm
sapperlott's Avatar
You can also disassemble raw binaries directly with objdump: ppu-objdump -b binary -m powerpc:common64 -d

You can see the supported object formats and architectures like this: ppu-objdump -i

#25 - tragedy - September 22, 2010 // 6:37 pm
tragedy's Avatar
Quote Originally Posted by emsi View Post
I have no time to verify it but will the ppu-lv2-objdump be of any use if I want to deal with GameOS memory dump? Doesn't it work with ELF files only?
You can use ppu-objcopy to convert from binary to object file. ppu-objdump -D will disassemble all sections, even data sections.

#24 - emsi - September 22, 2010 // 10:21 am
emsi's Avatar
Quote Originally Posted by sapperlott View Post
It seems that more than just the menu was removed so that seems unlikely.

As for the debugger/disassembler: they're part of the SDK. But I guess the debugger (gdb) won't work without a PS3 TEST since it has to do remote debugging. You can disassemble elf files with ppu-lv2-objdump and spu-lv2-objdump.

AFAIK the first version of patch removed only a XMB menu so it was possible to enable it. Perhaps you're right. All we need to do is backport the exploit to earlier version of firmware and analyze the dump.

Thanks for the objdump hint. I figured it out that debugging is only possible remotely but I'm used to gdb for disassembling as well (mainly using x/10i or something similiar).

And I got another idea. If someone has a running console with OtherOS capability and thus working Linux we might try to to debug (an run portions of its code to analyze) the GameOS under it.

Lot of hacking would be needed to tweak GameOS to run in user space (something like User Mode Linux) but it should be easier to analyze a function if can actually run it in virtualized environment. It's just an idea. Unfortunately I've lot access to Linux on my PS3 while upgraded to 3.41

I have no time to verify it but will the ppu-lv2-objdump be of any use if I want to deal with GameOS memory dump? Doesn't it work with ELF files only?

#23 - sapperlott - September 20, 2010 // 5:01 pm
sapperlott's Avatar
Quote Originally Posted by RexVF5 View Post
TEST and RETAIL units are the same hardware-wise. So it is just a matter of running TEST firmware on RETAIL unit - I think that is nearing.
Yeah - as soon as TEST FW will run on retail HW without any limitations, this issue will likely go away.
Quote Originally Posted by RexVF5 View Post
Also - are you talking about stock gdb available with open-source PS3 toolchain or is gdb part of leaked SDK? Open-source version does not rely on anything from PS3 TEST FW - once the binaries produced by toolchain are happily running on RETAIL PS3s there will be way of running them under gdb (similarly as psp-gdb runs on retail PSPs).
I guess it will be quite a challenge to get the open source SDK to a point where debugging with GDB will be possible. Only remote debugging is possible which means that the host part of GDB has to be ported to GameOS Lv-2 which might be tricky to pull off.

The GDB binaries from the leaked SDK (ppu-lv2-gdb, spu-lv2-gdb) seem to rely on a separate communication manager for communication with the console. The counterpart of this communication manager is most likely only contained in debug FW.

#22 - RexVF5 - September 19, 2010 // 8:20 am
RexVF5's Avatar
Quote Originally Posted by sapperlott View Post

As for the debugger/disassembler: they're part of the SDK. But I guess the debugger (gdb) won't work without a PS3 TEST since it has to do remote debugging.

TEST and RETAIL units are the same hardware-wise. So it is just a matter of running TEST firmware on RETAIL unit - I think that is nearing.

Also - are you talking about stock gdb available with open-source PS3 toolchain or is gdb part of leaked SDK? Open-source version does not rely on anything from PS3 TEST FW - once the binaries produced by toolchain are happily running on RETAIL PS3s there will be way of running them under gdb (similarly as psp-gdb runs on retail PSPs).