diff --git a/Core/Config.cpp b/Core/Config.cpp index dfcca9ed1d..1f40ab67e7 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -291,7 +291,7 @@ static ConfigSetting generalSettings[] = { ConfigSetting("WindowHeight", &g_Config.iWindowHeight, 0), ConfigSetting("PauseOnLostFocus", &g_Config.bPauseOnLostFocus, false), #endif - + ConfigSetting("DumpDecryptedEboots", &g_Config.bDumpDecryptedEboot, false), ConfigSetting(false), }; diff --git a/Core/Config.h b/Core/Config.h index 1145c5f543..2c9fc26aeb 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -66,6 +66,7 @@ public: int iNumWorkerThreads; bool bScreenshotsAsPNG; bool bEnableLogging; + bool bDumpDecryptedEboot; #if defined(USING_WIN_UI) bool bPauseOnLostFocus; bool bTopMost; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 21f505727e..7089b668bb 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -48,6 +48,7 @@ #include "Core/HLE/sceKernelMemory.h" #include "Core/HLE/sceIo.h" #include "Core/HLE/KernelWaitHelpers.h" +#include "Core/ELF/ParamSFO.h" #include "GPU/GPUState.h" @@ -719,6 +720,48 @@ void Module::Cleanup() { } } +void __SaveDecryptedEbootToStorageMedia(const u8 *decryptedEbootDataPtr, const u32 length) { + if (!decryptedEbootDataPtr) { + ERROR_LOG(SCEMODULE, "Error saving decrypted EBOOT.BIN: invalid pointer"); + return; + } + + if (length == 0) { + ERROR_LOG(SCEMODULE, "Error saving decrypted EBOOT.BIN: invalid length"); + return; + } + + const std::string filenameToDumpTo = g_paramSFO.GetValueString("DISC_ID") + ".BIN"; + const std::string dumpDirectory = GetSysDirectory(DIRECTORY_DUMP); + const std::string fullPath = dumpDirectory + filenameToDumpTo; + + // If the file already exists, don't dump it again. + if (File::Exists(fullPath)) { + INFO_LOG(SCEMODULE, "Decrypted EBOOT.BIN already exists for this game, skipping dump."); + return; + } + + // Make sure the dump directory exists before continuing. + if (!File::Exists(dumpDirectory)) { + if (!File::CreateDir(dumpDirectory)) { + ERROR_LOG(SCEMODULE, "Unable to create directory for EBOOT dumping, aborting."); + return; + } + } + + FILE *decryptedEbootFile = fopen(fullPath.c_str(), "wb"); + if (!decryptedEbootFile) { + ERROR_LOG(SCEMODULE, "Unable to write decrypted EBOOT."); + return; + } + + const size_t lengthToWrite = length; + + fwrite(decryptedEbootDataPtr, sizeof(u8), lengthToWrite, decryptedEbootFile); + fclose(decryptedEbootFile); + INFO_LOG(SCEMODULE, "Successfully wrote decrypted EBOOT to %s", fullPath.c_str()); +} + Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *error_string, u32 *magic) { Module *module = new Module; kernelObjects.Create(module); @@ -763,6 +806,12 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro } else { // TODO: Is this right? module->nm.bss_size = head->bss_size; + + // If we've made it this far, it should be safe to dump. + if (g_Config.bDumpDecryptedEboot) { + INFO_LOG(SCEMODULE, "Dumping derypted EBOOT.BIN to file."); + __SaveDecryptedEbootToStorageMedia(ptr, head->elf_size); + } } } diff --git a/Core/System.cpp b/Core/System.cpp index 1036a82bcc..a6d91778c7 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -455,6 +455,8 @@ std::string GetSysDirectory(PSPDirectories directoryType) { return g_Config.memCardDirectory + "PSP/SYSTEM/"; case DIRECTORY_PAUTH: return g_Config.memCardDirectory + "PAUTH/"; + case DIRECTORY_DUMP: + return g_Config.memCardDirectory + "PSP/SYSTEM/DUMP/"; // Just return the memory stick root if we run into some sort of problem. default: ERROR_LOG(FILESYS, "Unknown directory type."); diff --git a/Core/System.h b/Core/System.h index 71a8b7a569..04ac782202 100644 --- a/Core/System.h +++ b/Core/System.h @@ -42,6 +42,7 @@ enum PSPDirectories { DIRECTORY_GAME, DIRECTORY_SAVEDATA, DIRECTORY_PAUTH, + DIRECTORY_DUMP, }; extern GlobalUIState globalUIState; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index e3b53a3607..6b60b1d757 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -576,6 +576,7 @@ void DeveloperToolsScreen::CreateViews() { list->Add(new Choice(de->T("System Information")))->OnClick.Handle(this, &DeveloperToolsScreen::OnSysInfo); list->Add(new CheckBox(&g_Config.bShowDeveloperMenu, de->T("Show Developer Menu"))); + list->Add(new CheckBox(&g_Config.bDumpDecryptedEboot, de->T("Dump Decrypted Eboot", "Dump Decrypted EBOOT.BIN (If Encrypted) When Booting Game"))); Choice *cpuTests = new Choice(de->T("Run CPU Tests")); list->Add(cpuTests)->OnClick.Handle(this, &DeveloperToolsScreen::OnRunCPUTests);