taiHEN  1.0
CFW framework for PS Vita
taihen.c
1 /* taihen.c -- cfw framework for PS Vita
2  *
3  * Copyright (C) 2016 Yifan Lu
4  *
5  * This software may be modified and distributed under the terms
6  * of the MIT license. See the LICENSE file for details.
7  */
8 #include <psp2kern/types.h>
9 #include <psp2kern/kernel/modulemgr.h>
10 #include <taihen/parser.h>
11 #include "error.h"
12 #include "hen.h"
13 #include "module.h"
14 #include "patches.h"
15 #include "proc_map.h"
16 #include "taihen_internal.h"
17 
19 unsigned char log_ctr = 0;
20 
22 extern const char *g_config;
23 
41 SceUID taiHookFunctionAbs(SceUID pid, tai_hook_ref_t *p_hook, void *dest_func, const void *hook_func) {
42  return tai_hook_func_abs(p_hook, pid, dest_func, hook_func);
43 }
44 
72 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) {
73  int ret;
74  uintptr_t func;
75 
76  ret = module_get_export_func(pid, module, library_nid, func_nid, &func);
77  if (ret < 0) {
78  LOG("Failed to find export for %s, NID:0x%08X: 0x%08X", module, func_nid, ret);
79  return ret;
80  }
81  return taiHookFunctionAbs(pid, p_hook, (void *)func, hook_func);
82 }
83 
115 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) {
116  int ret;
117  uintptr_t stubptr;
118  uint32_t stub[3];
119 
120  ret = module_get_import_func(pid, module, import_library_nid, import_func_nid, &stubptr);
121  if (ret < 0) {
122  LOG("Failed to find stub for %s, NID:0x%08X: 0x%08X", module, import_func_nid, ret);
123  return ret;
124  }
125  ret = tai_memcpy_to_kernel(pid, stub, (const void *)(stubptr & ~1), sizeof(stub));
126  if (ret < 0) {
127  LOG("Failed to read stub %p, %x", stubptr, ret);
128  return ret;
129  }
130  // FIXME: find a better way to do this
131  if (stub[0] == 0xE24FC008 && stub[1] == 0xE12FFF1E) {
132  LOG("stub for %p has not been resolved yet!", import_func_nid);
133  return TAI_ERROR_STUB_NOT_RESOLVED;
134  }
135  return taiHookFunctionAbs(pid, p_hook, (void *)stubptr, hook_func);
136 }
137 
159 SceUID taiHookFunctionOffsetForKernel(SceUID pid, tai_hook_ref_t *p_hook, SceUID modid, int segidx, uint32_t offset, int thumb, const void *hook_func) {
160  int ret;
161  uintptr_t addr;
162 
163  ret = module_get_offset(pid, modid, segidx, offset, &addr);
164  if (ret < 0) {
165  LOG("Failed to find offset for mod:%x, segidx:%d, offset:0x%08X: 0x%08X", modid, segidx, offset, ret);
166  return ret;
167  }
168  if (thumb) {
169  addr = addr | 1;
170  }
171  return taiHookFunctionAbs(pid, p_hook, (void *)addr, hook_func);
172 }
173 
191 int taiGetModuleInfoForKernel(SceUID pid, const char *module, tai_module_info_t *info) {
192  return module_get_by_name_nid(pid, module, TAI_IGNORE_MODULE_NID, info);
193 }
194 
204 int taiHookReleaseForKernel(SceUID tai_uid, tai_hook_ref_t hook) {
205  return tai_hook_release(tai_uid, hook);
206 }
207 
219 SceUID taiInjectAbsForKernel(SceUID pid, void *dest, const void *src, size_t size) {
220  return tai_inject_abs(pid, dest, src, size);
221 }
222 
236 SceUID taiInjectDataForKernel(SceUID pid, SceUID modid, int segidx, uint32_t offset, const void *data, size_t size) {
237  int ret;
238  uintptr_t addr;
239 
240  ret = module_get_offset(pid, modid, segidx, offset, &addr);
241  if (ret < 0) {
242  LOG("Failed to find offset for mod:%x, segidx:%d, offset:0x%08X: 0x%08X", modid, segidx, offset, ret);
243  return ret;
244  }
245  return taiInjectAbsForKernel(pid, (void *)addr, data, size);
246 }
247 
255 int taiInjectReleaseForKernel(SceUID tai_uid) {
256  return tai_inject_release(tai_uid);
257 }
258 
270 int taiLoadPluginsForTitleForKernel(SceUID pid, const char *titleid, int flags) {
271  tai_plugin_load_t param;
272  if (g_config) {
273  param.pid = pid;
274  param.flags = flags;
275  taihen_config_parse(g_config, titleid, hen_load_plugin, &param);
276  return TAI_SUCCESS;
277  } else {
278  LOG("config not loaded");
279  return TAI_ERROR_SYSTEM;
280  }
281 }
282 
295 int module_start(SceSize argc, const void *args) {
296  int ret;
297  LOG("starting taihen...");
298  ret = proc_map_init();
299  if (ret < 0) {
300  LOG("proc map init failed: %x", ret);
301  return SCE_KERNEL_START_FAILED;
302  }
303  ret = patches_init();
304  if (ret < 0) {
305  LOG("patches init failed: %x", ret);
306  return SCE_KERNEL_START_FAILED;
307  }
308  ret = hen_add_patches();
309  if (ret < 0) {
310  LOG("HEN patches failed: %x", ret);
311  return SCE_KERNEL_START_FAILED;
312  }
313  ret = hen_load_config();
314  if (ret < 0) {
315  LOG("HEN config load failed: %x", ret);
316  return SCE_KERNEL_START_FAILED;
317  }
319  return SCE_KERNEL_START_SUCCESS;
320 }
321 
326 void _start() __attribute__ ((weak, alias ("module_start")));
327 
341 int module_stop(SceSize argc, const void *args) {
342  // TODO: release everything
344  patches_deinit();
345  proc_map_deinit();
346  return SCE_KERNEL_STOP_SUCCESS;
347 }
348 
354 void module_exit(void) {
355 
356 }
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.
Definition: taihen.c:72
SceUID taiHookFunctionAbs(SceUID pid, tai_hook_ref_t *p_hook, void *dest_func, const void *hook_func)
Add a hook given an absolute address.
Definition: taihen.c:41
int taiHookReleaseForKernel(SceUID tai_uid, tai_hook_ref_t hook)
Release a hook.
Definition: taihen.c:204
void proc_map_deinit(void)
Cleans up the map system.
Definition: proc_map.c:56
Extended module information.
Definition: taihen.h:53
uintptr_t tai_hook_ref_t
Hook information.
Definition: taihen.h:215
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.
Definition: taihen.c:115
SceUID taiHookFunctionOffsetForKernel(SceUID pid, tai_hook_ref_t *p_hook, SceUID modid, int segidx, uint32_t offset, int thumb, const void *hook_func)
Add a hook to a module manually with an offset.
Definition: taihen.c:159
int tai_hook_release(SceUID uid, tai_hook_ref_t hook_ref)
Removes a hook and restores original function if chain is empty.
Definition: patches.c:595
void hen_load_plugin(const char *path, void *param)
Callback to config parser to load a plugin.
Definition: hen.c:482
#define KERNEL_PID
Definition: taihen.h:34
int taiLoadPluginsForTitleForKernel(SceUID pid, const char *titleid, int flags)
Parses the taiHEN config and loads all plugins for a titleid to a process.
Definition: taihen.c:270
int taiInjectReleaseForKernel(SceUID tai_uid)
Release an injection.
Definition: taihen.c:255
SceUID pid
Process to load plugin to.
Definition: hen.h:23
int patches_init(void)
Initializes the patch system.
Definition: patches.c:90
SceUID tai_inject_abs(SceUID pid, void *dest, const void *src, size_t size)
Inserts a raw data injection given an absolute address and PID of the address space.
Definition: patches.c:646
int module_get_by_name_nid(SceUID pid, const char *name, uint32_t nid, tai_module_info_t *info)
Gets a loaded module by name or NID or both.
Definition: module.c:235
int module_get_export_func(SceUID pid, const char *modname, uint32_t libnid, uint32_t funcnid, uintptr_t *func)
Gets an exported function address.
Definition: module.c:326
int hen_load_config(void)
Load tai config file.
Definition: hen.c:392
SceUID tai_hook_func_abs(tai_hook_ref_t *p_hook, SceUID pid, void *dest_func, const void *hook_func)
Inserts a hook given an absolute address and PID of the function.
Definition: patches.c:498
#define TAI_IGNORE_MODULE_NID
Definition: taihen.h:40
SceUID taiInjectAbsForKernel(SceUID pid, void *dest, const void *src, size_t size)
Injects data into a process bypassing MMU flags.
Definition: taihen.c:219
Arguments passed from taiHEN to config parser back to taiHEN.
Definition: hen.h:22
int flags
Flags for loading.
Definition: hen.h:24
int tai_inject_release(SceUID uid)
Removes an injection and restores the original data.
Definition: patches.c:710
int hen_add_patches(void)
Add kernel patches to disable SELF signature checks.
Definition: hen.c:507
SceUID taiInjectDataForKernel(SceUID pid, SceUID modid, int segidx, uint32_t offset, const void *data, size_t size)
Inject data into a process bypassing MMU flags given an offset.
Definition: taihen.c:236
int hen_remove_patches(void)
Removes the kernel patches for SELF loading.
Definition: hen.c:641
int module_get_offset(SceUID pid, SceUID modid, int segidx, size_t offset, uintptr_t *addr)
Gets an offset from a segment in a module.
Definition: module.c:288
int tai_memcpy_to_kernel(SceUID src_pid, void *dst, const char *src, size_t size)
Memcpy from a process to kernel.
Definition: patches.c:364
int taiGetModuleInfoForKernel(SceUID pid, const char *module, tai_module_info_t *info)
Gets information on a currently loaded module.
Definition: taihen.c:191
void patches_deinit(void)
Cleans up the patch system.
Definition: patches.c:125
int proc_map_init(void)
Initializes the map system.
Definition: proc_map.c:38
int module_get_import_func(SceUID pid, const char *modname, uint32_t target_libnid, uint32_t funcnid, uintptr_t *stub)
Gets an imported function stub address.
Definition: module.c:392