8 #include <psp2kern/types.h> 9 #include <psp2kern/io/fcntl.h> 10 #include <psp2kern/kernel/modulemgr.h> 11 #include <psp2kern/kernel/sysmem.h> 13 #include <taihen/parser.h> 18 #include "taihen_internal.h" 21 #define MAX_SEGMENTS 8 24 #define OFFSET_PATCH_ARG 168 30 typedef uint16_t Elf32_Half;
31 typedef uint32_t Elf32_Word;
32 typedef int32_t Elf32_Sword;
33 typedef void * Elf32_Addr;
34 typedef size_t Elf32_Off;
39 unsigned char e_ident[EI_NIDENT];
48 Elf32_Half e_phentsize;
50 Elf32_Half e_shentsize;
52 Elf32_Half e_shstrndx;
60 uint32_t metadata_offset;
62 uint64_t elf_filesize;
63 uint64_t self_filesize;
66 uint64_t appinfo_offset;
70 uint64_t section_info_offset;
71 uint64_t sceversion_offset;
72 uint64_t controlinfo_offset;
73 uint64_t controlinfo_size;
121 static SceUID g_hooks[11];
124 static SceUID g_config_blk;
127 char *g_config = NULL;
130 static int g_is_homebrew;
133 static self_section_info_t g_seg_info[MAX_SEGMENTS];
145 static int parse_headers_patched(
int ctx,
const void *headers,
size_t len,
void *args) {
151 memset(&g_seg_info, 0,
sizeof(g_seg_info));
152 if (len >=
sizeof(self_header_t) && len >=
sizeof(Elf32_Ehdr)) {
153 self = (self_header_t *)headers;
154 if (self->elf_offset <= len -
sizeof(Elf32_Ehdr)) {
155 elf = (Elf32_Ehdr *)(headers + self->elf_offset);
156 num_segs = elf->e_phnum;
157 if (num_segs <= MAX_SEGMENTS &&
158 self->section_info_offset < self->section_info_offset + num_segs *
sizeof(self_section_info_t) &&
159 self->section_info_offset + num_segs *
sizeof(self_section_info_t) < len
161 memcpy(&g_seg_info, headers + self->section_info_offset, num_segs *
sizeof(self_section_info_t));
165 ret =
TAI_CONTINUE(
int, g_parse_headers_hook, ctx, headers, len, args);
167 if (ret == 0x800f0624 || ret == 0x800f0616 || ret == 0x800f0024 || ((
unsigned)ret >= 0x800f0b30 && (
unsigned)ret <= 0x800f0b3f)) {
170 if (*(uint32_t *)(args + OFFSET_PATCH_ARG) == 0) {
171 *(uint32_t *)(args + OFFSET_PATCH_ARG) = 0x20;
177 LOG(
"parse ret %x, decrypt is homebrew? %d", ret, g_is_homebrew);
190 static int setup_buffer_patched(
int ctx,
int segidx) {
193 ret =
TAI_CONTINUE(
int, g_setup_buffer_hook, ctx, segidx);
194 if (ctx == 1 && g_is_homebrew && segidx < MAX_SEGMENTS) {
195 ret = g_seg_info[segidx].compressed;
196 LOG(
"segidx %d, compression type: %d", segidx, ret);
210 static int decrypt_buffer_patched(
int ctx,
void *buffer,
size_t len) {
213 ret =
TAI_CONTINUE(
int, g_decrypt_buffer_hook, ctx, buffer, len);
214 if (ctx == 1 && g_is_homebrew) {
215 LOG(
"patching decrypt buffer bypass");
233 static int rif_check_vita_patched(
int a1,
int a2,
int a3,
int a4,
int a5,
int a6) {
235 ret =
TAI_CONTINUE(
int, g_rif_check_vita_hook, a1, a2, a3, a4, a5, a6);
236 if (ret == 0x80870003) {
237 LOG(
"patched rif check return: %x => 0", ret);
254 static int rif_check_psp_patched(
int a1,
int a2,
int a3,
int a4,
int a5) {
256 ret =
TAI_CONTINUE(
int, g_rif_check_psp_hook, a1, a2, a3, a4, a5);
257 if (ret == 0x80870003) {
258 LOG(
"patched rif check return: %x => 0", ret);
282 static int rif_get_info_patched(
int a1,
int a2,
int a3,
int a4,
int a5,
int a6,
int a7,
int a8,
int a9,
int a10,
int a11,
int a12) {
284 ret =
TAI_CONTINUE(
int, g_rif_get_info_hook, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
285 if (ret == 0x80870003) {
286 LOG(
"patched rif check return: %x => 0", ret);
297 static int package_check_patched(
void) {
300 LOG(
"patching fpkg enabled: %x => 1", ret);
309 static int package_check_2_patched(
void) {
312 LOG(
"patching fpkg enabled: %x => 1", ret);
325 static int load_user_libs_patched(SceUID pid,
void *args,
int flags) {
331 ret =
TAI_CONTINUE(
int, g_load_user_libs_hook, pid, args, flags);
333 sceKernelGetProcessTitleIdForKernel(pid, titleid, 32);
334 LOG(
"title started: %s, pid: %x", titleid, pid);
338 param.
flags = 0x8000;
341 LOG(
"config not loaded, skipping plugin load");
358 static int nid_poison_patched(uintptr_t dst,
int set,
size_t len) {
372 static int unload_process_patched(SceUID pid) {
375 LOG(
"unloading pid:%x", pid);
377 LOG(
"cleanup: %x", ret);
379 LOG(
"process unloaded: %x", ret);
406 len = sceIoLseekForDriver(fd, 0, SCE_SEEK_END);
408 LOG(
"failed to seek config");
409 sceIoCloseForDriver(fd);
410 return TAI_ERROR_SYSTEM;
413 sceIoLseekForDriver(fd, 0, SCE_SEEK_SET);
416 LOG(
"allocating %d bytes for config", (len + 0xfff) & ~0xfff);
417 g_config_blk = sceKernelAllocMemBlockForKernel(
"tai_config", SCE_KERNEL_MEMBLOCK_TYPE_KERNEL_RW, (len + 0xfff) & ~0xfff, NULL);
418 if (g_config_blk < 0) {
419 LOG(
"failed to allocate memory: %x", g_config_blk);
420 sceIoCloseForDriver(fd);
424 ret = sceKernelGetMemBlockBaseForKernel(g_config_blk, (
void **)&config);
426 LOG(
"failed to get base for %x: %x", g_config_blk, ret);
427 sceIoCloseForDriver(fd);
434 LOG(
"reading config to memory");
436 while (total < len) {
437 rd = sceIoReadForDriver(fd, config+total, len-total);
439 LOG(
"failed to read config: rd %x, total %x, len %x", rd, total, len);
446 sceIoCloseForDriver(fd);
448 sceKernelFreeMemBlockForKernel(g_config_blk);
452 if ((ret = taihen_config_validate(config)) != 0) {
453 LOG(
"config parsing failed: %x", ret);
454 sceKernelFreeMemBlockForKernel(g_config_blk);
469 sceKernelFreeMemBlockForKernel(g_config_blk);
488 LOG(
"no config loaded! skipping plugin load");
492 LOG(
"pid:%x loading module %s (flags:%x)", load->
pid, path, load->
flags);
493 if ((load->
flags & 0x8000) == 0x8000) {
494 ret = sceKernelLoadModuleForPid(load->
pid, path, load->
flags, NULL);
497 ret = sceKernelLoadStartModuleForPid(load->
pid, path, 0, NULL, load->
flags, NULL, &result);
499 LOG(
"load result: %x", ret);
508 memset(g_hooks, 0,
sizeof(g_hooks));
510 &g_parse_headers_hook,
511 "SceKernelModulemgr",
514 parse_headers_patched);
515 if (g_hooks[0] < 0)
goto fail;
516 LOG(
"parse_headers_patched added");
518 &g_setup_buffer_hook,
519 "SceKernelModulemgr",
522 setup_buffer_patched);
523 if (g_hooks[1] < 0)
goto fail;
524 LOG(
"setup_buffer_patched added");
526 &g_decrypt_buffer_hook,
527 "SceKernelModulemgr",
530 decrypt_buffer_patched);
531 if (g_hooks[2] < 0)
goto fail;
532 LOG(
"decrypt_buffer_patched added");
534 &g_rif_check_vita_hook,
538 rif_check_vita_patched);
539 if (g_hooks[3] < 0)
goto fail;
540 LOG(
"rif_check_vita added");
542 &g_rif_check_psp_hook,
546 rif_check_psp_patched);
547 if (g_hooks[4] < 0)
goto fail;
548 LOG(
"rif_check_psp added");
550 &g_rif_get_info_hook,
554 rif_get_info_patched);
555 if (g_hooks[5] < 0)
goto fail;
556 LOG(
"rif_get_info added");
558 &g_package_check_hook,
562 package_check_patched);
563 LOG(
"package_check added");
564 if (g_hooks[6] < 0)
goto fail;
566 &g_package_check_2_hook,
570 package_check_2_patched);
571 LOG(
"package_check_2 added");
572 if (g_hooks[7] < 0)
goto fail;
574 &g_load_user_libs_hook,
575 "SceKernelModulemgr",
578 load_user_libs_patched);
579 if (g_hooks[8] < 0)
goto fail;
580 LOG(
"load_user_libs added");
583 "SceKernelModulemgr",
587 if (g_hooks[9] < 0)
goto fail;
588 LOG(
"nid_poison_patched added");
590 &g_unload_process_hook,
594 unload_process_patched);
595 if (g_hooks[10] < 0)
goto fail;
596 LOG(
"unload_process_patched added");
600 if (g_hooks[0] >= 0) {
603 if (g_hooks[1] >= 0) {
606 if (g_hooks[2] >= 0) {
609 if (g_hooks[3] >= 0) {
612 if (g_hooks[4] >= 0) {
615 if (g_hooks[5] >= 0) {
618 if (g_hooks[6] >= 0) {
621 if (g_hooks[7] >= 0) {
624 if (g_hooks[8] >= 0) {
627 if (g_hooks[9] >= 0) {
630 if (g_hooks[10] >= 0) {
633 return TAI_ERROR_SYSTEM;
SceUID taiHookFunctionExportForKernel(SceUID pid, tai_hook_ref_t *p_hook, const char *module, uint32_t library_nid, uint32_t func_nid, const void *hook_func)
Add a hook to a module function export.
int hen_free_config(void)
Frees tai config file.
int taiHookReleaseForKernel(SceUID tai_uid, tai_hook_ref_t hook)
Release a hook.
uintptr_t tai_hook_ref_t
Hook information.
SceUID taiHookFunctionImportForKernel(SceUID pid, tai_hook_ref_t *p_hook, const char *module, uint32_t import_library_nid, uint32_t import_func_nid, const void *hook_func)
Add a hook to a module function import.
void hen_load_plugin(const char *path, void *param)
Callback to config parser to load a plugin.
SceUID pid
Process to load plugin to.
int tai_try_cleanup_process(SceUID pid)
Called on process exist to force remove private hooks.
int hen_load_config(void)
Load tai config file.
Arguments passed from taiHEN to config parser back to taiHEN.
int flags
Flags for loading.
int hen_add_patches(void)
Add kernel patches to disable SELF signature checks.
#define TAI_CONTINUE(type, hook,...)
Calls the next function in the chain.
int hen_remove_patches(void)
Removes the kernel patches for SELF loading.
#define TAIHEN_CONFIG_FILE