mirror of
https://github.com/EchoStretch/kstuff-lite.git
synced 2026-10-19 02:09:50 -05:00
Enable plaintext PPR interception through firmware 13.60
This commit is contained in:
1 parent
47e6c23311
commit
a7ca1c3ad7
9 files changed
+114
-62
No files matched your search
@@ -76,18 +76,18 @@ DEF(cr0_write_ret, -0x581453)
|
||||
DEF(store_rax_rdi, -0x1EE5B2)
|
||||
|
||||
// PPR/fPKG offsets
|
||||
DEF(ppr_pfs_get_xts_index, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x0)
|
||||
DEF(ppr_pfs_get_xts_return, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x0)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x0)
|
||||
DEF(ppr_pfs_clear_key_missing, -0x0)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0x0)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0x0)
|
||||
DEF(ppr_pfs_get_xts_index, -0x127090)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x126f30)
|
||||
DEF(ppr_pfs_get_xts_return, -0x93a5f7)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x93a5ac)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x945590)
|
||||
DEF(ppr_pfs_clear_key_missing, -0xa279ff)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0xa28e9d)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0xa28b42)
|
||||
|
||||
// non data-relative offsets
|
||||
DEF(p_sysent, 0xA08)
|
||||
#include "offset_list.txt"
|
||||
END_FW()
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -76,18 +76,18 @@ DEF(cr0_write_ret, -0x581143)
|
||||
DEF(store_rax_rdi, -0x1EE302)
|
||||
|
||||
// PPR/fPKG offsets
|
||||
DEF(ppr_pfs_get_xts_index, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x0)
|
||||
DEF(ppr_pfs_get_xts_return, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x0)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x0)
|
||||
DEF(ppr_pfs_clear_key_missing, -0x0)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0x0)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0x0)
|
||||
DEF(ppr_pfs_get_xts_index, -0x126e90)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x126d30)
|
||||
DEF(ppr_pfs_get_xts_return, -0x93a5f7)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x93a5ac)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x945590)
|
||||
DEF(ppr_pfs_clear_key_missing, -0xa279ff)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0xa28e9d)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0xa28b42)
|
||||
|
||||
// non data-relative offsets
|
||||
DEF(p_sysent, 0xA08)
|
||||
#include "offset_list.txt"
|
||||
END_FW()
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -76,18 +76,18 @@ DEF(cr0_write_ret, -0x580E33)
|
||||
DEF(store_rax_rdi, -0x1EDFF2)
|
||||
|
||||
// PPR/fPKG offsets
|
||||
DEF(ppr_pfs_get_xts_index, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x0)
|
||||
DEF(ppr_pfs_get_xts_return, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x0)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x0)
|
||||
DEF(ppr_pfs_clear_key_missing, -0x0)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0x0)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0x0)
|
||||
DEF(ppr_pfs_get_xts_index, -0x126b80)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x126a20)
|
||||
DEF(ppr_pfs_get_xts_return, -0x93a597)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x93a54c)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x945530)
|
||||
DEF(ppr_pfs_clear_key_missing, -0xa2799f)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0xa28e3d)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0xa28ae2)
|
||||
|
||||
// non data-relative offsets
|
||||
DEF(p_sysent, 0xA08)
|
||||
#include "offset_list.txt"
|
||||
END_FW()
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -76,18 +76,18 @@ DEF(cr0_write_ret, -0x580E33)
|
||||
DEF(store_rax_rdi, -0x1EDFF2)
|
||||
|
||||
// PPR/fPKG offsets
|
||||
DEF(ppr_pfs_get_xts_index, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x0)
|
||||
DEF(ppr_pfs_get_xts_return, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x0)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x0)
|
||||
DEF(ppr_pfs_clear_key_missing, -0x0)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0x0)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0x0)
|
||||
DEF(ppr_pfs_get_xts_index, -0x126b80)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x126a20)
|
||||
DEF(ppr_pfs_get_xts_return, -0x93a597)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x93a54c)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x945530)
|
||||
DEF(ppr_pfs_clear_key_missing, -0xa2799f)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0xa28e3d)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0xa28ae2)
|
||||
|
||||
// non data-relative offsets
|
||||
DEF(p_sysent, 0xA08)
|
||||
#include "offset_list.txt"
|
||||
END_FW()
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -76,14 +76,14 @@ DEF(cr0_write_ret, -0x58E983)
|
||||
DEF(store_rax_rdi, -0x1F44A2)
|
||||
|
||||
// PPR/fPKG offsets
|
||||
DEF(ppr_pfs_get_xts_index, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x0)
|
||||
DEF(ppr_pfs_get_xts_return, -0x0)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x0)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x0)
|
||||
DEF(ppr_pfs_clear_key_missing, -0x0)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0x0)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0x0)
|
||||
DEF(ppr_pfs_get_xts_index, -0x12c6e0)
|
||||
DEF(ppr_pfs_get_cmac_index, -0x12c580)
|
||||
DEF(ppr_pfs_get_xts_return, -0x949bf7)
|
||||
DEF(ppr_pfs_get_cmac_return, -0x949bac)
|
||||
DEF(ppr_pfs_cleanup_keys, -0x954b90)
|
||||
DEF(ppr_pfs_clear_key_missing, -0xa3795f)
|
||||
DEF(sceSblServiceMailbox_lr_verifyImage, -0xa38dfd)
|
||||
DEF(ppr_pfs_verify_image_no_key_success, -0xa38aa2)
|
||||
|
||||
// non data-relative offsets
|
||||
DEF(p_sysent, 0xA08)
|
||||
|
||||
+8
-10
@@ -951,23 +951,21 @@ static int install_shellcore_ppr_hook(
|
||||
size_t game_umount_entry = 0;
|
||||
size_t ppr_umount_entry = 0;
|
||||
|
||||
int game_only = (r0gdb_get_fw_version() >> 16) > 0x1140;
|
||||
size_t api_count = game_only ? 2 : 4;
|
||||
const size_t api_count = sizeof(api_got) / sizeof(api_got[0]);
|
||||
if(!blob_size || blob_size > sizeof(prepared_blob))
|
||||
return shellcore_ppr_fail("fpkg scope: invalid wrapper blob size");
|
||||
|
||||
uint32_t required_mask = SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_MOUNT_GAME)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_UMOUNT_GAME);
|
||||
if(!game_only)
|
||||
required_mask |= SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_CLOSE)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_OPEN)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_PREAD)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_MOUNT_PPR)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_UMOUNT_PPR);
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_UMOUNT_GAME)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_CLOSE)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_OPEN)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_PREAD)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_MOUNT_PPR)
|
||||
| SHELLCORE_IMPORT_BIT(SHELLCORE_IMPORT_UMOUNT_PPR);
|
||||
if(kstuff_shellcore_imports(pid, shellcore_base, required_mask,
|
||||
import_got))
|
||||
return shellcore_ppr_fail("fpkg scope: ShellCore imports unavailable");
|
||||
for(size_t i = 0; i < (game_only ? 0 : 3); i++)
|
||||
for(size_t i = 0; i < 3; i++)
|
||||
{
|
||||
uint64_t lazy_plt;
|
||||
if(read_shellcore_import(pid, shellcore_base, text_end, import_got[i],
|
||||
|
||||
+28
-6
@@ -66,6 +66,7 @@ enum ppr_verify_success_abi
|
||||
PPR_VERIFY_SUCCESS_R13_STACK_158,
|
||||
PPR_VERIFY_SUCCESS_R13_STACK_150,
|
||||
PPR_VERIFY_SUCCESS_PACKED_STACK_158,
|
||||
PPR_VERIFY_SUCCESS_PACKED_STACK_150,
|
||||
};
|
||||
|
||||
struct ppr_profile
|
||||
@@ -151,6 +152,16 @@ static const struct ppr_profile* get_ppr_profile(void)
|
||||
R13, R14, R15, RBX, 0x0a,
|
||||
PPR_VERIFY_SUCCESS_PACKED_STACK_158,
|
||||
};
|
||||
static const struct ppr_profile fw12 = {
|
||||
0x119, 0x149,
|
||||
R13, R14, R15, RBX, 0x0a,
|
||||
PPR_VERIFY_SUCCESS_PACKED_STACK_150,
|
||||
};
|
||||
static const struct ppr_profile fw13 = {
|
||||
0x12b, 0x15b,
|
||||
R13, R14, R15, RBX, 0x0a,
|
||||
PPR_VERIFY_SUCCESS_PACKED_STACK_150,
|
||||
};
|
||||
|
||||
switch(FWVER)
|
||||
{
|
||||
@@ -178,9 +189,14 @@ static const struct ppr_profile* get_ppr_profile(void)
|
||||
return &fw9;
|
||||
case 0x1000: case 0x1001: case 0x1020: case 0x1040: case 0x1060:
|
||||
return &fw10;
|
||||
case 0x1100: case 0x1120: case 0x1140:
|
||||
case 0x1100: case 0x1120: case 0x1140: case 0x1160:
|
||||
return &fw11;
|
||||
/* 11.60+ offsets are data-only until runtime interception is validated. */
|
||||
case 0x1200: case 0x1202: case 0x1220: case 0x1240:
|
||||
case 0x1260: case 0x1270:
|
||||
return &fw12;
|
||||
case 0x1300: case 0x1320: case 0x1340: case 0x1342:
|
||||
case 0x1360:
|
||||
return &fw13;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@@ -1636,11 +1652,15 @@ int try_handle_fpkg_mailbox(uint64_t* regs, uint64_t lr)
|
||||
== PPR_VERIFY_SUCCESS_R13_STACK_150)
|
||||
success_stack_offset = -0x150;
|
||||
else if(ppr_abi->verify_success_abi
|
||||
== PPR_VERIFY_SUCCESS_PACKED_STACK_158)
|
||||
== PPR_VERIFY_SUCCESS_PACKED_STACK_158
|
||||
|| ppr_abi->verify_success_abi
|
||||
== PPR_VERIFY_SUCCESS_PACKED_STACK_150)
|
||||
{
|
||||
success_stack_offset = -0x158;
|
||||
success_stack_offset = ppr_abi->verify_success_abi
|
||||
== PPR_VERIFY_SUCCESS_PACKED_STACK_158
|
||||
? -0x158 : -0x150;
|
||||
/*
|
||||
* The 10.x/11.x no-key continuation loads this qword and
|
||||
* The 10.x-13.x no-key continuation loads this qword and
|
||||
* publishes its upper dword as ekey (XTS) and its lower
|
||||
* dword as skey (CMAC). Keep that order distinct from the
|
||||
* in-memory key-index pair used later by ppfs cleanup.
|
||||
@@ -1676,7 +1696,9 @@ int try_handle_fpkg_mailbox(uint64_t* regs, uint64_t lr)
|
||||
regs[R15] = PPR_PFS_PLAINTEXT_CMAC_HANDLE;
|
||||
}
|
||||
else if(ppr_abi->verify_success_abi
|
||||
!= PPR_VERIFY_SUCCESS_PACKED_STACK_158)
|
||||
!= PPR_VERIFY_SUCCESS_PACKED_STACK_158
|
||||
&& ppr_abi->verify_success_abi
|
||||
!= PPR_VERIFY_SUCCESS_PACKED_STACK_150)
|
||||
{
|
||||
regs[R13] = PPR_PFS_PLAINTEXT_CMAC_HANDLE;
|
||||
}
|
||||
|
||||
@@ -209,7 +209,8 @@ def cleanup_body_delta(segments: list[Segment], address: int) -> int:
|
||||
|
||||
|
||||
def locate_cleanup(reference_segments: list[Segment], reference_address: int,
|
||||
target_segments: list[Segment]) \
|
||||
target_segments: list[Segment], cleanup_cmac_delta: int,
|
||||
cleanup_xts_delta: int) \
|
||||
-> tuple[LocatedSite | None, list[int]]:
|
||||
site, candidates = locate_site(
|
||||
reference_segments, reference_address, target_segments
|
||||
@@ -217,6 +218,30 @@ def locate_cleanup(reference_segments: list[Segment], reference_address: int,
|
||||
if site is not None:
|
||||
return site, candidates
|
||||
|
||||
# 13.xx adds a branch near the beginning of cleanup_a53io_pkg_keys,
|
||||
# invalidating the older entry signature. Its two key release calls retain
|
||||
# a unique local instruction shape. Verify both calls and the entry thunk.
|
||||
pattern = bytes.fromhex("41 8b 7e 3c e8")
|
||||
matches = []
|
||||
for first_load in find_exact(target_segments, pattern):
|
||||
entry = (first_load + 4 - cleanup_cmac_delta) & MASK64
|
||||
second_load = (entry + cleanup_xts_delta - 4) & MASK64
|
||||
if (bytes_at(target_segments, entry, 4)
|
||||
!= bytes.fromhex("55 48 89 e5")
|
||||
or bytes_at(target_segments, entry + 0x10, 4)
|
||||
!= bytes.fromhex("55 48 89 e5")
|
||||
or bytes_at(target_segments, second_load, 5)
|
||||
!= bytes.fromhex("41 8b 7e 38 e8")
|
||||
or rel32_call_target(target_segments, first_load + 4) is None
|
||||
or rel32_call_target(target_segments,
|
||||
entry + cleanup_xts_delta) is None):
|
||||
continue
|
||||
matches.append(entry)
|
||||
if len(matches) == 1:
|
||||
return LocatedSite(matches[0], "paired-key-release-calls"), matches
|
||||
if matches:
|
||||
return None, matches
|
||||
|
||||
# Newer kernels expose cleanup_a53io_pkg_keys through a short alignment
|
||||
# thunk. Its rel32 jump changes easily, while the actual body is highly
|
||||
# distinctive. Match the body and translate back to the public entry.
|
||||
@@ -422,8 +447,13 @@ def scan(target: Path, reference: Path, header_dir: Path,
|
||||
|
||||
name = "ppr_pfs_cleanup_keys"
|
||||
reference_address = (reference_anchor + reference_known[name]) & MASK64
|
||||
target_profile = PROFILES.get(ppr_profile_key(major, minor))
|
||||
if target_profile is None:
|
||||
raise ValueError(f"no PPR ABI profile for {major}.{minor:02d}")
|
||||
site, candidates = locate_cleanup(
|
||||
reference_segments, reference_address, target_segments
|
||||
reference_segments, reference_address, target_segments,
|
||||
target_profile.cleanup_cmac_delta,
|
||||
target_profile.cleanup_xts_delta,
|
||||
)
|
||||
if site is None:
|
||||
ambiguous[name] = [f"{candidate:#x}" for candidate in candidates]
|
||||
|
||||
@@ -139,6 +139,8 @@ PROFILES = {
|
||||
VERIFY_SUCCESS_FW10_11),
|
||||
12: Profile(0x119, 0x149, bytes.fromhex("bb fe ff ff ff"),
|
||||
VERIFY_SUCCESS_FW12),
|
||||
13: Profile(0x12B, 0x15B, bytes.fromhex("bb fe ff ff ff"),
|
||||
VERIFY_SUCCESS_FW12),
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user