diff --git a/loader/Makefile b/loader/Makefile index 3af2aa5..b999e6d 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -34,6 +34,8 @@ TARGET := wiiupluginloader BUILD := build BUILD_DBG := $(TARGET)_dbg SOURCES := src/libelf \ +SOURCES := src/patcher \ + src/common \ src/ DATA := diff --git a/loader/src/common/retain_vars.cpp b/loader/src/common/retain_vars.cpp index aacbb82..39ac974 100644 --- a/loader/src/common/retain_vars.cpp +++ b/loader/src/common/retain_vars.cpp @@ -1,2 +1,2 @@ #include "retain_vars.h" - +replacement_data_t gbl_replacement_data __attribute__((section(".data"))); diff --git a/loader/src/common/retain_vars.h b/loader/src/common/retain_vars.h index 343d292..5a44443 100644 --- a/loader/src/common/retain_vars.h +++ b/loader/src/common/retain_vars.h @@ -1,5 +1,8 @@ #ifndef RETAINS_VARS_H_ #define RETAINS_VARS_H_ +#include "patcher/function_patcher.h" + +extern replacement_data_t gbl_replacement_data; #endif // RETAINS_VARS_H_ diff --git a/loader/src/link_utils.cpp b/loader/src/link_utils.cpp index b5b26e1..ffd190f 100644 --- a/loader/src/link_utils.cpp +++ b/loader/src/link_utils.cpp @@ -26,6 +26,7 @@ #include "link_utils.h" #include "elf_utils.h" #include "utils.h" +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include @@ -161,11 +163,17 @@ bool Module_LinkModuleElf(size_t index, Elf *elf, uint8_t **space) { destinations[elf_ndxscn(scn)] = (uint8_t *)entries; if (!Module_ElfLoadSection(elf, scn, shdr, entries)) goto exit_error; - Module_ElfLoadSymbols( - elf_ndxscn(scn), entries, symtab, symtab_count); + Module_ElfLoadSymbols(elf_ndxscn(scn), entries, symtab, symtab_count); + + int entries_offset = module_entries_count - entries_count; + + for(int i = 0;i< entries_count;i++){ + gbl_replacement_data.module_data[index].functions[i].entry_index = entries_offset +i; + gbl_replacement_data.module_data[index].number_used_functions++; + } } else { - DEBUG_FUNCTION_LINE("Copy function to %08X\n",*space); *space -= shdr->sh_size; + if (shdr->sh_addralign > 3) *space = (uint8_t *)((int)*space & ~(shdr->sh_addralign - 1)); @@ -175,6 +183,12 @@ bool Module_LinkModuleElf(size_t index, Elf *elf, uint8_t **space) { destinations[elf_ndxscn(scn)] = *space; assert(*space != NULL); + if((u32) *space < getApplicationEndAddr()){ + DEBUG_FUNCTION_LINE("Not enough space to load function %s into memory at %08X.\n",name,*space); + goto exit_error; + } + + DEBUG_FUNCTION_LINE("Copy section %s to %08X\n",name,*space); if (!Module_ElfLoadSection(elf, scn, shdr, *space)) goto exit_error; Module_ElfLoadSymbols( @@ -217,72 +231,69 @@ exit_error: return result; } -bool Module_ListLinkFinal(uint8_t **space) { - size_t relocation_index, entry_index, module_index; - bool result = false, has_error = false; +/** +Relocation the real_XXX calls into the "replace_data" area of the replacement_data_function_t struct. +This function also fill the other data needed of the replacement_data_function_t struct. +**/ +bool Module_ListLinkFinal() { + int has_error = 0; + bool result; - relocation_index = 0; - entry_index = 0; + int relocations = 0; + DEBUG_FUNCTION_LINE("Found modules: %d\n",gbl_replacement_data.number_used_modules); + for(int module_index=0;module_indexmodule_name); + DEBUG_FUNCTION_LINE("number of used function: %d\n",module_data->number_used_functions); + for(int j=0;jnumber_used_functions;j++){ + replacement_data_function_t * function_data = &module_data->functions[j]; + if(function_data->entry_index > module_entries_count-1){ + DEBUG_FUNCTION_LINE("Error. entry_index was too high: %d. maximum is %d\n",function_data->entry_index,module_entries_count-1); + goto exit_error; + } + wups_loader_entry_t * entry = &module_entries[function_data->entry_index]; + strncpy(function_data->function_name,entry->data._function.name,MAXIMUM_FUNCTION_NAME_LENGTH-1); + function_data->library = entry->data._function.library; + function_data->replaceAddr = (u32) entry->data._function.target; + function_data->replaceCall = (u32) entry->data._function.call_addr; - /* Process the replacements the link each module in turn. - * It must be done in this order, otherwise two replacements to the same - * function will cause an infinite loop. */ - for (module_index = 0; module_index < module_list_count; module_index++) { - size_t limit; + /* + We don't need this... - limit = entry_index + module_list[module_index]->entries_count; + DEBUG_FUNCTION_LINE("Searching for relocations %d\n",module_relocations_count); - /*for (; entry_index < limit; entry_index++) { - wups_loader_entry_t *entry; + module_unresolved_relocation_t *reloc = NULL; + for (int relocation_index = 0;relocation_index < module_relocations_count;relocation_index++) { + DEBUG_FUNCTION_LINE("Try relocation %d\n",relocation_index); + if (module_relocations[relocation_index].module == module_index){ + if(strcmp(entry->data._function.real_function_name,module_relocations[relocation_index].name) == 0){ + DEBUG_FUNCTION_LINE("Found the entry we want to replace %s\n",entry->data._function.real_function_name); + reloc = &module_relocations[relocation_index]; + break; + } + } + } - assert(entry_index < module_entries_count); - - entry = module_entries + entry_index; - - switch (entry->type) { - case WUPS_LOADER_ENTRY_EXPORT: { - break; - } case WUPS_LOADER_ENTRY_FUNCTION: - case WUPS_LOADER_ENTRY_FUNCTION_MANDATORY: { - if (!Module_ListLinkFinalReplaceFunction(space, entry)) + if(reloc != NULL){ + u32 call_addr = (u32) &function_data->replace_data[0]; + //DEBUG_FUNCTION_LINE("Found reloc. We need to find the symbol for: %s in lib %d\n",entry->data._function.name,entry->data._function.library); + //u32 call_addr = (u32) new_GetAddressOfFunction("OSFatal",WUPS_LOADER_LIBRARY_COREINIT); + DEBUG_FUNCTION_LINE("Relocating\n"); + if (!Module_ElfLinkOne(reloc->type, reloc->offset, reloc->addend, reloc->address, (uint32_t)call_addr)){ goto exit_error; - break; - } default: - goto exit_error; - } - }*/ + }else{ + relocations++; + DEBUG_FUNCTION_LINE("Success! relocated to %08X\n",call_addr); + } + }else{ - for (; - relocation_index < module_relocations_count; - relocation_index++) { - module_unresolved_relocation_t *reloc; - void *symbol; - - reloc = module_relocations + relocation_index; - - if (reloc->module != module_index) - break; - - assert(reloc->name != NULL); - //symbol = Search_SymbolLookup(reloc->name); - - if (symbol == NULL) { - DEBUG_FUNCTION_LINE( - "Missing symbol '%s' needed by '%s'\n", reloc->name, - module_list[module_index]->name); - has_error = true; - continue; - } - - if (!Module_ElfLinkOne( - reloc->type, reloc->offset, reloc->addend, - reloc->address, (uint32_t)symbol)) - goto exit_error; + }*/ } } + module_relocations_count -= relocations; - assert(entry_index == module_entries_count); - assert(relocation_index == module_relocations_count); + //assert(entry_index == module_entries_count); + //assert(relocation_index == module_relocations_count); if (has_error) goto exit_error; @@ -290,9 +301,11 @@ bool Module_ListLinkFinal(uint8_t **space) { result = true; exit_error: if (!result) DEBUG_FUNCTION_LINE("Module_ListLinkFinal: exit_error\n"); - module_relocations_count = 0; - module_relocations_capacity = 0; - free(module_relocations); + //module_relocations_count = 0; + //module_relocations_capacity = 0; + if(module_relocations_count == 0){ + free(module_relocations); + } return result; } diff --git a/loader/src/link_utils.h b/loader/src/link_utils.h index 8920604..a36fd77 100644 --- a/loader/src/link_utils.h +++ b/loader/src/link_utils.h @@ -17,7 +17,7 @@ extern "C" { bool Module_ListLink(uint8_t **space); bool Module_LinkModule(size_t index, const char *path, uint8_t **space); bool Module_LinkModuleElf(size_t index, Elf *elf, uint8_t **space); -bool Module_ListLinkFinal(uint8_t **space); +bool Module_ListLinkFinal(); extern wups_loader_entry_t *module_entries; extern size_t module_entries_count; diff --git a/loader/src/main.cpp b/loader/src/main.cpp index 0ea0b99..44245be 100644 --- a/loader/src/main.cpp +++ b/loader/src/main.cpp @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include "common/retain_vars.h" #include "common/common.h" #include @@ -22,9 +24,11 @@ #include "module_parser.h" #include "link_utils.h" #include "elf_utils.h" +#include "patcher/function_patcher.h" static void printModuleInfos(); static void printInfos(); +static void printReplacementInfos(); /* Entry point */ extern "C" int Menu_Main(int argc, char **argv){ @@ -38,12 +42,68 @@ extern "C" int Menu_Main(int argc, char **argv){ setup_os_exceptions(); + DEBUG_FUNCTION_LINE("End address of loader %08X\n",getApplicationEndAddr()); + + memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data)); + DEBUG_FUNCTION_LINE("Mount SD partition\n"); int res = 0; if((res = mount_sd_fat("sd")) >= 0){ DEBUG_FUNCTION_LINE("Mounting successful\n"); - loadAndProcessElf("sd:/wiiu/plugins/example_plugin.mod"); + loadElf("sd:/wiiu/plugins/example_plugin.mod"); + + if(module_list_count == 0){ + DEBUG_FUNCTION_LINE("Found no valid modules! =( Exiting\n"); + return EXIT_SUCCESS; + } + + DEBUG_FUNCTION_LINE("Found %d modules!\n",module_list_count); + + printInfos(); + + DEBUG_FUNCTION_LINE("Relocating them now\n"); + unsigned char * space = (unsigned char*)0x01000000; + + Module_ListLink(&space); + Module_ListLinkFinal(); + + DEBUG_FUNCTION_LINE("Flush memory\n"); + + DCFlushRange ((void*)getApplicationEndAddr(),0x01000000-getApplicationEndAddr()); + DCInvalidateRange((void*)getApplicationEndAddr(),0x01000000-getApplicationEndAddr()); + + if(module_relocations_count != 0){ + DEBUG_FUNCTION_LINE("We still have undefined symbol. Make sure to link them in =/ Exiting\n"); + } + + DEBUG_FUNCTION_LINE("Printing some information before replacing the functions\n"); + + printReplacementInfos(); + + for(int module_index=0;module_index= dump_size){ - DEBUG_FUNCTION_LINE("Hexdump of the first %08X bytes: \n",dump_size); - dumpHex(elfData,dump_size); - } - - DEBUG_FUNCTION_LINE("Now try to use brainslug code\n"); + DEBUG_FUNCTION_LINE("Try to load %s\n",elfPath); if(Module_CheckFile(elfPath)){ Module_Load(elfPath); - DEBUG_FUNCTION_LINE("Found %d modules!\n",module_list_count); - printInfos(); - unsigned char * space = (unsigned char*)0x00910000; - Module_ListLink(&space); - - printInfos(); - - DCFlushRange ((void*)0x00850000,0x00910000-0x00850000); - DCInvalidateRange((void*)0x00850000,0x00910000-0x00850000); - - if(module_relocations_count == 0){ - DEBUG_FUNCTION_LINE("We need no more relocations, we can call the functions!!\n"); - DEBUG_FUNCTION_LINE("Calling %d functions!\n",module_entries_count); - for (unsigned int i = 0; i < module_entries_count; i++) { - DEBUG_FUNCTION_LINE("--- Function %d ---\n",i); - if( module_entries[i].type == WUPS_LOADER_ENTRY_FUNCTION || - module_entries[i].type == WUPS_LOADER_ENTRY_FUNCTION_MANDATORY){ - DEBUG_FUNCTION_LINE("Let's call the function: %s \n",module_entries[i].data._function.name); - int ret = ( (int (*)(void))((unsigned int*)module_entries[i].data._function.target) )(); - DEBUG_FUNCTION_LINE("result: %08X \n",ret); - } - } - }else{ - DEBUG_FUNCTION_LINE("There are still symbols that need to be resolved. Can't call the functions\n"); - } } +} +static void printReplacementInfos(){ + DEBUG_FUNCTION_LINE("Found modules: %d\n",gbl_replacement_data.number_used_modules); + for(int module_index=0;module_indexmodule_name); + DEBUG_FUNCTION_LINE("Functions that will be replaced: %d\n",module_data->number_used_functions); + for(int j=0;jnumber_used_functions;j++){ + replacement_data_function_t * function_data = &module_data->functions[j]; + DEBUG_FUNCTION_LINE("[%d] function: %s from lib %d\n",j,function_data->function_name, function_data->library); + } + DEBUG_FUNCTION_LINE("--- function list end ---\n"); + } + DEBUG_FUNCTION_LINE("--- module list end ---\n"); } static void printInfos(){ diff --git a/loader/src/main.h b/loader/src/main.h index dbd62a9..7e9cf4a 100644 --- a/loader/src/main.h +++ b/loader/src/main.h @@ -11,7 +11,7 @@ extern "C" { //! C wrapper for our C++ functions int Menu_Main(int argc, char **argv); -void loadAndProcessElf(const char * elfPath); +void loadElf(const char * elfPath); #ifdef __cplusplus } diff --git a/loader/src/module_parser.cpp b/loader/src/module_parser.cpp index e125085..b015e6a 100644 --- a/loader/src/module_parser.cpp +++ b/loader/src/module_parser.cpp @@ -35,6 +35,7 @@ #include #include #include +#include "common/retain_vars.h" #include "utils.h" bool module_has_error; @@ -93,8 +94,7 @@ void Module_Load(const char *path) { switch (elf_kind(elf)) { case ELF_K_AR: /* TODO */ - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - Archives not yet supported.\n", path); + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Archives not yet supported.\n", path); module_has_info = true; goto exit_error; case ELF_K_ELF: @@ -238,6 +238,8 @@ static void Module_LoadElf(const char *path, Elf *elf) { /* roundup to multiple of 4 */ metadata->size += (-metadata->size & 3); + strncpy(gbl_replacement_data.module_data[module_list_count].module_name,metadata->name,MAXIMUM_MODULE_NAME_LENGTH-1); + list_ptr = (module_metadata_t **)Module_ListAllocate( &module_list, sizeof(module_metadata_t *), 1, &module_list_capacity, &module_list_count, MODULE_LIST_CAPACITY_DEFAULT); @@ -255,6 +257,9 @@ static void Module_LoadElf(const char *path, Elf *elf) { /* prevent the data being freed */ metadata = NULL; + gbl_replacement_data.number_used_modules++; + + exit_error: if (metadata != NULL) free(metadata); @@ -303,9 +308,7 @@ static module_metadata_t *Module_MetadataRead(const char *path, size_t index, El continue; if (!Module_ElfLoadSection(elf, scn, shdr, metadata)) { - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - Couldn't load .wups.meta.\n", - path); + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't load .wups.meta.\n", path); module_has_info = true; goto exit_error; } @@ -316,9 +319,7 @@ static module_metadata_t *Module_MetadataRead(const char *path, size_t index, El if (!Module_ElfLink( index, elf, elf_ndxscn(scn), metadata, symtab, symtab_count, symtab_strndx, false)) { - DEBUG_FUNCTION_LINE( - "Warning: Ignoring '%s' - .wups.meta contains invalid " - "relocations.\n", path); + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - .wups.meta contains invalid relocations.\n", path); module_has_info = true; goto exit_error; } @@ -456,7 +457,7 @@ static module_metadata_t *Module_MetadataRead(const char *path, size_t index, El strlen(game) + strlen(name) + strlen(author) + strlen(version) + strlen(license) + 6); if (ret == NULL) { - DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't parse BSlug metadata.\n", path); + DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Couldn't parse WUPS metadata.\n", path); module_has_info = true; goto exit_error; } diff --git a/loader/src/patcher/function_patcher.cpp b/loader/src/patcher/function_patcher.cpp new file mode 100644 index 0000000..4218041 --- /dev/null +++ b/loader/src/patcher/function_patcher.cpp @@ -0,0 +1,341 @@ +/**************************************************************************** + * Copyright (C) 2016-2018 Maschell + * With code from chadderz and dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "function_patcher.h" +#include +#include +#include + +#define DEBUG_LOG_DYN 1 + +rpl_handling rpl_handles[] __attribute__((section(".data"))) = { + {WUPS_LOADER_LIBRARY_AVM, "avm.rpl" ,0}, + {WUPS_LOADER_LIBRARY_CAMERA, "camera.rpl" ,0}, + {WUPS_LOADER_LIBRARY_COREINIT, "coreinit.rpl" ,0}, + {WUPS_LOADER_LIBRARY_DC, "dc.rpl" ,0}, + {WUPS_LOADER_LIBRARY_DMAE, "dmae.rpl" ,0}, + {WUPS_LOADER_LIBRARY_DRMAPP, "drmapp.rpl" ,0}, + {WUPS_LOADER_LIBRARY_ERREULA, "erreula.rpl" ,0}, + {WUPS_LOADER_LIBRARY_GX2, "gx2.rpl" ,0}, + {WUPS_LOADER_LIBRARY_H264, "h264.rpl" ,0}, + {WUPS_LOADER_LIBRARY_LZMA920, "lzma920.rpl" ,0}, + {WUPS_LOADER_LIBRARY_MIC, "mic.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NFC, "nfc.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NIO_PROF, "nio_prof.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NLIBCURL, "nlibcurl.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NLIBNSS, "nlibnss.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NLIBNSS2, "nlibnss2.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_AC, "nn_ac.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_ACP, "nn_acp.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_ACT, "nn_act.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_AOC, "nn_aoc.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_BOSS, "nn_boss.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_CCR, "nn_ccr.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_CMPT, "nn_cmpt.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_DLP, "nn_dlp.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_EC, "nn_ec.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_FP, "nn_fp.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_HAI, "nn_hai.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_HPAD, "nn_hpad.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_IDBE, "nn_idbe.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_NDM, "nn_ndm.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_NETS2, "nn_nets2.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_NFP, "nn_nfp.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_NIM, "nn_nim.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_OLV, "nn_olv.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_PDM, "nn_pdm.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_SAVE, "nn_save.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_SL, "nn_sl.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_SPM, "nn_spm.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_TEMP, "nn_temp.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_UDS, "nn_uds.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NN_VCTL, "nn_vctl.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NSYSCCR, "nsysccr.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NSYSHID, "nsyshid.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NSYSKBD, "nsyskbd.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NSYSNET, "nsysnet.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NSYSUHS, "nsysuhs.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NSYSUVD, "nsysuvd.rpl" ,0}, + {WUPS_LOADER_LIBRARY_NTAG, "ntag.rpl" ,0}, + {WUPS_LOADER_LIBRARY_PADSCORE, "padscore.rpl" ,0}, + {WUPS_LOADER_LIBRARY_PROC_UI, "proc_ui.rpl" ,0}, + {WUPS_LOADER_LIBRARY_SNDCORE2, "sndcore2.rpl" ,0}, + {WUPS_LOADER_LIBRARY_SNDUSER2, "snduser2.rpl" ,0}, + {WUPS_LOADER_LIBRARY_SND_CORE, "snd_core.rpl" ,0}, + {WUPS_LOADER_LIBRARY_SND_USER, "snd_user.rpl" ,0}, + {WUPS_LOADER_LIBRARY_SWKBD, "swkbd.rpl" ,0}, + {WUPS_LOADER_LIBRARY_SYSAPP, "sysapp.rpl" ,0}, + {WUPS_LOADER_LIBRARY_TCL, "tcl.rpl" ,0}, + {WUPS_LOADER_LIBRARY_TVE, "tve.rpl" ,0}, + {WUPS_LOADER_LIBRARY_UAC, "uac.rpl" ,0}, + {WUPS_LOADER_LIBRARY_UAC_RPL, "uac_rpl.rpl" ,0}, + {WUPS_LOADER_LIBRARY_USB_MIC, "usb_mic.rpl" ,0}, + {WUPS_LOADER_LIBRARY_UVC, "uvc.rpl" ,0}, + {WUPS_LOADER_LIBRARY_UVD, "uvd.rpl" ,0}, + {WUPS_LOADER_LIBRARY_VPAD, "vpad.rpl" ,0}, + {WUPS_LOADER_LIBRARY_VPADBASE, "vpadbase.rpl" ,0}, + {WUPS_LOADER_LIBRARY_ZLIB125, "zlib125.rpl" ,0} +}; + +void new_PatchInvidualMethodHooks(replacement_data_module_t * module_data){ + InitAcquireOS(); + new_resetLibs(); + + DEBUG_FUNCTION_LINE("Patching %d given functions\n",module_data->number_used_functions); + + s32 method_hooks_count = module_data->number_used_functions; + + u32 skip_instr = 1; + u32 my_instr_len = 6; + u32 instr_len = my_instr_len + skip_instr; + u32 flush_len = 4*instr_len; + for(s32 i = 0; i < method_hooks_count; i++){ + replacement_data_function_t * function_data = &module_data->functions[i]; + /* Patch branches to it. */ + volatile u32 *space = function_data->replace_data; + + DEBUG_FUNCTION_LINE("Patching %s ...\n",function_data->function_name); + if(function_data->functionType == STATIC_FUNCTION && function_data->alreadyPatched == 1){ + if(new_isDynamicFunction((u32)OSEffectiveToPhysical((void*)function_data->realAddr))){ + log_printf("The function %s is a dynamic function. Please fix that <3\n", function_data->function_name); + function_data->functionType = DYNAMIC_FUNCTION; + }else{ + log_printf("Skipping %s, its already patched\n", function_data->function_name); + continue; + } + } + + u32 physical = 0; + u32 repl_addr = (u32)function_data->replaceAddr; + u32 call_addr = (u32)function_data->replaceCall; + + u32 real_addr = new_GetAddressOfFunction(function_data->function_name,function_data->library); + + if(!real_addr){ + log_printf("\n"); + DEBUG_FUNCTION_LINE("OSDynLoad_FindExport failed for %s\n", function_data->function_name); + continue; + } + + if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE("%s is located at %08X!\n", function_data->function_name,real_addr);} + + physical = (u32)OSEffectiveToPhysical((void*)real_addr); + if(!physical){ + log_printf("Error. Something is wrong with the physical address\n"); + continue; + } + + if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE("%s physical is located at %08X!\n", function_data->function_name,physical);} + + *(volatile u32 *)(call_addr) = (u32)(space); + + + SC0x25_KernelCopyData((u32)space, physical, 4); + space++; + + //Only works if skip_instr == 1 + if(skip_instr == 1){ + // fill the restore instruction section + function_data->realAddr = real_addr; + function_data->restoreInstruction = *(space-1); + if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE("function_data->realAddr = %08X!\n", function_data->realAddr);} + if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE("function_data->restoreInstruction = %08X!\n",function_data->restoreInstruction) ;} + } + else{ + log_printf("Error. Can't save %s for restoring!\n", function_data->function_name); + } + + //adding jump to real function thx @ dimok for the assembler code + /* + 90 61 ff e0 stw r3,-32(r1) + 3c 60 12 34 lis r3,4660 + 60 63 56 78 ori r3,r3,22136 + 7c 69 03 a6 mtctr r3 + 80 61 ff e0 lwz r3,-32(r1) + 4e 80 04 20 bctr*/ + *space = 0x9061FFE0; + space++; + *space = 0x3C600000 | (((real_addr + (skip_instr * 4)) >> 16) & 0x0000FFFF); // lis r3, real_addr@h + space++; + *space = 0x60630000 | ((real_addr + (skip_instr * 4)) & 0x0000ffff); // ori r3, r3, real_addr@l + space++; + *space = 0x7C6903A6; // mtctr r3 + space++; + *space = 0x8061FFE0; // lwz r3,-32(r1) + space++; + *space = 0x4E800420; // bctr + space++; + DCFlushRange((void*)(space - instr_len), flush_len); + ICInvalidateRange((unsigned char*)(space - instr_len), flush_len); + + //setting jump back + u32 replace_instr = 0x48000002 | (repl_addr & 0x03fffffc); + ICInvalidateRange(&replace_instr, 4); + DCFlushRange(&replace_instr, 4); + + SC0x25_KernelCopyData(physical, (u32)OSEffectiveToPhysical(&replace_instr), 4); + ICInvalidateRange((void*)(real_addr), 4); + DCFlushRange((void*)(real_addr), 4); + + function_data->alreadyPatched = 1; + DEBUG_FUNCTION_LINE("done with patching %s!\n", function_data->function_name); + + } + DEBUG_FUNCTION_LINE("Done with patching given functions!\n"); +} + +/* ****************************************************************** */ +/* RESTORE ORIGINAL INSTRUCTIONS */ +/* ****************************************************************** */ +void new_RestoreInvidualInstructions(replacement_data_module_t * module_data){ + InitAcquireOS(); + new_resetLibs(); + DEBUG_FUNCTION_LINE("Restoring given functions!\n"); + + s32 method_hooks_count = module_data->number_used_functions; + + for(s32 i = 0; i < method_hooks_count; i++){ + replacement_data_function_t * function_data = &module_data->functions[i]; + + DEBUG_FUNCTION_LINE("Restoring %s... ",function_data->function_name); + if(function_data->restoreInstruction == 0 || function_data->realAddr == 0){ + log_printf("I dont have the information for the restore =( skip\n"); + continue; + } + + u32 real_addr = new_GetAddressOfFunction(function_data->function_name,function_data->library); + + if(!real_addr){ + log_printf("OSDynLoad_FindExport failed for %s\n", function_data->function_name); + continue; + } + + u32 physical = (u32)OSEffectiveToPhysical((void*)real_addr); + if(!physical){ + log_printf("Something is wrong with the physical address\n"); + continue; + } + + if(new_isDynamicFunction(physical)){ + log_printf("Its a dynamic function. We don't need to restore it!\n",function_data->function_name); + } else { + physical = (u32)OSEffectiveToPhysical((void*)function_data->realAddr); //When its an static function, we need to use the old location + if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE("Restoring %08X to %08X\n",(u32)function_data->restoreInstruction,physical);} + SC0x25_KernelCopyData(physical,(u32)&function_data->restoreInstruction , 4); + if(DEBUG_LOG_DYN){DEBUG_FUNCTION_LINE("ICInvalidateRange %08X\n",(void*)function_data->realAddr);} + ICInvalidateRange((void*)function_data->realAddr, 4); + DCFlushRange((void*)function_data->realAddr, 4); + log_printf("done\n"); + } + function_data->alreadyPatched = 0; // In case a + } + + DEBUG_FUNCTION_LINE("Done with restoring given functions!\n"); +} + +s32 new_isDynamicFunction(u32 physicalAddress){ + if((physicalAddress & 0x80000000) == 0x80000000){ + return 1; + } + return 0; +} + +u32 new_GetAddressOfFunction(const char * functionName,wups_loader_library_type_t library){ + u32 real_addr = 0; + + if(strcmp(functionName, "OSDynLoad_Acquire") == 0) + { + memcpy(&real_addr, &OSDynLoad_Acquire, 4); + return real_addr; + } + else if(strcmp(functionName, "LiWaitOneChunk") == 0) + { + real_addr = (u32)addr_LiWaitOneChunk; + return real_addr; + } + else if(strcmp(functionName, "LiBounceOneChunk") == 0) + { + //! not required on firmwares above 3.1.0 + if(OS_FIRMWARE >= 400) + return 0; + + u32 addr_LiBounceOneChunk = 0x010003A0; + real_addr = (u32)addr_LiBounceOneChunk; + return real_addr; + } + + u32 rpl_handle = 0; + + int rpl_handles_size = sizeof rpl_handles / sizeof rpl_handles[0]; + + for(int i = 0;i< rpl_handles_size; i++){ + if(rpl_handles[i].library == library){ + if(rpl_handles[i].handle == 0){ + DEBUG_FUNCTION_LINE("Lets acquire handle for rpl: %s\n",rpl_handles[i].rplname); + OSDynLoad_Acquire(rpl_handles[i].rplname, &rpl_handles[i].handle); + } + if(rpl_handles[i].handle == 0){log_printf("%s failed to acquire\n",rpl_handles[i].rplname); return 0;} + rpl_handle = rpl_handles[i].handle; + break; + } + } + + if(!rpl_handle){ + DEBUG_FUNCTION_LINE("Failed to find the RPL handle for %s\n", functionName); + return 0; + } + + OSDynLoad_FindExport(rpl_handle, 0, functionName, &real_addr); + + if(!real_addr){ + DEBUG_FUNCTION_LINE("OSDynLoad_FindExport failed for %s\n", functionName); + return 0; + } + + if((library == WUPS_LOADER_LIBRARY_NN_ACP) && (u32)(*(volatile u32*)(real_addr) & 0x48000002) == 0x48000000){ + u32 address_diff = (u32)(*(volatile u32*)(real_addr) & 0x03FFFFFC); + if((address_diff & 0x03000000) == 0x03000000) { + address_diff |= 0xFC000000; + } + real_addr += (s32)address_diff; + if((u32)(*(volatile u32*)(real_addr) & 0x48000002) == 0x48000000){ + return 0; + } + } + + return real_addr; +} + +void new_resetLibs(){ + int rpl_handles_size = sizeof rpl_handles / sizeof rpl_handles[0]; + + for(int i = 0;i< rpl_handles_size; i++){ + if(rpl_handles[i].handle != 0){ + DEBUG_FUNCTION_LINE("Resetting handle for rpl: %s\n",rpl_handles[i].rplname); + } + rpl_handles[i].handle = 0; + // Release handle? + } +} diff --git a/loader/src/patcher/function_patcher.h b/loader/src/patcher/function_patcher.h new file mode 100644 index 0000000..92dc8f0 --- /dev/null +++ b/loader/src/patcher/function_patcher.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * Copyright (C) 2016-2018 Maschell + * With code from chadderz and dimok + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#ifndef _FUNCTION_HOOKS_H_ +#define _FUNCTION_HOOKS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct rpl_handling { + wups_loader_library_type_t library; + const char rplname[15]; + u32 handle; +}; + +#define FUNCTION_PATCHER_METHOD_STORE_SIZE 7 + +#define STATIC_FUNCTION 0 +#define DYNAMIC_FUNCTION 1 + +#define FUNCTION_PATCHER_METHOD_STORE_SIZE 7 +#define MAXIMUM_MODULE_NAME_LENGTH 51 +#define MAXIMUM_FUNCTION_NAME_LENGTH 51 + +struct replacement_data_function_t{ + u32 replaceAddr; /* [needs to be filled] Address of our replacement function */ + u32 replaceCall; /* [needs to be filled] Address to access the real_function */ + wups_loader_library_type_t library; /* [needs to be filled] rpl where the function we want to replace is. */ + char function_name[MAXIMUM_FUNCTION_NAME_LENGTH]; /* [needs to be filled] name of the function we want to replace */ + u32 realAddr; /* [will be filled] Address of the real function we want to replace. */ + volatile u32 replace_data [FUNCTION_PATCHER_METHOD_STORE_SIZE]; /* [will be filled] Space for us to store some jump instructions */ + u32 restoreInstruction; /* [will be filled] Copy of the instruction we replaced to jump to our code. */ + u8 functionType; /* [needs to be filled] name of the function we want to replace */ + u8 alreadyPatched; /* [will be filled] */ + u32 entry_index; /* [needs to be filled] name of the function we want to replace */ + +}; + +#define MAXIMUM_FUNCTION_PER_MODULE 100 + +struct replacement_data_module_t{ + char module_name[MAXIMUM_MODULE_NAME_LENGTH] = ""; // Name of this module + int priority; // Priority of this module + int number_used_functions; // Number of used function. Maximum is MAXIMUM_FUNCTION_PER_MODULE + replacement_data_function_t functions[MAXIMUM_FUNCTION_PER_MODULE]; // Replacement information for each function. +}; + +#define MAXIMUM_MODULES 32 + +struct replacement_data_t{ + int number_used_modules = 0; // Number of used function. Maximum is MAXIMUM_FUNCTION_PER_MODULE + replacement_data_module_t module_data[MAXIMUM_MODULES]; +}; + +void new_PatchInvidualMethodHooks(replacement_data_module_t * data); +void new_RestoreInvidualInstructions(replacement_data_module_t * module_data); +u32 new_GetAddressOfFunction(const char * functionName,wups_loader_library_type_t library); +s32 new_isDynamicFunction(u32 physicalAddress); +void new_resetLibs(); + +//Orignal code by Chadderz. +#define MAKE_MAGIC(x, lib,functionType) { (u32) my_ ## x, (u32) &real_ ## x, lib, # x,0,0,functionType,0} +#define MAKE_MAGIC_NAME(x,y, lib,functionType) { (u32) my_ ## x, (u32) &real_ ## x, lib, # y,0,0,functionType,0} + +#ifdef __cplusplus +} +#endif + +#endif /* _FS_H */