/********************************************//** * \brief Frees memory of where we want to load * * Finds the max and min addresses we want to * load to using program headers and frees * any module taking up those spaces. * \returns Zero on success, otherwise error ***********************************************/ int uvl_elf_free_memory (Elf32_Phdr_t *prog_hdrs, ///< Array of program headers int count) ///< Number of program headers { void *min_addr = (void*)0xFFFFFFFF; void *max_addr = (void*)0x00000000; loaded_module_info_t m_mod_info; PsvUID mod_list[MAX_LOADED_MODS]; u32_t num_loaded = MAX_LOADED_MODS; int i, j; u32_t length; int temp[2]; IF_VERBOSE LOG ("Reading %u program headers.", count); for (i = 0; i < count; i++) { if (prog_hdrs[i].p_vaddr < min_addr) { min_addr = prog_hdrs[i].p_vaddr; } if ((u32_t)prog_hdrs[i].p_vaddr + prog_hdrs[i].p_memsz > (u32_t)max_addr) { max_addr = (void*)((u32_t)prog_hdrs[i].p_vaddr + prog_hdrs[i].p_memsz); } } IF_DEBUG LOG ("Lowest load address: 0x%08X, highest: 0x%08X", (u32_t)min_addr, (u32_t)max_addr);\ IF_DEBUG LOG ("Getting list of loaded modules."); if (sceKernelGetModuleList (0xFF, mod_list, &num_loaded) < 0) { LOG ("Failed to get module list."); return -1; } IF_DEBUG LOG ("Found %u loaded modules.", num_loaded); for (i = 0; i < num_loaded; i++) { m_mod_info.size = sizeof (loaded_module_info_t); // should be 440 IF_VERBOSE LOG ("Getting information for module #%u, UID: 0x%X.", i, mod_list[i]); if (sceKernelGetModuleInfo (mod_list[i], &m_mod_info) < 0) { LOG ("Error getting info for mod 0x%08X, continuing", mod_list[i]); continue; } for (j = 0; j < 3; j++) { //if (m_mod_info.segments[j].vaddr > min_addr || (u32_t)m_mod_info.segments[j].vaddr + m_mod_info.segments[j].memsz > (u32_t)min_addr) if (m_mod_info.segments[j].vaddr == (void*)0x81000000) { IF_DEBUG LOG ("Module %s segment %u (0x%08X, size %u) is in our address space. Attempting to unload.", m_mod_info.module_name, j, (u32_t)m_mod_info.segments[j].vaddr, m_mod_info.segments[j].memsz); if (sceKernelStopUnloadModule (mod_list[i], 0, 0, 0, &temp[0], &temp[1]) < 0) { LOG ("Error unloading %s.", m_mod_info.module_name); return -1; } break; } } } return 0; }
int nid_table_addStubsInModule(Psp2LoadedModuleInfo *target) { nidTable_entry entry; DEBUG_LOG_("Searching for module info"); SceModuleInfo *orig_mod_info = nid_table_findModuleInfo(target->segments[0].vaddr, target->segments[0].memsz, target->module_name); DEBUG_LOG_("Found"); if(orig_mod_info != NULL) { //Build entries from export table SceUInt base_orig = (SceUInt)orig_mod_info - orig_mod_info->ent_top + sizeof(SceModuleInfo); SceModuleExports *exportTable_orig = (SceModuleExports*)(base_orig + orig_mod_info->ent_top); for(; (SceUInt)exportTable_orig < (SceUInt)(base_orig + orig_mod_info->ent_end); exportTable_orig++) { for(int i = 0; i < exportTable_orig->num_functions; i++) { entry.nid = exportTable_orig->nid_table[i]; entry.type = ENTRY_TYPES_FUNCTION; entry.value.p = exportTable_orig->entry_table[i]; nid_storage_addEntry(&entry); } } DEBUG_LOG_("Exports resolved"); //NOTE: The problem is somewhere here //Build entries from import table Psp2LoadedModuleInfo l_mod_info; int loadResult = sizeof(int); SceUID l_mod_uid = sceKernelLoadModule(target->path,0,&loadResult); if(l_mod_uid < 0) { DEBUG_LOG_("Reload failed..."); return -1; } l_mod_info.size = sizeof(Psp2LoadedModuleInfo); if(sceKernelGetModuleInfo(l_mod_uid, &l_mod_info) < 0) { DEBUG_LOG_("Failed to get module info..."); return -1; } SceModuleInfo *mod_info = nid_table_findModuleInfo(l_mod_info.segments[0].vaddr, l_mod_info.segments[0].memsz, l_mod_info.module_name); if(mod_info != NULL) { SceUInt base_orig = (SceUInt)target->segments[0].vaddr; SceUInt base_l = (SceUInt)l_mod_info.segments[0].vaddr; SceModuleImports *importTable_l = (SceModuleImports*)(base_l + mod_info->stub_top); //Check the export tables to see if the NID is present //If so assign the respective pointer to functionPtrLocation FOREACH_IMPORT(base_orig, orig_mod_info, importTable_orig) { void **entryTable = GET_FUNCTIONS_ENTRYTABLE(importTable_orig); SceNID *nidTable = GET_FUNCTIONS_NIDTABLE(importTable_l); for(unsigned int i = 0; i < GET_FUNCTION_COUNT(importTable_orig); i++) { int err = nid_table_analyzeStub(entryTable[i], nidTable[i], &entry); if(err == ANALYZE_STUB_OK) nid_storage_addEntry(&entry); else if(err == ANALYZE_STUB_INVAL) break; } entryTable = GET_VARIABLE_ENTRYTABLE(importTable_orig); nidTable = GET_VARIABLE_NIDTABLE(importTable_l); for(int i = 0; i < GET_VARIABLE_COUNT(importTable_orig); i++) { entry.type = ENTRY_TYPES_VARIABLE; entry.nid = nidTable[i]; entry.value.i = *(SceUInt*)entryTable[i]; nid_storage_addEntry(&entry); } importTable_l = GET_NEXT_IMPORT(importTable_l); }
int main(void) { int server, client; struct sockaddr_in serverAddress, clientAddress; char message[MessageSize]; char m1[] = "libSceLibcInternal.sprx"; char m2[] = "libkernel.sprx"; char m3[] = "librt.sprx"; char *modules[] = {m1, m2, m3}; int run = 1; memset(&serverAddress, 0, sizeof(serverAddress)); serverAddress.sin_len = sizeof(serverAddress); serverAddress.sin_family = AF_INET; serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); serverAddress.sin_port = htons(9025); memset(&clientAddress, 0, sizeof(clientAddress)); server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(server < 0) return EXIT_FAILURE; setsockopt(server, SOL_SOCKET, SO_REUSEADDR, (char *)&(int){ 1 }, sizeof(int)); setsockopt(server, SOL_SOCKET, SO_REUSEPORT, (char *)&(int){ 1 }, sizeof(int)); if(bind(server, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) { close(server); return EXIT_FAILURE; } if(listen(server, 10) < 0) { close(server); return EXIT_FAILURE; } while(run) { client = accept(server, NULL, NULL); if(client < 0) continue; while(1) { char moduleName[128]; char symbolName[128]; int module = 0; void *symbol = NULL; int state = 0; // sym - base could be 0 int i; PS4ResolveStatus r; SceKernelModuleInfo info; info.size = sizeof(SceKernelModuleInfo); if(read(client, message, MessageSize) <= 0) break; if(strncmp(message, "exit\0", 5) == 0) { run = 0; break; } if(sscanf(message, "%s %s", moduleName, symbolName) < 2) break; /* should use dlsym and lsm from kernel instead */ r = ps4ResolveModuleAndSymbol(moduleName, symbolName, &module, &symbol); for(i = 0; i < sizeof(modules) / sizeof(modules[0]) && r != PS4ResolveStatusSuccess; ++i) { if(strcmp(modules[i], moduleName) == 0) continue; module = 0; r = ps4ResolveModuleAndSymbol(modules[i], symbolName, &module, &symbol); if(r == 0) strcpy(moduleName, modules[i]); } if(symbol != 0) { state = 1; if(sceKernelGetModuleInfo(module, &info) == 0) symbol = (void *)((uintptr_t)symbol - (uintptr_t)(info.segmentInfo[0].address)); else state = 2; } memset(message, 0, MessageSize); if(sprintf(message, "%s %"PRIxPTR" %i", moduleName, symbol, state) < 0) break; if(write(client, message, MessageSize) <= 0) break; } close(client); } close(server); return EXIT_SUCCESS; }