diff --git a/Misc/General_IPC.h b/Misc/General_IPC.h index 310adc2..cd5dc1a 100644 --- a/Misc/General_IPC.h +++ b/Misc/General_IPC.h @@ -1,12 +1,13 @@ #pragma once // Genreall IPC ADDRS should follow the GeneralIPC# pattern. -#define GENERAL_IPC_ADDR "/system_tmp/GeneralIPC#%s" +#define GENERAL_IPC_ADDR "/system_tmp/GeneralIPC-%d" enum GeneralIPCCommands { - GIPC_INFO, GIPC_LIB_LIST, + GIPC_LIB_LOAD, + GIPC_LIB_UNLOAD, GIPC_JAILBREAK, GIPC_JAIL, GIPC_RW, @@ -19,10 +20,8 @@ enum GeneralIPCResult GIPC_OK, }; -struct ExtProccesInfoPacket +struct LibPacket { - char Path[64]; - char TitleId[16]; - char ContentId[64]; - char Version[6]; -}; \ No newline at end of file + char Path[100]; + int Handle; +}; diff --git a/Playstation/OrbisLibAPI/APIPackets.h b/Playstation/OrbisLibAPI/APIPackets.h index c2aff96..9dde53a 100644 --- a/Playstation/OrbisLibAPI/APIPackets.h +++ b/Playstation/OrbisLibAPI/APIPackets.h @@ -58,10 +58,10 @@ enum APICommands API_DBG_SET_DBGREG, /* Remote Library functions */ - API_DBG_LOAD_SPRX, - API_DBG_UNLOAD_SPRX, - API_DBG_RELOAD_SPRX, - API_DBG_MODULE_LIST, + API_DBG_LOAD_LIBRARY, + API_DBG_UNLOAD_LIBRARY, + API_DBG_RELOAD_LIBRARY, + API_DBG_LIBRARY_LIST, /* Thread Management */ API_DBG_THREAD_LIST, @@ -194,7 +194,7 @@ struct LibraryPacket int64_t Handle; char Path[256]; int32_t SegmentCount; - OrbisKernelModuleInfo Segments[4]; + OrbisKernelModuleSegmentInfo Segments[4]; }; struct DbgRWPacket @@ -205,13 +205,11 @@ struct DbgRWPacket struct DbgSPRXPacket { - char Name[256]; char Path[256]; - int ModuleHandle; - int Flags; + int Handle; }; -struct ProcBreakpointPacket +struct DbgBreakpointPacket { int Index; uint64_t Address; diff --git a/Playstation/OrbisLibAPI/Apps.cpp b/Playstation/OrbisLibAPI/Apps.cpp index 9027143..3758f4c 100644 --- a/Playstation/OrbisLibAPI/Apps.cpp +++ b/Playstation/OrbisLibAPI/Apps.cpp @@ -177,7 +177,7 @@ void Apps::StartApp(OrbisNetId Sock, const char* TitleId) return; } - auto res = LncUtil::sceLncUtilLaunchApp(TitleId, nullptr, &appParam); + auto res = sceLncUtilLaunchApp(TitleId, nullptr, &appParam); if (res <= 0) { klog("sceLncUtilLaunchApp() : Failed with error % llX\n", res); @@ -207,7 +207,7 @@ void Apps::SuspendApp(OrbisNetId Sock, const char* TitleId) { auto appId = GetAppId(TitleId); - if (appId > 0 && LncUtil::sceLncUtilSuspendApp(appId, 0) == 0) + if (appId > 0 && sceLncUtilSuspendApp(appId, 0) == 0) { Sockets::SendInt(Sock, 1); } @@ -221,7 +221,7 @@ void Apps::ResumeApp(OrbisNetId Sock, const char* TitleId) { auto appId = GetAppId(TitleId); - if (appId > 0 && LncUtil::sceLncUtilResumeApp(appId, 0) == 0 && sceApplicationSetApplicationFocus(appId) == 0) + if (appId > 0 && sceLncUtilResumeApp(appId, 0) == 0 && sceLncUtilSetAppFocus(appId, 0) == 0) { Sockets::SendInt(Sock, 1); } diff --git a/Playstation/OrbisLibAPI/Common.h b/Playstation/OrbisLibAPI/Common.h index 6ab98e6..d783838 100644 --- a/Playstation/OrbisLibAPI/Common.h +++ b/Playstation/OrbisLibAPI/Common.h @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include "SocketListener.h" #include "Utilities.h" @@ -33,11 +36,5 @@ #include "Sockets.h" #include "System.h" #include "Flash.h" - #include "APIPackets.h" -#include "LncUtil.h" -#include "ShellCoreUtil.h" #include "SystemMonitor.h" - -//#define FIRMWARE_505 -#define FIRMWARE_900 \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/Debug.cpp b/Playstation/OrbisLibAPI/Debug.cpp index 08a6df2..591aeed 100644 --- a/Playstation/OrbisLibAPI/Debug.cpp +++ b/Playstation/OrbisLibAPI/Debug.cpp @@ -1,11 +1,19 @@ #include "Common.h" #include "Debug.h" #include "APIHelper.h" +#include "GeneralIPC.h" #include +#define HelperPrxPath "/data/Orbis Suite/OrbisLibGeneralHelper.sprx" + void Debug::HandleAPI(OrbisNetId Sock, APIPacket* Packet) { + if (Packet->Command > API_DBG_GET_CURRENT) + { + Sockets::SendInt(Sock, IsDebugging ? 1 : 0); + } + switch (Packet->Command) { default: @@ -13,10 +21,58 @@ void Debug::HandleAPI(OrbisNetId Sock, APIPacket* Packet) case API_DBG_ATTACH: + Attach(Sock); + break; case API_DBG_DETACH: + + Detach(Sock); + break; + + case API_DBG_GET_CURRENT: + + Sockets::SendInt(Sock, CurrentPID); + + break; + + case API_DBG_READ: + + break; + + case API_DBG_WRITE: + + break; + + case API_DBG_KILL: + + break; + + //... + + case API_DBG_LOAD_LIBRARY: + + LoadLibrary(Sock); + + break; + + case API_DBG_UNLOAD_LIBRARY: + + UnloadLibrary(Sock); + + break; + + case API_DBG_RELOAD_LIBRARY: + + ReloadLibrary(Sock); + + break; + + case API_DBG_LIBRARY_LIST: + + GetLibraryList(Sock); + break; } } @@ -40,7 +96,7 @@ bool Debug::TryDetach(int pid) // TODO: Kill the watching thread and Remove any Watchpoints / Breakpoints now. IsDebugging = false; - CurrentPID = 0; + CurrentPID = -1; return true; } @@ -49,6 +105,12 @@ void Debug::Attach(OrbisNetId Sock) { auto pid = RecieveInt(Sock); + // Get Process name. + char processName[32]; + sceKernelGetProcessName(pid, processName); + + klog("Attempting to attach to %s (%d)\n", processName, pid); + // If we are currently debugging another process lets detach from it. if (!TryDetach(pid)) { @@ -66,8 +128,10 @@ void Debug::Attach(OrbisNetId Sock) return; } + sceKernelUsleep(500); + // Attaching by default will stop execution of the remote process. Lets continue it now. - res = ptrace(PT_CONTINUE, pid, nullptr, 0); + res = ptrace(PT_CONTINUE, pid, (void*)1, 0); if (res != 0) { klog("Attach(): ptrace(PT_CONTINUE) failed with error %llX\n", res); @@ -78,19 +142,154 @@ void Debug::Attach(OrbisNetId Sock) IsDebugging = true; CurrentPID = pid; + klog("Attached to %s(%d)\n", processName, pid); + SendStatus(Sock, 1); + + if (strcmp(processName, "SceShellCore")) + { + // Get app info. + OrbisAppInfo appInfo; + sceKernelGetAppInfo(pid, &appInfo); + + // Get sandbox path. + char sandBoxPath[PATH_MAX]; + snprintf(sandBoxPath, sizeof(sandBoxPath), "/mnt/sandbox/%s_000/data", appInfo.TitleId); + + // Mount data into sandbox + LinkDir("/data/", sandBoxPath); + } + + // Load the helper library. + int handle = sys_sdk_proc_prx_load(processName, HelperPrxPath); + klog("Helper handle = %llX\n", handle); } void Debug::Detach(OrbisNetId Sock) { - auto pid = RecieveInt(Sock); - auto result = TryDetach(pid); + bool result = false; + if (IsDebugging) + result = TryDetach(CurrentPID); SendStatus(Sock, result ? 1 : 0); } +void Debug::LoadLibrary(OrbisNetId Sock) +{ + if (!IsDebugging || CurrentPID == -1) + { + return; + } + + // Get next packet. + auto Packet = (DbgSPRXPacket*)malloc(sizeof(DbgSPRXPacket)); + sceNetRecv(Sock, Packet, sizeof(DbgSPRXPacket), 0); + + // Load the library. + int handle = 0; + GeneralIPC::LoadLibrary(CurrentPID, Packet->Path, &handle); + + // Send the result. + Sockets::SendInt(Sock, handle); + + free(Packet); +} + +void Debug::UnloadLibrary(OrbisNetId Sock) +{ + if (!IsDebugging || CurrentPID == -1) + { + return; + } + + // Get next packet. + auto Packet = (DbgSPRXPacket*)malloc(sizeof(DbgSPRXPacket)); + sceNetRecv(Sock, Packet, sizeof(DbgSPRXPacket), 0); + + // Unload the library. + auto result = GeneralIPC::UnLoadLibrary(CurrentPID, Packet->Handle); + + // Send the result. + Sockets::SendInt(Sock, result); + + free(Packet); +} + +void Debug::ReloadLibrary(OrbisNetId Sock) +{ + if (!IsDebugging || CurrentPID == -1) + { + return; + } + + // Get next packet. + auto Packet = (DbgSPRXPacket*)malloc(sizeof(DbgSPRXPacket)); + sceNetRecv(Sock, Packet, sizeof(DbgSPRXPacket), 0); + + // Unload the library. + auto result = GeneralIPC::UnLoadLibrary(CurrentPID, Packet->Handle); + if (result != 0) + { + klog("Failed to unload %d\n", Packet->Handle); + + Sockets::SendInt(Sock, result); + + free(Packet); + + return; + } + + // Wait a second. + sceKernelSleep(1); + + // Load the library again. + int handle = 0; + GeneralIPC::LoadLibrary(CurrentPID, Packet->Path, &handle); + + // Send the result. + Sockets::SendInt(Sock, handle); + + free(Packet); +} + +void Debug::GetLibraryList(OrbisNetId Sock) +{ + if (!IsDebugging || CurrentPID == -1) + { + return; + } + + // Get the library list with path. + std::vector klibraryList; + GeneralIPC::GetLibraryList(CurrentPID, klibraryList); + + // Parse the library list. + std::vector libraryList; + for (const auto& i : klibraryList) + { + OrbisKernelModuleInfo moduleInfo; + moduleInfo.size = sizeof(OrbisKernelModuleInfo); + sceKernelGetModuleInfo(i.ModuleHandle, &moduleInfo); + + LibraryPacket temp; + temp.Handle = i.ModuleHandle; + strcpy(temp.Path, i.Path); + temp.SegmentCount = moduleInfo.segmentCount; + memcpy(&temp.Segments, &moduleInfo.segmentInfo, sizeof(OrbisKernelModuleSegmentInfo) * 4); + + libraryList.push_back(temp); + } + + // Send the data size. + Sockets::SendInt(Sock, libraryList.size()); + + // Send the list to host. + Sockets::SendLargeData(Sock, (unsigned char*)libraryList.data(), libraryList.size() * sizeof(LibraryPacket)); +} + Debug::Debug() { - + IsDebugging = false; + CurrentPID = -1; } Debug::~Debug() diff --git a/Playstation/OrbisLibAPI/Debug.h b/Playstation/OrbisLibAPI/Debug.h index 94eeaab..bd5d7fb 100644 --- a/Playstation/OrbisLibAPI/Debug.h +++ b/Playstation/OrbisLibAPI/Debug.h @@ -15,4 +15,8 @@ private: void Attach(OrbisNetId Sock); void Detach(OrbisNetId Sock); + void LoadLibrary(OrbisNetId Sock); + void UnloadLibrary(OrbisNetId Sock); + void ReloadLibrary(OrbisNetId Sock); + void GetLibraryList(OrbisNetId Sock); }; diff --git a/Playstation/OrbisLibAPI/GeneralIPC.cpp b/Playstation/OrbisLibAPI/GeneralIPC.cpp index 6e16eda..2b8016b 100644 --- a/Playstation/OrbisLibAPI/GeneralIPC.cpp +++ b/Playstation/OrbisLibAPI/GeneralIPC.cpp @@ -2,10 +2,10 @@ #include "GeneralIPC.h" #include -OrbisNetId GeneralIPC::Connect(const char* ProcessName) +OrbisNetId GeneralIPC::Connect(int pid) { char fullPath[0x200]; - snprintf(fullPath, sizeof(fullPath), GENERAL_IPC_ADDR, ProcessName); + snprintf(fullPath, sizeof(fullPath), GENERAL_IPC_ADDR, pid); OrbisNetSockaddrUn addr = { 0 }; addr.sun_family = ORBIS_NET_AF_LOCAL; @@ -42,21 +42,193 @@ bool GeneralIPC::SendCommand(OrbisNetId Sock, int Command) return Status == GIPC_OK; } -bool GeneralIPC::GetExtProcessInfo(const char* ProcessName, ExtProccesInfoPacket* info) +bool GeneralIPC::GetLibraryList(int pid, std::vector& Libraries) { - auto Sock = Connect(ProcessName); - - if (!Sock) + // Open a new local socket connection for the process. + auto sock = Connect(pid); + if (!sock) { klog("[GeneralIPC] Failed to connect to socket.\n"); return false; } - if (!SendCommand(Sock, GIPC_INFO)) + // Send the command. + if (!SendCommand(sock, GIPC_LIB_LIST)) { klog("[GeneralIPC] Failed to send command.\n"); return false; } - return sceNetRecv(Sock, (void*)info, sizeof(ExtProccesInfoPacket), 0) == 0; + // Get the library count. + int LibraryCount = 0; + if (!Sockets::RecvInt(sock, &LibraryCount)) + { + klog("[GeneralIPC] Failed to recv library count.\n"); + return false; + } + + // Resize the vector to accept the data. + Libraries.resize(LibraryCount); + + if (!Sockets::RecvLargeData(sock, (unsigned char*)Libraries.data(), LibraryCount * sizeof(LibraryInfo))) + { + klog("[GeneralIPC] Failed to recv library data.\n"); + return false; + } + + return true; +} + +bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut) +{ + // Open a new local socket connection for the process. + auto sock = Connect(pid); + if (!sock) + { + klog("[GeneralIPC] Failed to connect to socket.\n"); + return false; + } + + // Send the command. + if (!SendCommand(sock, GIPC_LIB_LOAD)) + { + klog("[GeneralIPC] Failed to send command.\n"); + return false; + } + + // Jailbreak the process. + Jailbreak(pid); + + // Create next packet. + auto Packet = (LibPacket*)malloc(sizeof(LibPacket)); + strcpy(Packet->Path, Path); + + // Send the packet. + if (sceNetSend(sock, Packet, sizeof(LibPacket), 0) < 0) + { + klog("[GeneralIPC] Failed to send LibPacket.\n"); + + // Restore the jail. + Jail(pid); + + return false; + } + + // Recieve the result. + if (!Sockets::RecvInt(sock, HandleOut)) + { + klog("[GeneralIPC] Failed to recv handle.\n"); + + // Restore the jail. + Jail(pid); + + return false; + } + + // Check to see if it was loaded successfully. + if (*HandleOut <= 0) + { + klog("[GeneralIPC] Failed to load PRX '%s' (0x%llX).\n", *HandleOut); + + // Restore the jail. + Jail(pid); + + return false; + } + + // Restore the jail. + Jail(pid); + + return true; +} + +bool GeneralIPC::UnLoadLibrary(int pid, int Handle) +{ + // Open a new local socket connection for the process. + auto sock = Connect(pid); + if (!sock) + { + klog("[GeneralIPC] Failed to connect to socket.\n"); + return false; + } + + // Send the command. + if (!SendCommand(sock, GIPC_LIB_UNLOAD)) + { + klog("[GeneralIPC] Failed to send command.\n"); + return false; + } + + // Recieve the result. + int result = 0; + if (!Sockets::RecvInt(sock, &result)) + { + klog("[GeneralIPC] Failed to recv result.\n"); + return false; + } + + // Check to see if it was unloaded successfully. + if (result != 0) + { + klog("[GeneralIPC] Failed to un load PRX '%s' (0x%llX).\n", result); + return false; + } + + return true; +} + +bool GeneralIPC::Jailbreak(int pid) +{ + // Open a new local socket connection for the process. + auto sock = Connect(pid); + if (!sock) + { + klog("[GeneralIPC] Failed to connect to socket.\n"); + return false; + } + + // Send the command. + if (!SendCommand(sock, GIPC_JAILBREAK)) + { + klog("[GeneralIPC] Failed to send command.\n"); + return false; + } + + // Recieve the result. + int result = 0; + if (!Sockets::RecvInt(sock, &result)) + { + klog("[GeneralIPC] Failed to recv result.\n"); + return false; + } + + return result == 1; +} + +bool GeneralIPC::Jail(int pid) +{ + // Open a new local socket connection for the process. + auto sock = Connect(pid); + if (!sock) + { + klog("[GeneralIPC] Failed to connect to socket.\n"); + return false; + } + + // Send the command. + if (!SendCommand(sock, GIPC_JAIL)) + { + klog("[GeneralIPC] Failed to send command.\n"); + return false; + } + + // Recieve the result. + int result = 0; + if (!Sockets::RecvInt(sock, &result)) + { + klog("[GeneralIPC] Failed to recv result.\n"); + return false; + } + + return result == 1; } \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/GeneralIPC.h b/Playstation/OrbisLibAPI/GeneralIPC.h index 5eea152..d45a1fe 100644 --- a/Playstation/OrbisLibAPI/GeneralIPC.h +++ b/Playstation/OrbisLibAPI/GeneralIPC.h @@ -4,9 +4,13 @@ class GeneralIPC { private: - static OrbisNetId Connect(const char* ProcessName); + static OrbisNetId Connect(int pid); static bool SendCommand(OrbisNetId Sock, int Command); public: - static bool GetExtProcessInfo(const char* ProcessName, ExtProccesInfoPacket* info); + static bool GetLibraryList(int pid, std::vector& Libraries); + static bool LoadLibrary(int pid, const char* Path, int* HandleOut); + static bool UnLoadLibrary(int pid, int Handle); + static bool Jailbreak(int pid); + static bool Jail(int pid); }; \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/LncUtil.cpp b/Playstation/OrbisLibAPI/LncUtil.cpp deleted file mode 100644 index 46ab634..0000000 --- a/Playstation/OrbisLibAPI/LncUtil.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "Common.h" -#include "LncUtil.h" - -uint64_t LncUtil::LibraryBaseAddress = 0; -int(*LncUtil::_sceLncUtilGetAppId)(const char*); -int(*LncUtil::_sceLncUtilLaunchApp)(const char* titleId, char* args, LaunchAppParam* appParam); -int(*LncUtil::_sceLncUtilSuspendApp)(int AppId, int Flag); -int(*LncUtil::_sceLncUtilResumeApp)(int AppId, int Flag); - -#ifdef FIRMWARE_505 -#define sceLncUtilInitializeOffset 0x4BF0 -#define sceLncUtilGetAppIdOffset 0x4E10 -#define sceLncUtilLaunchAppOffset 0x4C10 -#define sceLncUtilSuspendAppOffset 0x4F20 -#define sceLncUtilResumeAppOffset 0x4F40 -#endif - -#ifdef FIRMWARE_900 -#define sceLncUtilInitializeOffset 0x5580 -#define sceLncUtilGetAppIdOffset 0x5770 -#define sceLncUtilLaunchAppOffset 0x55A0 -#define sceLncUtilSuspendAppOffset 0x5880 -#define sceLncUtilResumeAppOffset 0x58A0 -#endif - -int LncUtil::Init() -{ - // Load the prx or get its module handle. - int libHandle = sceKernelLoadStartModule("/system/common/lib/libSceSystemService.sprx", 0, nullptr, 0, nullptr, nullptr); - if (libHandle == 0) { - klog("Failed to load libSceSystemService Library.\n"); - return -1; - } - - // Get module info so we can find the base address. - OrbisKernelModuleInfo moduleInfo; - moduleInfo.size = sizeof(OrbisKernelModuleInfo); - if (sceKernelGetModuleInfo(libHandle, &moduleInfo) != 0) - { - klog("Failed to get libSceSystemService module info.\n"); - return -1; - } - - // Save base address for later. - LibraryBaseAddress = (uint64_t)moduleInfo.segmentInfo[0].address; - - if (LibraryBaseAddress <= 0) - { - klog("Failed to get libSceSystemService base address.\n"); - return -1; - } - - // Init the lnc util library. - auto sceLncUtilInitialize = (int(*)())(LibraryBaseAddress + sceLncUtilInitializeOffset); - if (sceLncUtilInitialize() != 0) - { - klog("Failed to call sceLncUtilInitialize().\n"); - return -1; - } - - // Set up Functions. - _sceLncUtilGetAppId = (decltype(_sceLncUtilGetAppId))(LibraryBaseAddress + sceLncUtilGetAppIdOffset); - _sceLncUtilLaunchApp = (decltype(_sceLncUtilLaunchApp))(LibraryBaseAddress + sceLncUtilLaunchAppOffset); - _sceLncUtilSuspendApp = (decltype(_sceLncUtilSuspendApp))(LibraryBaseAddress + sceLncUtilSuspendAppOffset); - _sceLncUtilResumeApp = (decltype(_sceLncUtilResumeApp))(LibraryBaseAddress + sceLncUtilResumeAppOffset); - - return 0; -} - -int LncUtil::sceLncUtilGetAppId(const char* TitleId) -{ - if ((uint64_t)_sceLncUtilGetAppId > sceLncUtilGetAppIdOffset) - { - return _sceLncUtilGetAppId(TitleId); - } - else - { - klog("failed to resolve sceLncUtilGetAppId\n"); - return -1; - } -} - -int LncUtil::sceLncUtilLaunchApp(const char* titleId, char* args, LaunchAppParam* appParam) -{ - if ((uint64_t)_sceLncUtilLaunchApp > sceLncUtilLaunchAppOffset) - { - return _sceLncUtilLaunchApp(titleId, args, appParam); - } - else - { - klog("failed to resolve sceLncUtilLaunchApp\n"); - return -1; - } -} - -int LncUtil::sceLncUtilSuspendApp(int AppId, int Flag) -{ - if ((uint64_t)_sceLncUtilSuspendApp > sceLncUtilSuspendAppOffset) - { - return _sceLncUtilSuspendApp(AppId, Flag); - } - else - { - klog("failed to resolve sceLncUtilSuspendApp\n"); - return -1; - } -} - -int LncUtil::sceLncUtilResumeApp(int AppId, int Flag) -{ - if ((uint64_t)_sceLncUtilResumeApp > sceLncUtilResumeAppOffset) - { - return _sceLncUtilResumeApp(AppId, Flag); - } - else - { - klog("failed to resolve sceLncUtilResumeApp\n"); - return -1; - } -} diff --git a/Playstation/OrbisLibAPI/LncUtil.h b/Playstation/OrbisLibAPI/LncUtil.h deleted file mode 100644 index e1c347e..0000000 --- a/Playstation/OrbisLibAPI/LncUtil.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -enum AppType -{ - AppTypeInvalid = -1, - Unknown, - ShellUI, - Daemon, - CDLG, - MiniApp, - BigApp, - ShellCore, - ShellApp -}; - -struct AppStatus -{ - int AppId; - int LaunchRequestAppId; - char AppType; -}; - -enum Flag -{ - Flag_None = 0, - SkipLaunchCheck = 1, - SkipResumeCheck = 1, - SkipSystemUpdateCheck = 2, - RebootPatchInstall = 4, - VRMode = 8, - NonVRMode = 16 -}; - -struct LaunchAppParam -{ - unsigned int size; //0x00 - int userId; //0x04 - int appAttr; //0x08 - int enableCrashReport; //0x0C - uint64_t checkFlag; //0x10 -}; - -class LncUtil -{ -public: - static int Init(); - static int sceLncUtilGetAppId(const char* TitleId); - static int sceLncUtilLaunchApp(const char* titleId, char* args, LaunchAppParam* appParam); - static int sceLncUtilSuspendApp(int AppId, int Flag); - static int sceLncUtilResumeApp(int AppId, int Flag); - -private: - static uint64_t LibraryBaseAddress; - static int(*_sceLncUtilGetAppId)(const char* titleId); - static int(*_sceLncUtilLaunchApp)(const char* titleId, char* args, LaunchAppParam* appParam); - static int(*_sceLncUtilSuspendApp)(int AppId, int Flag); - static int(*_sceLncUtilResumeApp)(int AppId, int Flag); -}; diff --git a/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj b/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj index b19a6fa..30c8168 100644 --- a/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj +++ b/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj @@ -69,11 +69,9 @@ del /s /q /f $(IntDir)\*.oelf - - @@ -95,9 +93,7 @@ del /s /q /f $(IntDir)\*.oelf - - diff --git a/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj.filters b/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj.filters index 7a958e6..df2edef 100644 --- a/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj.filters +++ b/Playstation/OrbisLibAPI/OrbisLibAPI.vcxproj.filters @@ -9,10 +9,6 @@ {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - {2695a710-ecaf-42db-80bb-c904ec4dfb8f} @@ -88,12 +84,6 @@ Source Files\Utilities - - Source Files\Utilities\PS Utils - - - Source Files\Utilities\PS Utils - Source Files\Utilities\PS Utils @@ -156,12 +146,6 @@ Header Files\Utilities - - Header Files\Utilities\PS Utils - - - Header Files\Utilities\PS Utils - Header Files\Utilities\PS Utils diff --git a/Playstation/OrbisLibAPI/ShellCoreUtil.cpp b/Playstation/OrbisLibAPI/ShellCoreUtil.cpp deleted file mode 100644 index 0dd7c3b..0000000 --- a/Playstation/OrbisLibAPI/ShellCoreUtil.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "Common.h" -#include "ShellCoreUtil.h" - -uint64_t ShellCoreUtil::LibraryBaseAddress = 0; -int(*ShellCoreUtil::_sceShellCoreUtilGetFreeSizeOfUserPartition)(uint64_t* free, uint64_t* total); - -#ifdef FIRMWARE_505 -#define sceShellCoreUtilGetFreeSizeOfUserPartitionOffset 0x105A0 -#endif - -#ifdef FIRMWARE_900 -#define sceShellCoreUtilGetFreeSizeOfUserPartitionOffset 0x10B40 -#endif - -int ShellCoreUtil::Init() -{ - // Load the prx or get its module handle. - int libHandle = sceKernelLoadStartModule("/system/common/lib/libSceSystemService.sprx", 0, nullptr, 0, nullptr, nullptr); - if (libHandle == 0) { - klog("Failed to load libSceSystemService Library.\n"); - return -1; - } - - // Get module info so we can find the base address. - OrbisKernelModuleInfo moduleInfo; - moduleInfo.size = sizeof(OrbisKernelModuleInfo); - if (sceKernelGetModuleInfo(libHandle, &moduleInfo) != 0) - { - klog("Failed to get libSceSystemService module info.\n"); - return -1; - } - - // Save base address for later. - LibraryBaseAddress = (uint64_t)moduleInfo.segmentInfo[0].address; - - if (LibraryBaseAddress <= 0) - { - klog("Failed to get libSceSystemService base address.\n"); - return -1; - } - - // Set up Functions. - _sceShellCoreUtilGetFreeSizeOfUserPartition = (decltype(_sceShellCoreUtilGetFreeSizeOfUserPartition))(LibraryBaseAddress + sceShellCoreUtilGetFreeSizeOfUserPartitionOffset); - - return 0; -} - -int ShellCoreUtil::sceShellCoreUtilGetFreeSizeOfUserPartition(uint64_t* free, uint64_t* total) -{ - if ((uint64_t)_sceShellCoreUtilGetFreeSizeOfUserPartition > sceShellCoreUtilGetFreeSizeOfUserPartitionOffset) - { - return _sceShellCoreUtilGetFreeSizeOfUserPartition(free, total); - } - else - { - klog("failed to resolve sceShellCoreUtilGetFreeSizeOfUserPartition\n"); - return -1; - } -} \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/ShellCoreUtil.h b/Playstation/OrbisLibAPI/ShellCoreUtil.h deleted file mode 100644 index 9e38a6f..0000000 --- a/Playstation/OrbisLibAPI/ShellCoreUtil.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -class ShellCoreUtil -{ -public: - static int Init(); - static int sceShellCoreUtilGetFreeSizeOfUserPartition(uint64_t* free, uint64_t* total); - -private: - static uint64_t LibraryBaseAddress; - static int(*_sceShellCoreUtilGetFreeSizeOfUserPartition)(uint64_t* free, uint64_t* total); -}; diff --git a/Playstation/OrbisLibAPI/Sockets.cpp b/Playstation/OrbisLibAPI/Sockets.cpp index dcc920d..bb92ee8 100644 --- a/Playstation/OrbisLibAPI/Sockets.cpp +++ b/Playstation/OrbisLibAPI/Sockets.cpp @@ -3,12 +3,28 @@ bool Sockets::SendInt(OrbisNetId Sock, int val) { - return !(sceNetSend(Sock, &val, sizeof(int), 0) < 0); + auto res = sceNetSend(Sock, &val, sizeof(int), 0); + if (res <= 0) + { + klog("SendInt(): Failed to send %llX\n", res); + + return false; + } + + return true; } bool Sockets::RecvInt(OrbisNetId Sock, int* val) { - return !(sceNetRecv(Sock, val, sizeof(int), 0) < 0); + auto res = sceNetRecv(Sock, val, sizeof(int), 0); + if (res <= 0) + { + klog("RecvInt(): Failed to send %llX\n", res); + + return false; + } + + return true; } bool Sockets::SendLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen) @@ -25,6 +41,7 @@ bool Sockets::SendLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen if (res < 0) { + klog("SendLargeData() Error: %llX\n", res); return false; } @@ -32,5 +49,28 @@ bool Sockets::SendLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen CurrentPosition += res; } + return true; +} + +bool Sockets::RecvLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen) +{ + size_t DataLeft = dataLen; + int Received = 0; + int res = 0; + + while (DataLeft > 0) + { + size_t DataChunkSize = std::min((size_t)8192, DataLeft); + res = sceNetRecv(Sock, data + Received, DataChunkSize, 0); + + if (res < 0) + { + return false; + } + + Received += res; + DataLeft -= res; + } + return true; } \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/Sockets.h b/Playstation/OrbisLibAPI/Sockets.h index d31075d..1c203ed 100644 --- a/Playstation/OrbisLibAPI/Sockets.h +++ b/Playstation/OrbisLibAPI/Sockets.h @@ -6,7 +6,7 @@ public: static bool SendInt(OrbisNetId Sock, int val); static bool RecvInt(OrbisNetId Sock, int* val); static bool SendLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen); - + static bool RecvLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen); private: }; diff --git a/Playstation/OrbisLibAPI/Target.cpp b/Playstation/OrbisLibAPI/Target.cpp index 5ae2d69..bb8e7f9 100644 --- a/Playstation/OrbisLibAPI/Target.cpp +++ b/Playstation/OrbisLibAPI/Target.cpp @@ -139,7 +139,7 @@ void Target::SendTargetInfo(OrbisNetId Sock) sceUserServiceGetForegroundUser(&Packet->ForegroundAccountId); // Storage Stats. - auto res = ShellCoreUtil::sceShellCoreUtilGetFreeSizeOfUserPartition(&Packet->FreeSpace, &Packet->TotalSpace); + auto res = sceShellCoreUtilGetFreeSizeOfUserPartition(&Packet->FreeSpace, &Packet->TotalSpace); // Perf Stats. TODO: Move from toolbox /*Packet->ThreadCount = SystemMonitor::Thread_Count; diff --git a/Playstation/OrbisLibAPI/Utilities.cpp b/Playstation/OrbisLibAPI/Utilities.cpp index c16d697..3e6f67d 100644 --- a/Playstation/OrbisLibAPI/Utilities.cpp +++ b/Playstation/OrbisLibAPI/Utilities.cpp @@ -78,18 +78,10 @@ bool LoadModules() } // Init temporary wrapper for lncutils. - res = LncUtil::Init(); + res = sceLncUtilInitialize(); if (res != 0) { - klog("LoadModules(): LncUtil::Init failed (%llX)\n", res); - return false; - } - - // Init temporary wrapper for shellcoreutils. - res = ShellCoreUtil::Init(); - if (res != 0) - { - klog("LoadModules(): ShellCoreUtil::Init failed (%llX)\n", res); + klog("LoadModules(): sceLncUtilInitialize failed (%llX)\n", res); return false; } @@ -289,4 +281,70 @@ int GetProcessList(std::vector& ProcessList) }), ProcessList.end()); return 0; +} + +static void build_iovec(iovec** iov, int* iovlen, const char* name, const void* val, size_t len) { + int i; + + if (*iovlen < 0) + return; + + i = *iovlen; + *iov = (iovec*)realloc(*iov, sizeof * *iov * (i + 2)); + if (*iov == NULL) { + *iovlen = -1; + return; + } + + (*iov)[i].iov_base = strdup(name); + (*iov)[i].iov_len = strlen(name) + 1; + ++i; + + (*iov)[i].iov_base = (void*)val; + if (len == (size_t)-1) { + if (val != NULL) + len = strlen((const char*)val) + 1; + else + len = 0; + } + (*iov)[i].iov_len = (int)len; + + *iovlen = ++i; +} + +int nmount(struct iovec* iov, unsigned int niov, int flags) +{ + return syscall(378, iov, niov, flags); +} + +bool LinkDir(const char* Dir, const char* LinkedDir) +{ + auto res = sceKernelMkdir(LinkedDir, 0777); + if (res != 0) + { + if (res == 0x80020011) + { + klog("Directory '%s' already exists!\n", LinkedDir); + return true; + } + + klog("Failed to make dir '%s' err: %llX\n", LinkedDir, res); + return false; + } + + struct iovec* iov = NULL; + int iovlen = 0; + + build_iovec(&iov, &iovlen, "fstype", "nullfs", -1); + build_iovec(&iov, &iovlen, "fspath", LinkedDir, -1); + build_iovec(&iov, &iovlen, "target", Dir, -1); + + if (nmount(iov, iovlen, 0)) + { + klog("nmount failed\n"); + sceKernelRmdir(LinkedDir); + return false; + } + + return true; } \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/Utilities.h b/Playstation/OrbisLibAPI/Utilities.h index d8e890b..9ef27ca 100644 --- a/Playstation/OrbisLibAPI/Utilities.h +++ b/Playstation/OrbisLibAPI/Utilities.h @@ -35,3 +35,4 @@ struct kinfo_proc { void hexdump(void* ptr, int buflen); int GetProcessList(std::vector& ProcessList); +bool LinkDir(const char* Dir, const char* LinkedDir); diff --git a/Playstation/OrbisLibAPI/Version.h b/Playstation/OrbisLibAPI/Version.h index cc8a4a7..a7c5037 100644 --- a/Playstation/OrbisLibAPI/Version.h +++ b/Playstation/OrbisLibAPI/Version.h @@ -1,11 +1,11 @@ -#pragma once -#define ORBISLIB_MAJOR 3 -#define ORBISLIB_MINOR 0 -#define ORBISLIB_BUILDVERSION 874 -#define stringify(a) stringify_(a) -#define stringify_(a) #a -#if defined(_DEBUG) -#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) -#else -#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) -#endif +#pragma once +#define ORBISLIB_MAJOR 3 +#define ORBISLIB_MINOR 0 +#define ORBISLIB_BUILDVERSION 933 +#define stringify(a) stringify_(a) +#define stringify_(a) #a +#if defined(_DEBUG) +#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) +#else +#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) +#endif diff --git a/Playstation/OrbisLibAPI/build.bat b/Playstation/OrbisLibAPI/build.bat index f2f0d69..97928ac 100644 --- a/Playstation/OrbisLibAPI/build.bat +++ b/Playstation/OrbisLibAPI/build.bat @@ -1,7 +1,7 @@ SETLOCAL EnableDelayedExpansion Rem Libraries to link in -set libraries=-lc++ -lc -lSceSysmodule -lkernel -lSceVideoOut -lSceSystemService -lSceSysCore -lSceSystemStateMgr -lSceNet -lScePad -lSceUserService -lSceRegMgr -lSceFreeType -lSceMsgDialog -lSceCommonDialog -lGoldHEN_Hook -lSQLite -lSceAppInstUtil +set libraries=-lc++ -lc -lSceSysmodule -lkernel -lSceVideoOut -lSceSystemService -lSceSysCore -lSceSystemStateMgr -lSceNet -lScePad -lSceUserService -lSceRegMgr -lSceFreeType -lSceMsgDialog -lSceCommonDialog -lGoldHEN_Hook -lSQLite -lSceAppInstUtil -lSceLncUtil -lSceShellCoreUtil Rem Read the script arguments into local vars set intdir=%1 @@ -31,7 +31,7 @@ copy "eboot.bin" %outputPath%\Playstation\Build\pkg\Daemons\ORBS30000\eboot.bin del "eboot.bin" REM Generate the script. Will overwrite any existing temp.txt -echo open 1.1.0.14 2121> temp.txt +echo open 1.1.0.15 2121> temp.txt echo anonymous>> temp.txt echo anonymous>> temp.txt echo cd "/system/vsh/app/ORBS30000/">> temp.txt diff --git a/Playstation/OrbisLibAPI/main.cpp b/Playstation/OrbisLibAPI/main.cpp index 8f97a9f..14894bf 100644 --- a/Playstation/OrbisLibAPI/main.cpp +++ b/Playstation/OrbisLibAPI/main.cpp @@ -3,10 +3,6 @@ #include "API.h" #include "GoldHEN.h" -#include "AppDatabase.h" - -#include "GeneralIPC.h" - void exiting() { klog("Good bye friends! :)\n"); @@ -67,9 +63,9 @@ int main() } #endif -//#define KILLSHELLUI +// #define KILLSHELLUI #ifdef KILLSHELLUI - sceSystemServiceKillApp(LncUtil::sceLncUtilGetAppId("NPXS20001"), -1, 0, 0); + sceSystemServiceKillApp(sceLncUtilGetAppId("NPXS20001"), -1, 0, 0); #endif sceSystemServiceLoadExec("exit", 0); diff --git a/Playstation/OrbisLibGeneralHelper/Common.h b/Playstation/OrbisLibGeneralHelper/Common.h index 6c3f8b0..72561fa 100644 --- a/Playstation/OrbisLibGeneralHelper/Common.h +++ b/Playstation/OrbisLibGeneralHelper/Common.h @@ -22,5 +22,6 @@ #include "../../Misc/libjbc.h" #include "Utilities.h" #include "LocalSocketListener.h" +#include "Sockets.h" extern LocalSocketListener* LocalListener; \ No newline at end of file diff --git a/Playstation/OrbisLibGeneralHelper/LocalSocketListener.cpp b/Playstation/OrbisLibGeneralHelper/LocalSocketListener.cpp index 85875ef..3e742da 100644 --- a/Playstation/OrbisLibGeneralHelper/LocalSocketListener.cpp +++ b/Playstation/OrbisLibGeneralHelper/LocalSocketListener.cpp @@ -20,6 +20,8 @@ void* LocalSocketListener::ClientThread(void* tdParam) void* LocalSocketListener::DoWork() { + Jailbreak(); + OrbisNetSockaddrUn addr = { 0 }; addr.sun_family = ORBIS_NET_AF_LOCAL; strncpy(addr.sun_path, this->ServerAddress, sizeof(addr.sun_path)); @@ -44,6 +46,8 @@ void* LocalSocketListener::DoWork() goto Cleanup; } + RestoreJail(); + if (sceNetListen(this->Socket, 100) != 0) { klog("Failed to start listening on Socket.\n"); @@ -86,6 +90,7 @@ void* LocalSocketListener::DoWork() int optval = 1; sceNetSetsockopt(ClientSocket, ORBIS_NET_SOL_SOCKET, ORBIS_NET_SO_NOSIGPIPE, &optval, sizeof(optval)); + // Set up thread params. ClientThreadParams* Params = new ClientThreadParams(); Params->LocalSocketListener = this; @@ -105,9 +110,9 @@ void* LocalSocketListener::DoWork() Cleanup: klog("Listener Thread Exiting!\n"); - // Clean up. sceNetSocketClose(this->Socket); + sceKernelUnlink(this->ServerAddress); // Kill our thread and exit. scePthreadExit(NULL); diff --git a/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.cpp b/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.cpp index 4d12006..3a05eba 100644 --- a/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.cpp +++ b/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.cpp @@ -5,37 +5,59 @@ LocalSocketListener* LocalListener = nullptr; void SendLibraryList(OrbisNetId Sock) { - int MaxOutput = 0; - if (!SockRecvInt(Sock, &MaxOutput)) - { - klog("Failed to recv int.\n"); - return; - } - // Get the libraries. - LibraryInfo* LibraryList = (LibraryInfo*)malloc(MaxOutput * sizeof(LibraryInfo)); - int RealLibCount = jbc_get_proc_libraries(LibraryList, MaxOutput); - - // Make sure not to overflow the sender. - if (RealLibCount > MaxOutput) - { - klog("Warning: SendLibraryList MaxOutput too small."); - RealLibCount = MaxOutput; - } + LibraryInfo* LibraryList = (LibraryInfo*)malloc(200 * sizeof(LibraryInfo)); + int RealLibCount = jbc_get_proc_libraries(LibraryList, 200); // Send the Count - SockSendInt(Sock, RealLibCount); + Sockets::SendInt(Sock, RealLibCount); // Ship it. - sceNetSend(Sock, (void*)LibraryList, RealLibCount * sizeof(LibraryInfo), 0); + Sockets::SendLargeData(Sock, (unsigned char*)LibraryList, RealLibCount * sizeof(LibraryInfo)); // Clean up! free(LibraryList); } +void LoadUnloadLib(int Command, OrbisNetId Sock) +{ + auto Packet = (LibPacket*)malloc(sizeof(LibPacket)); + sceNetRecv(Sock, Packet, sizeof(LibPacket), 0); + + if (Command == GIPC_LIB_LOAD) + { + int res = sceKernelLoadStartModule(Packet->Path, 0, 0, 0, 0, 0); + + // Send the result. + Sockets::SendInt(Sock, res); + } + else + { + int res = sceKernelStopUnloadModule(Packet->Handle, 0, 0, 0, 0, 0); + + // Send the result. + Sockets::SendInt(Sock, res); + } + + free(Packet); +} + void ListenerClientThread(void* tdParam, OrbisNetId Sock) { - int Command = RecieveInt(Sock); + int Command = 0; + + if (!Sockets::RecvInt(Sock, &Command)) + { + klog("Failed to recv Command.\n"); + return; + } + + if (!Sockets::SendInt(Sock, GIPC_OK)) + { + klog("Failed to send confirm command.\n"); + return; + } + if (Command != -1) { switch (Command) @@ -48,14 +70,27 @@ void ListenerClientThread(void* tdParam, OrbisNetId Sock) SendLibraryList(Sock); // Really Only needed for the path. break; + case GIPC_LIB_LOAD: + case GIPC_LIB_UNLOAD: + + LoadUnloadLib(Command, Sock); + + break; + case GIPC_JAILBREAK: - //sys_sdk_jailbreak(&JailBackup); // Could just use libjbc - SockSendInt(Sock, GIPC_OK); + + Jailbreak(); + + Sockets::SendInt(Sock, GIPC_OK); + break; case GIPC_JAIL: - //sys_sdk_unjailbreak(&JailBackup); // Could just use libjbc - SockSendInt(Sock, GIPC_OK); + + RestoreJail(); + + Sockets::SendInt(Sock, GIPC_OK); + break; case GIPC_RW: @@ -75,16 +110,15 @@ extern "C" { klog("Hello from Helper!\n"); - char ProcName[0x20]; - sceKernelGetProcessName(getpid(), ProcName); - - klog("Helping with %s\n", ProcName); + klog("Helping with %d\n", getpid()); char serverAddress[0x200]; - snprintf(serverAddress, sizeof(serverAddress), GENERAL_IPC_ADDR, ProcName); + snprintf(serverAddress, sizeof(serverAddress), GENERAL_IPC_ADDR, getpid()); LocalListener = new LocalSocketListener(ListenerClientThread, nullptr, serverAddress); + klog("Helper Init Complete.\n"); + return 0; } diff --git a/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.vcxproj b/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.vcxproj index eabde7d..8e072ec 100644 --- a/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.vcxproj +++ b/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.vcxproj @@ -68,6 +68,7 @@ del /s /q /f $(IntDir)\*.oelf + @@ -75,6 +76,7 @@ del /s /q /f $(IntDir)\*.oelf + diff --git a/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.vcxproj.filters b/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.vcxproj.filters index de51d8d..824c83c 100644 --- a/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.vcxproj.filters +++ b/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.vcxproj.filters @@ -9,26 +9,31 @@ {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;ipp;xsd - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {c3adf471-ac5e-4e6e-a359-e08060b8cec1} + + + {9efcd69e-6e69-4ace-a1dd-36024540ec2a} Source Files - - Source Files - - Source Files + Source Files\Utilities - - Source Files + + Source Files\Utilities - Source Files + Source Files\Utilities + + + Source Files\Utilities + + + Source Files\Utilities @@ -38,20 +43,23 @@ Header Files - - Header Files - - Header Files - - - Header Files - - - Header Files + Header Files\Utilities - Header Files + Header Files\Utilities + + + Header Files\Utilities + + + Header Files\Utilities + + + Header Files\Utilities + + + Header Files\Utilities \ No newline at end of file diff --git a/Playstation/OrbisLibGeneralHelper/Socket.cpp b/Playstation/OrbisLibGeneralHelper/Socket.cpp new file mode 100644 index 0000000..dcc920d --- /dev/null +++ b/Playstation/OrbisLibGeneralHelper/Socket.cpp @@ -0,0 +1,36 @@ +#include "Common.h" +#include "Sockets.h" + +bool Sockets::SendInt(OrbisNetId Sock, int val) +{ + return !(sceNetSend(Sock, &val, sizeof(int), 0) < 0); +} + +bool Sockets::RecvInt(OrbisNetId Sock, int* val) +{ + return !(sceNetRecv(Sock, val, sizeof(int), 0) < 0); +} + +bool Sockets::SendLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen) +{ + unsigned char* CurrentPosition = data; + size_t DataLeft = dataLen; + int res = 0; + + while (DataLeft > 0) + { + size_t DataChunkSize = std::min((size_t)8192, DataLeft); + + res = sceNetSend(Sock, CurrentPosition, DataChunkSize, 0); + + if (res < 0) + { + return false; + } + + DataLeft -= res; + CurrentPosition += res; + } + + return true; +} \ No newline at end of file diff --git a/Playstation/OrbisLibGeneralHelper/Sockets.h b/Playstation/OrbisLibGeneralHelper/Sockets.h new file mode 100644 index 0000000..d31075d --- /dev/null +++ b/Playstation/OrbisLibGeneralHelper/Sockets.h @@ -0,0 +1,12 @@ +#pragma once + +class Sockets +{ +public: + static bool SendInt(OrbisNetId Sock, int val); + static bool RecvInt(OrbisNetId Sock, int* val); + static bool SendLargeData(OrbisNetId Sock, unsigned char* data, size_t dataLen); + +private: + +}; diff --git a/Playstation/OrbisLibGeneralHelper/Utilities.cpp b/Playstation/OrbisLibGeneralHelper/Utilities.cpp index fd62530..4706eca 100644 --- a/Playstation/OrbisLibGeneralHelper/Utilities.cpp +++ b/Playstation/OrbisLibGeneralHelper/Utilities.cpp @@ -19,25 +19,30 @@ void klog(const char* fmt, ...) sceKernelDebugOutText(0, Buffer2); } -bool SockSendInt(OrbisNetId Sock, int val) -{ - return !(sceNetSend(Sock, &val, sizeof(int), 0) < 0); -} +jbc_cred BackupCred; +bool Jailbroken = false; -bool SockRecvInt(OrbisNetId Sock, int* val) +void Jailbreak() { - return !(sceNetRecv(Sock, val, sizeof(int), 0) < 0); -} - -int RecieveInt(OrbisNetId Sock) -{ - int Int = 0; - if (sceNetRecv(Sock, &Int, sizeof(int), 0) < 0) + if (!Jailbroken) { - SockSendInt(Sock, GIPC_FAIL); - return 0; - } + jbc_get_cred(&BackupCred); - SockSendInt(Sock, GIPC_OK); - return Int; + jbc_cred jbCred; + jbc_get_cred(&jbCred); + + jbc_jailbreak_cred(&jbCred); + + jbc_set_cred(&jbCred); + + Jailbroken = true; + } +} + +void RestoreJail() +{ + if (Jailbroken) + { + jbc_set_cred(&BackupCred); + } } \ No newline at end of file diff --git a/Playstation/OrbisLibGeneralHelper/Utilities.h b/Playstation/OrbisLibGeneralHelper/Utilities.h index 0e95167..1eb4871 100644 --- a/Playstation/OrbisLibGeneralHelper/Utilities.h +++ b/Playstation/OrbisLibGeneralHelper/Utilities.h @@ -2,24 +2,5 @@ // Misc void klog(const char* fmt, ...); - -// Networking -bool SockSendInt(OrbisNetId Sock, int val); -bool SockRecvInt(OrbisNetId Sock, int* val); -int RecieveInt(OrbisNetId Sock); - -template T* RecievePacket(OrbisNetId Sock) -{ - auto Packet = (T*)malloc(sizeof(T)); - - if (sceNetRecv(Sock, Packet, sizeof(T), 0) < 0) - { - SockSendInt(Sock, GIPC_FAIL); - free(Packet); - return nullptr; - } - - SockSendInt(Sock, GIPC_OK); - - return Packet; -} \ No newline at end of file +void Jailbreak(); +void RestoreJail(); \ No newline at end of file diff --git a/Playstation/OrbisLibGeneralHelper/build.bat b/Playstation/OrbisLibGeneralHelper/build.bat index e6465e7..3357b63 100644 --- a/Playstation/OrbisLibGeneralHelper/build.bat +++ b/Playstation/OrbisLibGeneralHelper/build.bat @@ -48,7 +48,7 @@ copy "%outputPrx%" "%outputPath%\Playstation\Build\pkg\Orbis Suite\%targetname%. del "%outputPrx%" REM Generate the script. Will overwrite any existing temp.txt -echo open 1.1.0.13 2121> temp.txt +echo open 1.1.0.15 2121> temp.txt echo anonymous>> temp.txt echo anonymous>> temp.txt echo cd "/data/Orbis Suite/">> temp.txt diff --git a/Playstation/OrbisToolbox-2.0/Version.h b/Playstation/OrbisToolbox-2.0/Version.h index 0eb6db9..3d95a08 100644 --- a/Playstation/OrbisToolbox-2.0/Version.h +++ b/Playstation/OrbisToolbox-2.0/Version.h @@ -1,11 +1,11 @@ -#pragma once -#define ORBIS_TOOLBOX_MAJOR 2 -#define ORBIS_TOOLBOX_MINOR 0 -#define ORBIS_TOOLBOX_BUILDVERSION 324 -#define stringify(a) stringify_(a) -#define stringify_(a) #a -#if defined(ORBIS_TOOLBOX_DEBUG) -#define ORBIS_TOOLBOX_BUILDSTRING ("[Orbis Toolbox " stringify(ORBIS_TOOLBOX_MAJOR) "." stringify(ORBIS_TOOLBOX_MINOR) "] Dev Build " stringify(ORBIS_TOOLBOX_BUILDVERSION) " " __DATE__ " " __TIME__) -#else -#define ORBIS_TOOLBOX_BUILDSTRING ("[Orbis Toolbox " stringify(ORBIS_TOOLBOX_MAJOR) "." stringify(ORBIS_TOOLBOX_MINOR) "] Build " stringify(ORBIS_TOOLBOX_BUILDVERSION) " " __DATE__ " " __TIME__) -#endif +#pragma once +#define ORBIS_TOOLBOX_MAJOR 2 +#define ORBIS_TOOLBOX_MINOR 0 +#define ORBIS_TOOLBOX_BUILDVERSION 325 +#define stringify(a) stringify_(a) +#define stringify_(a) #a +#if defined(ORBIS_TOOLBOX_DEBUG) +#define ORBIS_TOOLBOX_BUILDSTRING ("[Orbis Toolbox " stringify(ORBIS_TOOLBOX_MAJOR) "." stringify(ORBIS_TOOLBOX_MINOR) "] Dev Build " stringify(ORBIS_TOOLBOX_BUILDVERSION) " " __DATE__ " " __TIME__) +#else +#define ORBIS_TOOLBOX_BUILDSTRING ("[Orbis Toolbox " stringify(ORBIS_TOOLBOX_MAJOR) "." stringify(ORBIS_TOOLBOX_MINOR) "] Build " stringify(ORBIS_TOOLBOX_BUILDVERSION) " " __DATE__ " " __TIME__) +#endif diff --git a/Playstation/OrbisToolbox-2.0/build.bat b/Playstation/OrbisToolbox-2.0/build.bat index 5c610ab..7b53847 100644 --- a/Playstation/OrbisToolbox-2.0/build.bat +++ b/Playstation/OrbisToolbox-2.0/build.bat @@ -48,7 +48,7 @@ copy "%outputPrx%" "%outputPath%\Playstation\Build\pkg\Orbis Toolbox\%targetname del "%outputPrx%" REM Generate the script. Will overwrite any existing temp.txt -echo open 1.1.0.79 2121> temp.txt +echo open 1.1.0.15 2121> temp.txt echo anonymous>> temp.txt echo anonymous>> temp.txt echo cd "/data/Orbis Toolbox/">> temp.txt diff --git a/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs b/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs index 265f696..230213a 100644 --- a/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs +++ b/Windows/Libraries/OrbisLib2/Common/API/APIPackets.cs @@ -55,10 +55,10 @@ namespace OrbisLib2.Common.API API_DBG_SET_DBGREG, /* Remote Library functions */ - API_DBG_LOAD_SPRX, - API_DBG_UNLOAD_SPRX, - API_DBG_RELOAD_SPRX, - API_DBG_MODULE_LIST, + API_DBG_LOAD_LIBRARY, + API_DBG_UNLOAD_LIBRARY, + API_DBG_RELOAD_LIBRARY, + API_DBG_LIBRARY_LIST, /* Thread Management */ API_DBG_THREAD_LIST, @@ -191,35 +191,41 @@ namespace OrbisLib2.Common.API #region Debug [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)] + public struct SegmentInfo + { + public ulong baseAddr; + public uint size; + public int prot; + } + + [StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Ansi)] public struct LibraryPacket { - public Int64 Handle; + public long Handle; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string Path; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + public int SegmentCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public SegmentInfo[] Segments; } [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)] - public struct ProcRWPacket + public struct DbgRWPacket { public UInt64 Address; public UInt64 Length; } [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)] - public struct ProcSPRXPacket + public struct DbgSPRXPacket { - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] - public string Name; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string Path; - public int ModuleHandle; - public int Flags; + public int Handle; } [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)] - public struct ProcBreakpointPacket + public struct DbgBreakpointPacket { public int Index; public UInt64 Address; @@ -234,14 +240,6 @@ namespace OrbisLib2.Common.API #region Target - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)] - public struct SegmentInfo - { - public UInt64 baseAddr; - public uint size; - public int prot; - } - public enum ConsoleTypes { UNK, diff --git a/Windows/Libraries/OrbisLib2/Common/Helpers/Sockets.cs b/Windows/Libraries/OrbisLib2/Common/Helpers/Sockets.cs index 2f3a884..c2e18e1 100644 --- a/Windows/Libraries/OrbisLib2/Common/Helpers/Sockets.cs +++ b/Windows/Libraries/OrbisLib2/Common/Helpers/Sockets.cs @@ -13,16 +13,23 @@ namespace OrbisLib2.Common.Helpers /// The data to be recieved. public static void RecvLarge(this Socket s, byte[] data) { - int Left = data.Length; - int Received = 0; - - while (Left > 0) + try { - var chunkSize = Math.Min(s.ReceiveBufferSize, Left); - var res = s.Receive(data, Received, chunkSize, 0); + int Left = data.Length; + int Received = 0; - Received += res; - Left -= res; + while (Left > 0) + { + var chunkSize = Math.Min(s.ReceiveBufferSize, Left); + var res = s.Receive(data, Received, chunkSize, 0); + + Received += res; + Left -= res; + } + } + catch(Exception ex) + { + Console.WriteLine(ex.Message); } } diff --git a/Windows/Libraries/OrbisLib2/Dialog/SelectProcess.xaml.cs b/Windows/Libraries/OrbisLib2/Dialog/SelectProcess.xaml.cs index eda262a..b8ed5d5 100644 --- a/Windows/Libraries/OrbisLib2/Dialog/SelectProcess.xaml.cs +++ b/Windows/Libraries/OrbisLib2/Dialog/SelectProcess.xaml.cs @@ -27,8 +27,7 @@ namespace OrbisLib2.Dialog var selectedProc = (ProcInfo)dlg.ProcessList.SelectedItem; if(selectedProc != null) { - // TODO: Handle Attach here. - Console.WriteLine($"Attaching to {selectedProc.Name}"); + TargetManager.SelectedTarget.Debug.Attach(selectedProc.ProcessId); } return dlg.Result; diff --git a/Windows/Libraries/OrbisLib2/Targets/Debug.cs b/Windows/Libraries/OrbisLib2/Targets/Debug.cs new file mode 100644 index 0000000..032e62f --- /dev/null +++ b/Windows/Libraries/OrbisLib2/Targets/Debug.cs @@ -0,0 +1,202 @@ +using OrbisLib2.Common.API; +using OrbisLib2.Common.Helpers; +using System; +using System.Collections.Generic; +using System.Data.Entity.Core.Metadata.Edm; +using System.Linq; +using System.Net.Sockets; +using System.Reflection.Metadata; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using static SQLite.SQLite3; + +namespace OrbisLib2.Targets +{ + public record SegmentInfo(ulong Address, uint Size, int Protection); + + public record LibraryInfo(long Handle, string Path, SegmentInfo[] Segments); + + public class Debug + { + private Target Target; + + public Debug(Target Target) + { + this.Target = Target; + } + + public bool IsDebugging + { + get { return GetCurrentProcessId() != -1; } + } + + public bool Attach(int pid) + { + var result = API.SendCommand(Target, 3, APICommands.API_DBG_ATTACH, (Socket Sock, APIResults Result) => + { + Sock.SendInt32(pid); + + var res = Sock.RecvInt32(); + + if (res == 1) + Result = APIResults.API_OK; + else + Result = APIResults.API_ERROR_GENERAL; + }); + + return result == APIResults.API_OK; + } + + // TODO: We probably want to detach when our program is exiting. + public bool Detach() + { + if(!IsDebugging) + { + return false; + } + + var result = API.SendCommand(Target, 3, APICommands.API_DBG_DETACH, (Socket Sock, APIResults Result) => + { + var res = Sock.RecvInt32(); + + if (res == 1) + Result = APIResults.API_OK; + else + Result = APIResults.API_ERROR_GENERAL; + }); + + return result == APIResults.API_OK; + } + + public int GetCurrentProcessId() + { + var currentPid = -1; + var result = API.SendCommand(Target, 3, APICommands.API_DBG_GET_CURRENT, (Socket Sock, APIResults Result) => + { + currentPid = Sock.RecvInt32(); + }); + + return result == APIResults.API_OK ? currentPid : -1; + } + + public int LoadLibrary(string Path) + { + int loadResult = 0; + var result = API.SendCommand(Target, 3, APICommands.API_DBG_LOAD_LIBRARY, (Socket Sock, APIResults Result) => + { + var isDebugging = Sock.RecvInt32(); + if(isDebugging == 1) + { + var Packet = new DbgSPRXPacket(); + Packet.Path = Path; + Sock.Send(Helper.StructToBytes(Packet)); + + loadResult = Sock.RecvInt32(); + } + }); + + return result == APIResults.API_OK ? loadResult : -1; + } + + public bool UnloadLibrary(int Handle) + { + if (!IsDebugging) + { + return false; + } + + int loadResult = 0; + var result = API.SendCommand(Target, 3, APICommands.API_DBG_UNLOAD_LIBRARY, (Socket Sock, APIResults Result) => + { + var isDebugging = Sock.RecvInt32(); + if (isDebugging == 1) + { + var Packet = new DbgSPRXPacket(); + Packet.Handle = Handle; + Sock.Send(Helper.StructToBytes(Packet)); + + loadResult = Sock.RecvInt32(); + } + }); + + return result == APIResults.API_OK ? (loadResult == 0) : false; + } + + public int ReloadLibrary(int Handle, string Path) + { + if (!IsDebugging) + { + return -1; + } + + int loadResult = 0; + var result = API.SendCommand(Target, 3, APICommands.API_DBG_RELOAD_LIBRARY, (Socket Sock, APIResults Result) => + { + var isDebugging = Sock.RecvInt32(); + if (isDebugging == 1) + { + var Packet = new DbgSPRXPacket(); + Packet.Handle = Handle; + Packet.Path = Path; + Sock.Send(Helper.StructToBytes(Packet)); + + loadResult = Sock.RecvInt32(); + } + }); + + return result == APIResults.API_OK ? loadResult : -1; + } + + public List GetLibraries() + { + var libraryList = new List(); + + if (!IsDebugging) + { + return libraryList; + } + + var result = API.SendCommand(Target, 6, APICommands.API_DBG_LIBRARY_LIST, (Socket Sock, APIResults Result) => + { + var isDebugging = Sock.RecvInt32(); + if (isDebugging == 1) + { + var libraryCount = Sock.RecvInt32(); + + // Recieve all of the arrary as one large packet. + var dataSize = libraryCount * Marshal.SizeOf(typeof(LibraryPacket)); + var data = new byte[dataSize]; + Sock.RecvLarge(data); + + // Allocate and copy the packet to begin marshaling it. + IntPtr ptr = Marshal.AllocHGlobal(dataSize); + Marshal.Copy(data, 0, ptr, dataSize); + + for (int i = 0; i < libraryCount; i++) + { + // Marshal each part of the buffer to a struct. + var Packet = new LibraryPacket(); + Packet = (LibraryPacket)Marshal.PtrToStructure(IntPtr.Add(ptr, i * Marshal.SizeOf(typeof(LibraryPacket))), typeof(LibraryPacket)); + + if (Packet.SegmentCount > 4 || Packet.SegmentCount < 0) + Packet.SegmentCount = 4; + + var segments = new SegmentInfo[Packet.SegmentCount]; + for (int j = 0; j < Packet.SegmentCount; j++) + { + segments[j] = new SegmentInfo(Packet.Segments[j].baseAddr, Packet.Segments[j].size, Packet.Segments[j].prot); + } + + libraryList.Add(new LibraryInfo(Packet.Handle, Packet.Path, segments)); + } + + Marshal.FreeHGlobal(ptr); + } + }); + + return libraryList; + } + } +} diff --git a/Windows/Libraries/OrbisLib2/Targets/Target.cs b/Windows/Libraries/OrbisLib2/Targets/Target.cs index 2ba89a7..2f58edf 100644 --- a/Windows/Libraries/OrbisLib2/Targets/Target.cs +++ b/Windows/Libraries/OrbisLib2/Targets/Target.cs @@ -81,7 +81,7 @@ namespace OrbisLib2.Targets } public TargetEvents Events; - // public Debug Debug; + public Debug Debug; public Payload Payload; public Process Process; public FTP FTP; @@ -92,7 +92,7 @@ namespace OrbisLib2.Targets _SavedTargetId = SavedTarget.Id; Events = new TargetEvents(this); - // Debug = new Debug(this); + Debug = new Debug(this); Payload = new Payload(this); Process = new Process(this); FTP = new FTP(this); diff --git a/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml b/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml index 768a44b..2a2a245 100644 --- a/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml +++ b/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml @@ -6,12 +6,18 @@ xmlns:local="clr-namespace:OrbisLibraryManager" xmlns:simpleControls="clr-namespace:SimpleUI.Controls;assembly=SimpleUI" xmlns:controls="clr-namespace:OrbisLibraryManager.Controls" + xmlns:valueConverters="clr-namespace:OrbisLibraryManager.ValueConverters" mc:Ignorable="d" Title="LibraryManager" Height="640" Width="980" MinHeight="640" MinWidth="980" MaxHeight="640" MaxWidth="980" ResizeMode="CanMinimize"> + + + + + @@ -118,7 +124,8 @@ Height="25" ToolTip="Detach the current attached process" ImageSource="/OrbisLibraryManager;component/Images/Detached.png" - ImageMargin="2"/> + ImageMargin="2" + Click="DetachProcess_Click"/> - - - + + + - + diff --git a/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml.cs b/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml.cs index 21753a7..4e0d97e 100644 --- a/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml.cs +++ b/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml.cs @@ -1,6 +1,7 @@ using OrbisLib2.Common.Dispatcher; using OrbisLib2.Targets; using SimpleUI.Controls; +using System.Threading.Tasks; using System.Windows; namespace OrbisLibraryManager @@ -16,9 +17,43 @@ namespace OrbisLibraryManager DispatcherClient.Subscribe(); } + private void RefreshLibraryList() + { + Task.Run(() => + { + var libraryList = TargetManager.SelectedTarget.Debug.GetLibraries(); + + if (libraryList != null && libraryList.Count > 0) + { + Dispatcher.Invoke(() => + { + LibraryList.ItemsSource = libraryList; + LibraryList.Items.Refresh(); + }); + } + else + { + Dispatcher.Invoke(() => + { + LibraryList.ItemsSource = null; + }); + } + }); + } + private void AttachProcess_Click(object sender, RoutedEventArgs e) { OrbisLib2.Dialog.SelectProcess.ShowDialog(GetWindow(this)); } + + private void DetachProcess_Click(object sender, RoutedEventArgs e) + { + TargetManager.SelectedTarget.Debug.Detach(); + } + + private void Refresh_Click(object sender, RoutedEventArgs e) + { + RefreshLibraryList(); + } } } diff --git a/Windows/OrbisLibraryManager/ValueConverters/PathNameConverter.cs b/Windows/OrbisLibraryManager/ValueConverters/PathNameConverter.cs new file mode 100644 index 0000000..7609b0b --- /dev/null +++ b/Windows/OrbisLibraryManager/ValueConverters/PathNameConverter.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; + +namespace OrbisLibraryManager.ValueConverters +{ + public class PathNameConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (string.IsNullOrEmpty((string)value)) + { + return string.Empty; + } + + return Path.GetFileName((string)value); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return (string)value; + } + } +} diff --git a/Windows/OrbisLibraryManager/ValueConverters/SegmentConverter.cs b/Windows/OrbisLibraryManager/ValueConverters/SegmentConverter.cs new file mode 100644 index 0000000..bbc9077 --- /dev/null +++ b/Windows/OrbisLibraryManager/ValueConverters/SegmentConverter.cs @@ -0,0 +1,34 @@ +using OrbisLib2.Targets; +using System; +using System.Globalization; +using System.Linq; +using System.Windows.Data; + +namespace OrbisLibraryManager.ValueConverters +{ + public class SegmentConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var outputStr = string.Empty; + var segments = value as SegmentInfo[]; + if(segments != null) + { + foreach (var segment in segments) + { + if(segment.Address > 0 && segment.Size > 0) + { + outputStr += $"0x{segment.Address.ToString("X")}({segment.Size}) "; + } + } + } + + return string.IsNullOrEmpty(outputStr) ? "-" : outputStr; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return new SegmentInfo[0]; + } + } +} diff --git a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt index c9db241..2612554 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt @@ -1 +1 @@ -2227 +2313 diff --git a/Windows/OrbisNeighborHood/Resources/BuildString.txt b/Windows/OrbisNeighborHood/Resources/BuildString.txt index 984058a..283a30e 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildString.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildString.txt @@ -1 +1 @@ -Version 3.0.2227 Debug Build Sunday January 01 2023 9:57 PM +Version 3.0.2313 Debug Build Wednesday January 04 2023 8:32 PM