Advertisement
TheRouletteBoi

PS3 Hooking Methods and How to use them (LEGACY)

Jun 23rd, 2018 (edited)
597
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.92 KB | None | 0 0
  1. *****IMPORTANT*****
  2. *****SEE LINK FOR UPDATED HOOKING METHODS  https://pastebin.com/p7nKwnDx   *****
  3.  
  4.  
  5.  
  6. #include <ppu_asm_intrinsics.h> // __ALWAYS_INLINE
  7. #include <sys/process.h> // sys_process_getpid
  8.  
  9.  
  10. #define MARK_AS_EXECUTABLE __attribute__((section(".text")))
  11. #define GetRawDestination(type, destination) (type)*(type*)(destination)
  12. #define PROC_TOC              0x01C85330
  13.  
  14. struct opd_s
  15. {
  16.    uint32_t sub;
  17.    uint32_t toc;
  18. };
  19.  
  20. bool use_hen_syscalls = false;
  21.  
  22. uint32_t sys_dbg_write_process_memory(uint32_t pid, void* address, const void* data, size_t size)
  23. {
  24.     system_call_4(905, (uint64_t)pid, (uint64_t)address, (uint64_t)size, (uint64_t)data);
  25.     return_to_user_prog(uint32_t);
  26. }
  27.  
  28. uint32_t sys_hen_write_process_memory(uint32_t pid, void* address, const void* data, size_t size)
  29. {
  30.     system_call_6(8, 0x7777, 0x32, (uint64_t)pid, (uint64_t)address, (uint64_t)data, (uint64_t)size);
  31.     return_to_user_prog(uint32_t);
  32. }
  33.  
  34. uint32_t WriteProcessMemory(uint32_t pid, void* address, const void* data, size_t size)
  35. {
  36.     if (!use_hen_syscalls)
  37.     {
  38.         uint32_t write = sys_dbg_write_process_memory(pid, address, data, size);
  39.         if (write == SUCCEEDED)
  40.         {
  41.             return write;
  42.         }
  43.     }
  44.  
  45.     use_hen_syscalls = true;
  46.     return sys_hen_write_process_memory(pid, address, data, size);
  47. }
  48.  
  49. uint32_t GetCurrentToc()
  50. {
  51.    uint32_t* entry_point = *reinterpret_cast<uint32_t**>(0x1001C); // ElfHeader->e_entry
  52.    return entry_point[1];
  53. }
  54.  
  55. template <typename R>
  56. __ALWAYS_INLINE R(*GameCall(std::uint32_t addr, std::uint32_t toc = PROC_TOC))(...)
  57. {
  58.    volatile opd_s opd = { addr, toc };
  59.    R(*func)(...) = (R(*)(...))&opd;
  60.    return func;
  61. }
  62.  
  63. // when calling some game functions with GameCallV2 the game crashes in Minecraft PS3 Edition so use GameCall instead
  64. template <typename R, typename... TArgs>
  65. __ALWAYS_INLINE R GameCallV2(std::uint32_t addr, TArgs... args)
  66. {
  67.    volatile opd_s opd = { addr, PROC_TOC };
  68.    R(*func)(TArgs...) = (R(*)(TArgs...))&opd;
  69.    return func(args...);
  70. }
  71.  
  72. template <typename R>
  73. __ALWAYS_INLINE R(*VmtCall(std::uint32_t vmt, std::uint32_t offset))(...)
  74. {
  75.    std::uint32_t* funcAdr = (std::uint32_t*)(*(volatile std::uint32_t*)(vmt + offset));
  76.    volatile opd_s opd = { funcAdr[0], funcAdr[1] };
  77.    R(*func)(...) = (R(*)(...))&opd;
  78.    return func;
  79. }
  80.  
  81. template <typename var>
  82. bool write_mem(uint32_t address, var value)
  83. {
  84.    return (WriteProcessMemory(sys_process_getpid(), (void*)address, &value, sizeof(var)) == SUCCEEDED);
  85. }
  86.  
  87.  
  88. __attribute__((naked)) void _savegpr0_N()
  89. {
  90.    // https://pastebin.com/a7Ci8aAi
  91.    __asm
  92.    (
  93.       "std  %r14, -144(%r1);"         // _savegpr0_14
  94.       "std  %r15, -136(%r1);"         // _savegpr0_15
  95.       "std  %r16, -128(%r1);"         // _savegpr0_16
  96.       "std  %r17, -120(%r1);"         // _savegpr0_17
  97.       "std  %r18, -112(%r1);"         // _savegpr0_18
  98.       "std  %r19, -104(%r1);"         // _savegpr0_19
  99.       "std  %r20, -96(%r1);"          // _savegpr0_20
  100.       "std  %r21, -88(%r1);"          // _savegpr0_21
  101.       "std  %r22, -80(%r1);"          // _savegpr0_22
  102.       "std  %r23, -72(%r1);"          // _savegpr0_23
  103.       "std  %r24, -64(%r1);"          // _savegpr0_24
  104.       "std  %r25, -56(%r1);"          // _savegpr0_25
  105.       "std  %r26, -48(%r1);"          // _savegpr0_26
  106.       "std  %r27, -40(%r1);"          // _savegpr0_27
  107.       "std  %r28, -32(%r1);"          // _savegpr0_28
  108.       "std  %r29, -24(%r1);"          // _savegpr0_29
  109.       "std  %r30, -16(%r1);"          // _savegpr0_30
  110.       "std  %r31, -8(%r1);"           // _savegpr0_31
  111.       "std  %r0, 16(%r1);"
  112.       "blr;"
  113.    );
  114. }
  115.  
  116. uint32_t RelinkGPLR(uint32_t SFSOffset, uint32_t* SaveStubAddress, uint32_t* OriginalAddress)
  117. {
  118.     uint32_t Instruction = 0, Replacing;
  119.     uint32_t* Saver = *(uint32_t**)_savegpr0_N;
  120.  
  121.    if (SFSOffset & 0x2000000)
  122.       SFSOffset |= 0xFC000000;
  123.  
  124.    Replacing = OriginalAddress[SFSOffset / 4];
  125.  
  126.    for (int i = 0; i < 20; i++)
  127.    {
  128.       if (Replacing == Saver[i])
  129.       {
  130.          int NewOffset = (int)&Saver[i] - (int)SaveStubAddress;
  131.          Instruction = 0x48000001 | (NewOffset & 0x3FFFFFC);
  132.       }
  133.    }
  134.    return Instruction;
  135. }
  136.  
  137. void PatchInJump(uint32_t* address, uint32_t destination, bool linked)
  138. {
  139.     uint32_t inst_lis = 0x3D600000 + ((destination >> 16) & 0xFFFF); // lis %r11, dest>>16
  140.     write_mem<uint32_t>((uint32_t)&address[0], inst_lis);
  141.     if (destination & 0x8000)   // if bit 16 is 1
  142.         write_mem<uint32_t>((uint32_t)&address[0], inst_lis += 1);
  143.  
  144.     write_mem<uint32_t>((uint32_t)&address[1], 0x396B0000 + (destination & 0xFFFF)); // addi %r11, %r11, dest&OxFFFF
  145.     write_mem<uint32_t>((uint32_t)&address[2], 0x7D6903A6); // mtctr %r11
  146.     write_mem<uint32_t>((uint32_t)&address[3], 0x4E800420); // bctr
  147.     if (linked)
  148.         write_mem<uint32_t>((uint32_t)&address[3], 0x4E800421); // bctrl
  149.  
  150.     __dcbst(address);
  151.     __sync();
  152.     __isync();
  153. }
  154.  
  155. void HookFunctionStart(uint32_t* address, uint32_t destination, uint32_t* original)
  156. {
  157.     uint32_t addressRelocation = (uint32_t)(&address[4]); // Replacing 4 instructions with a jump, this is the stub return address
  158.  
  159.     // build the stub
  160.     // make a jump to go to the original function start+4 instructions
  161.     uint32_t inst_lis = 0x3D600000 + ((addressRelocation >> 16) & 0xFFFF); // lis r11, 0 | Load Immediate Shifted
  162.     write_mem<uint32_t>((uint32_t)&original[0], inst_lis);
  163.  
  164.     if (addressRelocation & 0x8000) // If bit 16 is 1
  165.         write_mem<uint32_t>((uint32_t)&original[0], inst_lis += 1); // lis r11, 0 | Load Immediate Shifted
  166.  
  167.     write_mem<uint32_t>((uint32_t)&original[1], 0x396B0000 + (addressRelocation & 0xFFFF)); // addi r11, r11, (value of AddressRelocation & 0xFFFF) | Add Immediate
  168.     write_mem<uint32_t>((uint32_t)&original[2], 0x7D6903A6); // mtspr CTR, r11 | Move to Special-Purpose Register CTR
  169.  
  170.     // Instructions [3] through [6] are replaced with the original instructions from the function hook
  171.     // Copy original instructions over, relink stack frame saves to local ones
  172.     for (int i = 0; i < 4; i++)
  173.     {
  174.         if ((address[i] & 0xF8000000) == 0x48000000) // branch with link
  175.         {
  176.             write_mem<uint32_t>((uint32_t)&original[i + 3], RelinkGPLR((address[i] & ~0x48000003), &original[i + 3], &address[i]));
  177.         }
  178.         else
  179.         {
  180.             write_mem<uint32_t>((uint32_t)&original[i + 3], address[i]);
  181.         }
  182.     }
  183.     write_mem<uint32_t>((uint32_t)&original[7], 0x4E800420); // bctr | Branch unconditionally
  184.  
  185.     __dcbst(original); // Data Cache Block Store | Allows a program to copy the contents of a modified block to main memory.
  186.     __sync(); // Synchronize | Ensure the dcbst instruction has completed.
  187.     __isync(); // Instruction Synchronize | Refetches any instructions that might have been fetched prior to this instruction.
  188.  
  189.     PatchInJump(address, *(uint32_t*)destination, false); // Redirect Function to ours
  190.  
  191.     /*
  192.     * So in the end, this will produce:
  193.     *
  194.     * lis r11, ((AddressRelocation >> 16) & 0xFFFF [+ 1])
  195.     * addi r11, r11, (AddressRelocation & 0xFFFF)
  196.     * mtspr CTR, r11
  197.     * branch (GPR)
  198.     * dcbst (SaveStub)
  199.     * sync
  200.     */
  201. }
  202.  
  203. #define MAX_HOOKFUNCTIONS_ASM_SIZE 300
  204. MARK_AS_EXECUTABLE uint8_t g_hookFunctionsAsm[300];
  205. int g_hookFunctionsAsmCount = 0;
  206.  
  207. bool HookFunctionStartAuto(uint32_t* address, uint32_t destination, uint32_t** original)
  208. {
  209.     // check for buffer overflow
  210.     if (g_hookFunctionsAsmCount > (MAX_HOOKFUNCTIONS_ASM_SIZE - 2))
  211.         return false;
  212.  
  213.     uint32_t* stubAddr = (uint32_t*)&g_hookFunctionsAsm[g_hookFunctionsAsmCount];
  214.  
  215.     HookFunctionStart(address, destination, stubAddr);
  216.  
  217.     // write an opd into memory
  218.     write_mem<uint64_t>((uint32_t)&stubAddr[8], ((uint64_t)stubAddr << 32) | GetCurrentToc()); // (uint32_t)__builtin_get_toc()
  219.     *original = &stubAddr[8];
  220.  
  221.     // Increment asm byte count
  222.     // 0x20 bytes from HookFunctionStart
  223.     // 0x8 bytes for opd
  224.     g_hookFunctionsAsmCount += 0x28;
  225.  
  226.     return true;
  227. }
  228.  
  229. void PatchInBranch(uint32_t* address, uint32_t destination, bool linked)
  230. {
  231.    destination = GetRawDestination(uint32_t, destination);
  232.    uint32_t inst_branch = 0x48000000 + ((destination - (uint32_t)address) & 0x3FFFFFF); // b Destination
  233.    write_mem<uint32_t>((uint32_t)&address[0], inst_branch);
  234.  
  235.    if (linked)
  236.       write_mem<uint32_t>((uint32_t)&address[0], inst_branch += 1); // bl Destination
  237. }
  238.  
  239. void PatchInVmt(uint32_t* address, uint32_t destination)
  240. {
  241.    write_mem<uint64_t>((uint32_t)&address[0], GetRawDestination(uint64_t, destination)); // uint64_t so it includes the toc
  242. }
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253. EXAMPLES:
  254.  
  255.  
  256.  
  257. // restore hook method
  258. #define GetLabelTextByGXTFn(gtxDictionary, gxtLabel) GameCall<const char*>(0xD914CC)(gtxDictionary, gxtLabel)
  259. char backup_GetLabelTextByGXT[16];
  260. const char* GetLabelTextByGXT(uint32_t gtxDictionary, const char* labelName)
  261. {
  262.    if (!strcmp(labelName, "LOADING_MPLAYER_L"))
  263.       return "Loading Online With Mod Menu";
  264.    else if (!strcmp(labelName, "LOADING_SPLAYER_L"))
  265.       return "Loading Story Mode With Mod Menu";
  266.  
  267.  
  268.     // backup hook, revert, call, hook
  269.     char backup_hook[16];
  270.     WriteProcessMemory(sys_process_getpid(), backup_hook, (const void *)0xD914CC, 16);
  271.     WriteProcessMemory(sys_process_getpid(), (void *)0xD914CC, backup_GetLabelTextByGXT, 16);
  272.     const char *ret = GetLabelTextByGXTFn(gtxDictionary, labelName);
  273.     WriteProcessMemory(sys_process_getpid(), (void *)0xD914CC, backup_hook, 16);
  274.     return ret;
  275. }
  276.  
  277. https://imgur.com/rGsg4iV
  278. WriteProcessMemory(sys_process_getpid(), backup_GetLabelTextByGXT, (const void *)0xD914CC, 16);
  279. PatchInJump((uint32_t*)0xD914CC, *(uint32_t*)GetLabelTextByGXT, false);
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287. // virtual table function method
  288. #define networkObjectMgr_HandleCloneRemoveFn(networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, objectId, bitFlags) GameCall<bool>(0x133DC5C)(networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, objectId, bitFlags)
  289. bool networkObjectMgr_HandleCloneRemove(uintptr_t networkObjectMgr, uintptr_t netGamePlayerClient, uintptr_t netGamePlayerSelf, uint16_t objectId, uint32_t bitFlags)
  290. {
  291.   printf("networkObjectMgr_HandleCloneRemove\n");
  292.   printf("netGamePlayerClient 0x%X\n", netGamePlayerClient);
  293.  
  294.  
  295.   return networkObjectMgr_HandleCloneRemoveFn(networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, objectId, bitFlags);
  296. }
  297.  
  298. https://imgur.com/ycGbthr
  299. PatchInVmt((uint32_t*)0x1C70800, (uint32_t)networkObjectMgr_HandleCloneRemove);
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308. // branch or mid function method
  309. #define netObjectMgrBase_GetNetworkObjectFn(cNetworkObjectMgr, id, evenIfDeleting) GameCall<uintptr_t>(0x9F8C38)(cNetworkObjectMgr, id, evenIfDeleting)
  310. #define netObjectMgrBase_RegisterNetworkObjectFn(netObjectMgr, netObject) GameCall<uint32_t>(0xA12890)(netObjectMgr, netObject)
  311.  
  312. void netObjectMgrBase_RegisterNetworkObject(uintptr_t networkObjectMgr, uintptr_t netObj)
  313. {
  314.    uintptr_t netObjPtr = netObjectMgrBase_GetNetworkObjectFn(networkObjectMgr, *(uint16_t*)(netObj + 0x6), 1);
  315.    if (netObjPtr)
  316.    {
  317.       uintptr_t vmt = *(uintptr_t*)(netObj);
  318.       VmtCall<void>(vmt, 0xC8)(netObj);
  319.  
  320.       printf("re registering existing network object\n");
  321.       return;
  322.    }
  323.  
  324.    netObjectMgrBase_RegisterNetworkObjectFn(networkObjectMgr, netObj);
  325. }
  326.  
  327. https://imgur.com/8sb4PwH
  328. PatchInBranch((uint32_t*)0x1339684, (uint32_t)netObjectMgrBase_RegisterNetworkObject, true);
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338. // hook functions with GPLR
  339. using parManager_LoadFromStructure_t = uint32_t(*)(uint32_t parStructureInstance, const char* filePath, const char* extension, uint32_t parStructure, uint32_t vars, uint32_t r8, uint32_t r9);
  340. parManager_LoadFromStructure_t parManager_LoadFromStructure_Original = nullptr;
  341.  
  342. uint32_t parManager_LoadFromStructure(uint32_t parStructureInstance, const char* filePath, const char* extension, uint32_t parStructure, uint32_t vars, uint32_t r8, uint32_t r9)
  343. {
  344.    printf("parManager_LoadFromStructure\n");
  345.    printf("filePath %s\n", filePath);
  346.  
  347.  
  348.    return parManager_LoadFromStructure_Original(parStructureInstance, filePath, extension, parStructure, vars, r8, r9);
  349. }
  350.  
  351. https://imgur.com/gigHt7F
  352. HookFunctionStartAuto((uint32_t*)0xAC709C, (uint32_t)parManager_LoadFromStructure, (uint32_t**)&parManager_LoadFromStructure_Original);
  353.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement