Advertisement
Al-Azif

RemotePlayEnabler.cpp

Sep 25th, 2020 (edited)
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.39 KB | None | 0 0
  1. // This is an open source non-commercial project. Dear PVS-Studio, please check it.
  2. // PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com
  3.  
  4. #include "RemotePlayEnabler.hpp"
  5. #include <Utils/Kdlsym.hpp>
  6. #include <Utils/Logger.hpp>
  7.  
  8. #include <Mira.hpp>
  9. #include <OrbisOS/Utilities.hpp>
  10.  
  11. extern "C"
  12. {
  13.     #include <sys/mman.h>
  14.     #include <sys/eventhandler.h>
  15. };
  16.  
  17. using namespace Mira::Plugins;
  18. using namespace Mira::OrbisOS;
  19.  
  20. RemotePlayEnabler::RemotePlayEnabler() :
  21.     m_processStartEvent(nullptr),
  22.     m_resumeEvent(nullptr)
  23. {
  24.  
  25. }
  26.  
  27. RemotePlayEnabler::~RemotePlayEnabler()
  28. {
  29.  
  30. }
  31.  
  32. void RemotePlayEnabler::ProcessStartEvent(void *arg, struct ::proc *p)
  33. {
  34.     auto strncmp = (int(*)(const char *, const char *, size_t))kdlsym(strncmp);
  35.  
  36.     if (!p)
  37.         return;
  38.  
  39.     char* s_TitleId = (char*)((uint64_t)p + 0x390);
  40.  
  41.     WriteLog(LL_Debug, "Title ID: %s", s_TitleId);
  42.     WriteLog(LL_Debug, "Process Name: %s", p->p_comm);
  43.     WriteLog(LL_Debug, "ELF Path: %s", p->p_elfpath);
  44.     WriteLog(LL_Debug, "------------------------------------------------------");
  45.  
  46.     if (strncmp(s_TitleId, "NPXS20001", 9) == 0) // && strncmp("SceShellUI", p->p_comm, 10) == 0)
  47.         ShellUIPatch();
  48.  
  49.     if (strncmp(s_TitleId, "NPXS21006", 9) == 0) // && strncmp("SceRemotePlay", p->p_comm, 13) == 0)
  50.         RemotePlayPatch();
  51.  
  52.     return;
  53. }
  54.  
  55. void RemotePlayEnabler::ResumeEvent()
  56. {
  57.     ShellUIPatch();
  58.     RemotePlayPatch();
  59.     WriteLog(LL_Debug, "InstallEventHandlers finished");
  60.     return;
  61. }
  62.  
  63. bool RemotePlayEnabler::ShellUIPatch()
  64. {
  65.     WriteLog(LL_Debug, "patching SceShellUI");
  66.  
  67.     struct ::proc* s_Process = Utilities::FindProcessByName("SceShellUI");
  68.     if (s_Process == nullptr)
  69.     {
  70.         WriteLog(LL_Error, "could not find SceShellUI");
  71.         return false;
  72.     }
  73.  
  74.     ProcVmMapEntry* s_Entries = nullptr;
  75.     size_t s_NumEntries = 0;
  76.     auto s_Ret = Utilities::GetProcessVmMap(s_Process, &s_Entries, &s_NumEntries);
  77.     if (s_Ret < 0)
  78.     {
  79.         WriteLog(LL_Error, "could not get vm map");
  80.         return false;
  81.     }
  82.  
  83.     if (s_Entries == nullptr || s_NumEntries == 0)
  84.     {
  85.         WriteLog(LL_Error, "invalid entries (%p) or numEntries (%d)", s_Entries, s_NumEntries);
  86.         return false;
  87.     }
  88.  
  89.     uint8_t* s_ShellUITextStart = nullptr;
  90.     for (auto i = 0; i < s_NumEntries; ++i)
  91.     {
  92.         if (!memcmp(s_Entries[i].name, "executable", 10) && s_Entries[i].prot >= (PROT_READ | PROT_EXEC))
  93.         {
  94.             s_ShellUITextStart = (uint8_t*)s_Entries[i].start;
  95.             break;
  96.         }
  97.     }
  98.  
  99.     if (s_ShellUITextStart == nullptr)
  100.     {
  101.         WriteLog(LL_Error, "could not find SceShellUI text start");
  102.         return false;
  103.     }
  104.  
  105.     WriteLog(LL_Debug, "SceShellUI .text: (%p)", s_ShellUITextStart);
  106.  
  107.     uint8_t* s_ShellUIAppTextStart = nullptr;
  108.     for (auto i = 0; i < s_NumEntries; ++i)
  109.     {
  110. #if MIRA_PLATFORM < MIRA_PLATFORM_ORBIS_BSD_500
  111.         if (!memcmp(s_Entries[i].name, "libSceVsh_aot.sprx", 18) && s_Entries[i].prot >= (PROT_READ | PROT_EXEC))
  112.         {
  113.             s_ShellUIAppTextStart = (uint8_t*)s_Entries[i].start;
  114.             break;
  115.         }
  116. #else
  117.         if (!memcmp(s_Entries[i].name, "app.exe.sprx", 12) && s_Entries[i].prot >= (PROT_READ | PROT_EXEC))
  118.         {
  119.             s_ShellUIAppTextStart = (uint8_t*)s_Entries[i].start;
  120.             break;
  121.         }
  122. #endif
  123.     }
  124.  
  125.     if (s_ShellUIAppTextStart == nullptr)
  126.     {
  127.         WriteLog(LL_Error, "could not find SceShellUI App text start");
  128.         return false;
  129.     }
  130.  
  131.     WriteLog(LL_Debug, "SceShellUI App .text: (%p)", s_ShellUIAppTextStart);
  132.  
  133.     // Free the entries we got returned
  134.     delete [] s_Entries;
  135.     s_Entries = nullptr;
  136.  
  137.     // `/system_ex/app/NPXS20001/eboot.bin`
  138.     s_Ret = Utilities::ProcessReadWriteMemory(s_Process, (void*)(s_ShellUITextStart + ssu_CreateUserForIDU_patch), 4, (void*)"\x48\x31\xC0\xC3", nullptr, true);
  139.     if (s_Ret < 0)
  140.     {
  141.         WriteLog(LL_Error, "ssu_CreateUserForIDU_patch");
  142.         return false;
  143.     }
  144.  
  145. #if MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_405
  146.     // `/system_ex/app/NPXS20001/libSceVsh_aot.sprx`
  147.     s_Ret = Utilities::ProcessReadWriteMemory(s_Process, (void*)(s_ShellUIAppTextStart + ssu_remote_play_menu_patch), 5, (void*)"\xE9\x64\x02\x00\x00", nullptr, true);
  148. #elif MIRA_PLATFORM >= MIRA_PLATFORM_ORBIS_BSD_455 && MIRA_PLATFORM <= MIRA_PLATFORM_ORBIS_BSD_474
  149.     // `/system_ex/app/NPXS20001/libSceVsh_aot.sprx`
  150.     s_Ret = Utilities::ProcessReadWriteMemory(s_Process, (void*)(s_ShellUIAppTextStart + ssu_remote_play_menu_patch), 5, (void*)"\xE9\x22\x02\x00\x00", nullptr, true);
  151. #elif MIRA_PLATFORM >= MIRA_PLATFORM_ORBIS_BSD_500 && MIRA_PLATFORM <= MIRA_PLATFORM_ORBIS_BSD_507
  152.     // `/system_ex/app/NPXS20001/psm/Application/app.exe.sprx`
  153.     s_Ret = Utilities::ProcessReadWriteMemory(s_Process, (void*)(s_ShellUIAppTextStart + ssu_remote_play_menu_patch), 5, (void*)"\xE9\x82\x02\x00\x00", nullptr, true);
  154. #elif MIRA_PLATFORM >= MIRA_PLATFORM_ORBIS_BSD_555 && MIRA_PLATFORM <= MIRA_PLATFORM_ORBIS_BSD_620
  155.     // `/system_ex/app/NPXS20001/psm/Application/app.exe.sprx`
  156.     s_Ret = Utilities::ProcessReadWriteMemory(s_Process, (void*)(s_ShellUIAppTextStart + ssu_remote_play_menu_patch), 5, (void*)"\xE9\xB8\x02\x00\x00", nullptr, true);
  157. #elif MIRA_PLATFORM == MIRA_PLATFORM_ORBIS_BSD_672
  158.     // `/system_ex/app/NPXS20001/psm/Application/app.exe.sprx`
  159.     s_Ret = Utilities::ProcessReadWriteMemory(s_Process, (void*)(s_ShellUIAppTextStart + ssu_remote_play_menu_patch), 5, (void*)"\xE9\xBA\x02\x00\x00", nullptr, true);
  160. #else
  161.     s_Ret = -1;
  162. #endif
  163.     if (s_Ret < 0)
  164.     {
  165.         WriteLog(LL_Error, "ssu_remote_play_menu_patch");
  166.         return false;
  167.     }
  168.  
  169.     WriteLog(LL_Debug, "SceShellUI successfully patched");
  170.  
  171.     return true;
  172. }
  173.  
  174. bool RemotePlayEnabler::RemotePlayPatch()
  175. {
  176.     WriteLog(LL_Debug, "patching SceRemotePlay");
  177.  
  178.     struct ::proc* s_Process = Utilities::FindProcessByName("SceRemotePlay");
  179.     if (s_Process == nullptr)
  180.     {
  181.         WriteLog(LL_Error, "could not find SceRemotePlay");
  182.         return false;
  183.     }
  184.  
  185.     ProcVmMapEntry* s_Entries = nullptr;
  186.     size_t s_NumEntries = 0;
  187.     auto s_Ret = Utilities::GetProcessVmMap(s_Process, &s_Entries, &s_NumEntries);
  188.     if (s_Ret < 0)
  189.     {
  190.         WriteLog(LL_Error, "could not get vm map");
  191.         return false;
  192.     }
  193.  
  194.     if (s_Entries == nullptr || s_NumEntries == 0)
  195.     {
  196.         WriteLog(LL_Error, "invalid entries (%p) or numEntries (%d)", s_Entries, s_NumEntries);
  197.         return false;
  198.     }
  199.  
  200.     uint8_t* s_RemotePlayTextStart = nullptr;
  201.     for (auto i = 0; i < s_NumEntries; ++i)
  202.     {
  203.         if (!memcmp(s_Entries[i].name, "executable", 10) && s_Entries[i].prot >= (PROT_READ | PROT_EXEC))
  204.         {
  205.             s_RemotePlayTextStart = (uint8_t*)s_Entries[i].start;
  206.             break;
  207.         }
  208.     }
  209.  
  210.     if (s_RemotePlayTextStart == nullptr)
  211.     {
  212.         WriteLog(LL_Error, "could not find SceRemotePlay text start");
  213.         return false;
  214.     }
  215.  
  216.     WriteLog(LL_Debug, "SceRemotePlay .text: (%p)", s_RemotePlayTextStart);
  217.  
  218.     // Free the entries we got returned
  219.     delete [] s_Entries;
  220.     s_Entries = nullptr;
  221.  
  222.     // `/system/vsh/app/NPXS21006/eboot.bin`
  223.     s_Ret = Utilities::ProcessReadWriteMemory(s_Process, (void*)(s_RemotePlayTextStart + srp_enabler_patchA), 1, (void*)"\x01", nullptr, true);
  224.     if (s_Ret < 0)
  225.     {
  226.         WriteLog(LL_Error, "srp_enabler_patchA");
  227.         return false;
  228.     }
  229.  
  230.     // `/system/vsh/app/NPXS21006/eboot.bin`
  231.     s_Ret = Utilities::ProcessReadWriteMemory(s_Process, (void*)(s_RemotePlayTextStart + srp_enabler_patchB), 2, (void*)"\xEB\x1E", nullptr, true);
  232.     if (s_Ret < 0)
  233.     {
  234.         WriteLog(LL_Error, "srp_enabler_patchB");
  235.         return false;
  236.     }
  237.  
  238.     WriteLog(LL_Debug, "SceRemotePlay successfully patched");
  239.  
  240.     return true;
  241. }
  242.  
  243. bool RemotePlayEnabler::OnLoad()
  244. {
  245.     auto s_MainThread = Mira::Framework::GetFramework()->GetMainThread();
  246.     if (s_MainThread == nullptr)
  247.     {
  248.         WriteLog(LL_Error, "could not get main mira thread");
  249.         return false;
  250.     }
  251.  
  252.     // Initialize the event handlers
  253.     auto eventhandler_register = (eventhandler_tag(*)(struct eventhandler_list *list, const char *name, void *func, void *arg, int priority))kdlsym(eventhandler_register);
  254.  
  255.     m_processStartEvent = eventhandler_register(NULL, "process_exec_end", reinterpret_cast<void*>(RemotePlayEnabler::ProcessStartEvent), NULL, EVENTHANDLER_PRI_LAST);
  256.     m_resumeEvent = eventhandler_register(NULL, "system_resume_phase4", reinterpret_cast<void*>(RemotePlayEnabler::ResumeEvent), NULL, EVENTHANDLER_PRI_LAST);
  257.  
  258.     auto s_Ret = ShellUIPatch();
  259.     if (s_Ret == false)
  260.     {
  261.         WriteLog(LL_Error, "could not patch SceShellUI");
  262.         return false;
  263.     }
  264.  
  265.     s_Ret = RemotePlayPatch();
  266.     if (s_Ret == false)
  267.     {
  268.         WriteLog(LL_Error, "could not patch SceRemotePlay");
  269.         return false;
  270.     }
  271.  
  272.     return true;
  273. }
  274.  
  275. bool RemotePlayEnabler::OnUnload()
  276. {
  277.     return true;
  278. }
  279.  
  280. bool RemotePlayEnabler::OnSuspend()
  281. {
  282.     return true;
  283. }
  284.  
  285. bool RemotePlayEnabler::OnResume()
  286. {
  287.     return true;
  288. }
  289.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement