Advertisement
TheRouletteBoi

PS3 HookHandler

May 9th, 2021 (edited)
385
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 25.07 KB | None | 0 0
  1. reference https://pastebin.com/yezsesij (enstone hooking. scroll to the bottom)
  2. reference https://pastebin.com/RBYPZEb5 (original)
  3.  
  4. GOAL:
  5. - make a hooking method without the need of a stub. that way we can use it on HEN and hopefully in Kernel LV2
  6. - have the ability to hook functions with less than 4 instructions
  7.  
  8. TODO
  9. - change executable detour location from 0xA104E8 to 0x10000 (ELF segment) so it works on any game
  10. - get rid of empty memory addresses (0x10065600) and use the stack
  11. - get rid of redundant parameters
  12. - fix warnings
  13. - make into a class?
  14. - find a better way to using get "original"
  15. - use __builtin_return_address() to get LR
  16. - use __builtin_get_toc() to get r2
  17. - use __reg(3)  __reg(4)  ect.. to get registers
  18.  
  19.  
  20.  
  21.  
  22. ------------------------------------------------------------------------------------------------------------------------------------
  23. Revision #2 by TheRouLetteBoi
  24. - addded 2 examples
  25. - auto increment and find hooks using STL
  26. - clean up code so it is easier to understand
  27. - changed detour location to 0x10080 to support all games
  28. - renamed one_hook to HookHandler
  29. - remove PatchInJump
  30. - removed "some" not all redundant parameters
  31. - fixed warnings
  32.  
  33.  
  34. #undef vector
  35. #include <vector>
  36. #include <algorithm>
  37.  
  38. #define MAKE_JUMP(addr, to) *(uint32_t *)(addr) = (0x12 << 26) | ((((to-(addr))>>2)&0xFFFFFF) << 2)
  39. #define __NAKED __attribute__((naked))
  40.  
  41. using original_t = void(*)();
  42.  
  43. using hooked_t =
  44. uint64_t(*)(original_t,
  45.    uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
  46.    uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
  47.  
  48. struct hookCache
  49. {
  50.    uint32_t hookAddress;
  51.    uint32_t originalInstruction;
  52.    uint64_t functionCallback;
  53. };
  54.  
  55. std::vector<hookCache> hookList;
  56.  
  57. // three free memory locations (24 bytes)
  58. #define ONE_HOOK_LR *(uint32_t*)0x10065600
  59. #define ONE_HOOK_R2 *(uint32_t*)0x10065610
  60. #define ONE_HOOK_BRANCHDATA *(uint32_t*)0x10065608
  61.  
  62. // need to add another one of these functions if the function you are hooking does not start with one of these two instructions
  63. __NAKED void Stub_mflr_r0()
  64. {
  65.    __asm("mflr %r0");
  66.  
  67.    // can't put comments on the code below but it's grabbing the address to branch to and r2 and loading them up
  68.    __asm("lis %r11, 0x1006");
  69.    __asm("addi %r11, %r11, 0x5610");
  70.    __asm("lwz %r2, 0x0(%r11)");        // r2 = *(uint32_t*)(0x10065610)
  71.    __asm("lis %r11, 0x1006");
  72.    __asm("addi %r11, %r11, 0x5608");
  73.    __asm("lwz %r11, 0x0(%r11)");       // r11 = *(uint32_t*)(0x10065608)
  74.    __asm("mtctr %r11");
  75.    __asm("bctr");                      // jump_to r11
  76. }
  77.  
  78. __NAKED void Stub_r1_0x70()
  79. {
  80.    __asm("stdu %r1, -0x70(%r1)");
  81.  
  82.    // can't put comments on the code below but it's grabbing the address to branch to and r2 and loading them up
  83.    __asm("lis %r11, 0x1006");
  84.    __asm("addi %r11, %r11, 0x5610");
  85.    __asm("lwz %r2, 0x0(%r11)");        // r2 = *(uint32_t*)(0x10065610)
  86.    __asm("lis %r11, 0x1006");
  87.    __asm("addi %r11, %r11, 0x5608");
  88.    __asm("lwz %r11, 0x0(%r11)");       // r11 = *(uint32_t*)(0x10065608)
  89.    __asm("mtctr %r11");
  90.    __asm("bctr");                      // jump_to r11
  91. }
  92.  
  93. uint32_t ResolveBranch(uint32_t branchAddress)
  94. {
  95.    uint32_t instruction = *(uint32_t*)(branchAddress);
  96.    int32_t offset = instruction & 0x3FFFFFC;
  97.  
  98.    if (offset & (1 << 25))
  99.       offset |= ~0x03FFFFFF;
  100.  
  101.    return branchAddress + offset;
  102. }
  103.  
  104. uint64_t HookHandler(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9,
  105.    uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17,
  106.    uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21)
  107. {
  108.    uint32_t lr_val = ONE_HOOK_LR;
  109.  
  110.    printf("LR found: 0x%X\n", lr_val);
  111.  
  112.    uint32_t branched_from = lr_val - 0x4; // link register -0x4 is the branch command
  113.  
  114.    uint32_t hookedAddress = ResolveBranch(branched_from);
  115.    printf("hooked address discovered: 0x%X\n", hookedAddress);
  116.  
  117.    auto currentHook = std::find_if(hookList.begin(), hookList.end(), [&hookedAddress](const hookCache& cache)
  118.    {
  119.       return cache.hookAddress == hookedAddress;
  120.    });
  121.  
  122.    ONE_HOOK_BRANCHDATA = hookedAddress + 4; // go to the next instruction after it
  123.  
  124.    original_t original = nullptr;
  125.    uint64_t ret = 0;
  126.    if (hookList.end() != currentHook)
  127.    {
  128.       // find the original instruction depending on our hook
  129.  
  130.       if ((*currentHook).originalInstruction == 0x7C0802A6)       // mflr %r0
  131.          original = &Stub_mflr_r0;
  132.       else if ((*currentHook).originalInstruction == 0xF821FF91)  // stdu %r1, -0x70(%r1)
  133.          original = &Stub_r1_0x70;
  134.  
  135.       if (original != nullptr)
  136.       {
  137.          hooked_t func = (hooked_t)&(*currentHook).functionCallback;
  138.          ret = func(original, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21);
  139.       }
  140.    }
  141.  
  142.  
  143.    return ret;
  144. }
  145.  
  146. __NAKED void HookHandlerAsm()
  147. {
  148.    __asm("mflr %r0");//this will link back to the previous func
  149.    __asm("stdu %r1, -0x70(%r1)");
  150.    __asm("std %r0, 0x60(%r1)");
  151.  
  152.    //now locate the link register from the previous function
  153.    //branched to - branched from = dif (lower 26 bits of instruction)
  154.    //branched to = dif + branched from
  155.    __asm("lis %r11, 0x1006");//assume r11 is never used
  156.    __asm("addi %r11, %r11, 0x5600");//ONE_HOOK_LR
  157.    __asm("stw %r0, 0x0(%r11)");//stores the lr to get back to the original call point into the spot we like
  158.  
  159.    __asm("lis %r11, 0x1006");//assume r11 is never used
  160.    __asm("addi %r11, %r11, 0x5610");//ONE_HOOK_R2
  161.    __asm("stw %r2, 0x0(%r11)");//stores the r2 for us to reload later because it is used in many functions
  162.  
  163.    __asm("bl ._Z11HookHandleryyyyyyyyyyyyyyyyyyy");//if you get a linker error then it is probably because of this
  164.  
  165.    __asm("ld %r0, 0x60(%r1)");
  166.    __asm("mtlr %r0");//this will be the link register to the
  167.    __asm("addi %r1, %r1, 0x70");
  168.    __asm("blr");//goes all the way back to the function that called our hooked function
  169. }
  170.  
  171. void SetupHook(uint32_t fnAddress, uintptr_t fnCallback)
  172. {
  173.    uint32_t instructions[4]{};
  174.    instructions[0] = 0x3D600000 + ((fnCallback >> 16) & 0xFFFF);    // lis %r11, fnCallback@h
  175.    instructions[1] = 0x616B0000 + (fnCallback & 0xFFFF);            // ori %r11, %r11, fnCallback@l
  176.    instructions[2] = 0x7D6903A6;                                    // mtctr %r11
  177.    instructions[3] = 0x4E800420;                                    // bctr
  178.    WriteProcessMemory(sys_process_getpid(), (void*)fnAddress, instructions, sizeof(instructions));
  179. }
  180.  
  181. void InstallHook()
  182. {
  183.    SetupHook(0x10080, *(uintptr_t*)HookHandlerAsm);
  184. }
  185.  
  186. void AddToHandler(uint32_t fnAddress, uintptr_t fnCallback)
  187. {
  188.    hookList.push_back({
  189.       fnAddress,
  190.       *reinterpret_cast<uint32_t*>(fnAddress),
  191.       *reinterpret_cast<uint64_t*>(fnCallback)
  192.       });
  193.  
  194.    MAKE_JUMP(fnAddress, 0x10080);
  195. }
  196.  
  197.  
  198.  
  199.  
  200.  
  201. EXAMPLES
  202.  
  203. using GetLabelTextByHash_t = const char*(*)(uintptr_t labelHashMap, uint32_t labelHash, uintptr_t nameHash);
  204. const char* GetLabelTextByHashHook(GetLabelTextByHash_t original, uintptr_t labelHashMap, uint32_t labelHash, uintptr_t nameHash)
  205. {
  206.    if (labelHash == 0x478FDC87)
  207.       return "EPIC GAMER STYLE";
  208.  
  209.    return original(labelHashMap, labelHash, nameHash);
  210. }
  211.  
  212. using AssignPhysicalIndex_t = uintptr_t(*)(uintptr_t networkPlayerMgr, uintptr_t netGamePlayer, uint8_t index);
  213. uintptr_t AssignPhysicalIndexHook(AssignPhysicalIndex_t original, uintptr_t networkPlayerMgr, uintptr_t netGamePlayer, uint8_t index)
  214. {
  215.    printf("AssignPhysicalIndexHook\n");
  216.    printf("netGamePlayer 0x%X\n", netGamePlayer);
  217.  
  218.    return original(networkPlayerMgr, netGamePlayer, index);
  219. }
  220.  
  221. int main()
  222. {
  223.    InstallHook();
  224.  
  225.    // https://imgur.com/usuPNXK
  226.    AddToHandler(0xD91468, (uintptr_t)GetLabelTextByHashHook);
  227.  
  228.    // https://imgur.com/yMbnnDC
  229.    AddToHandler(0xA15618, (uintptr_t)AssignPhysicalIndexHook);
  230. }
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244. ------------------------------------------------------------------------------------------------------------------------------------
  245. Revision #1 by gopro2027
  246. - add "original" into function hook
  247. - fix branch instruction
  248.  
  249.  
  250.  
  251.  
  252. #define __NAKED __attribute__ ((naked)) __attribute__((noinline))
  253.  
  254. #define NUM_HOOKS 1
  255.  
  256. //three free memory locations (24 bytes)
  257. #define ONE_HOOK_LR *(unsigned int*)0x10065600
  258. #define ONE_HOOK_BRANCHDATA *(unsigned int*)0x10065608
  259. #define ONE_HOOK_R2 *(unsigned int*)0x10065610
  260.  
  261. typedef uint64_t(*one_hook_function_call)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
  262.  
  263. uint64_t one_hook_dummy_func(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) {
  264.     return 0;
  265. }
  266.  
  267. struct hook_pairs {
  268.     unsigned int hookaddress;
  269.     unsigned int firstinstruction;
  270.     unsigned int functionToCallInSprxOPD;
  271. };
  272.  
  273. hook_pairs one_hooks[NUM_HOOKS];
  274.  
  275. //can't put comments on the code below but it's grabbing the address to branch to and r2 and loading them up
  276. #define one_hook_stub \
  277.     __asm("lis %r11, 0x1006");\
  278.     __asm("addi %r11, %r11, 0x5610");\
  279.     __asm("lwz %r2, 0x0(%r11)");\
  280.     __asm("lis %r11, 0x1006");\
  281.     __asm("addi %r11, %r11, 0x5608");\
  282.     __asm("lwz %r11, 0x0(%r11)");\
  283.     __asm("mtctr %r11");\
  284.     __asm("bctr");//braches to hooked function
  285.  
  286.  
  287.  
  288. //need to add another one of these functions if the function you are hooking does not start with one of these two instructions
  289. __NAKED uint64_t one_hook_stub_mflrr0(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) {
  290.     __asm("mflr %r0");
  291.  
  292.     one_hook_stub;
  293. }
  294.  
  295. __NAKED uint64_t one_hook_stub_r170(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) {
  296.     __asm("stdu %r1, -0x70(%r1)");
  297.  
  298.     one_hook_stub;
  299. }
  300.  
  301.  
  302. int one_hook(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) {
  303.     unsigned int lr_val = ONE_HOOK_LR;
  304.  
  305.     printf("LR found: 0x%X\n",lr_val);
  306.  
  307.     unsigned int branched_from = ONE_HOOK_LR - 0x4;                     //link register -0x4 is the branch command
  308.     unsigned int dif = *(unsigned int*)(branched_from) & 0x3FFFFFF;     //getting the lower 26 bits of the branch command which is the offset
  309.     unsigned int extra = dif % 4;//should return 0, 1, 2, or 3          //extra will be 1 if bl command (should be)
  310.     dif = dif - extra;//now dif should be the proper dif                //subtract the link value (1) from the offset
  311.  
  312.     int check = dif >> 25;//check the very highest bit of the difference. If it is 1 then it is a negative value, so we extend it to 32 bits
  313.     if (check == 1) {
  314.         dif = dif | 0xFC000000;//extend the negative from 26 bits to 32 bits if it is negative
  315.     }
  316.  
  317.     unsigned int branched_to = dif + branched_from;
  318.    
  319.     unsigned int hooked_address = branched_to;
  320.     printf("hooked address discovered: 0x%X\n",hooked_address);
  321.    
  322.     int hookIndex = -1;
  323.     for (int i = 0; i < NUM_HOOKS; i++) {
  324.         if (one_hooks[i].hookaddress == hooked_address) {
  325.             hookIndex = i;
  326.         }
  327.     }
  328.  
  329.      
  330.     ONE_HOOK_BRANCHDATA = hooked_address + 4;//go to the next instruction after it
  331.  
  332.     one_hook_function_call callFunc = one_hook_dummy_func;
  333.  
  334.     int ret = 0;
  335.     if (hookIndex != -1) {
  336.         if (one_hooks[hookIndex].firstinstruction == 0x7C0802A6)//mflr %r0
  337.             callFunc = &one_hook_stub_mflrr0;
  338.         else if (one_hooks[hookIndex].firstinstruction == 0xF821FF91)//stdu %r1, -0x70(%r1)
  339.             callFunc = &one_hook_stub_r170;
  340.         else {
  341.             printf("Hook at 0x%X does not have a registered stub for instruction 0x%X !!\n", hooked_address, one_hooks[hookIndex].firstinstruction);
  342.         }
  343.     }
  344.     else {
  345.         printf("Hook at 0x%X does not exist at all (invalid index) !!\n", hooked_address);
  346.     }
  347.    
  348.  
  349.     if (hookIndex != -1) {
  350.        
  351.  
  352.         opd_s func_ = { *(int*)one_hooks[hookIndex].functionToCallInSprxOPD , *(int*)(one_hooks[hookIndex].functionToCallInSprxOPD + 0x4) };
  353.         uint64_t(*func)(one_hook_function_call hooked_func,uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) = (uint64_t(*)(one_hook_function_call,uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21)) & func_;
  354.  
  355.         ret = func(callFunc,r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21);
  356.     }
  357.    
  358.    
  359.    
  360.  
  361.     return ret;
  362. }
  363.  
  364. __NAKED int one_hook_intermediate() {
  365.     __asm("mflr %r0");//this will link back to the previous func
  366.     __asm("stdu %r1, -0x70(%r1)");
  367.     __asm("std %r0, 0x60(%r1)");
  368.  
  369.     //now locate the link register from the previous function
  370.     //branched to - branched from = dif (lower 26 bits of instruction)
  371.     //branched to = dif + branched from
  372.     __asm("lis %r11, 0x1006");//assume r11 is never used
  373.     __asm("addi %r11, %r11, 0x5600");//ONE_HOOK_LR
  374.     __asm("stw %r0, 0x0(%r11)");//stores the lr to get back to the original call point into the spot we like
  375.  
  376.     __asm("lis %r11, 0x1006");//assume r11 is never used
  377.     __asm("addi %r11, %r11, 0x5610");//ONE_HOOK_R2
  378.     __asm("stw %r2, 0x0(%r11)");//stores the r2 for us to reload later because it is used in many functions
  379.  
  380.  
  381.     __asm("bl ._Z8one_hookyyyyyyyyyyyyyyyyyyy");//if you get a linker error then it is probably because of this
  382.  
  383.  
  384.  
  385.     __asm("ld %r0, 0x60(%r1)");
  386.     __asm("mtlr %r0");//this will be the link register to the
  387.     __asm("addi %r1, %r1, 0x70");
  388.     __asm("blr");//goes all the way back to the function that called our hooked function
  389. }
  390.  
  391.  
  392. bool onehookhasbeensetup = false;
  393. void setup_one_hook() {
  394.     //address we are putting it at is X
  395.     //anything between X and X+Y is guarenteed to hit a trap, so it's probably never executed. We assume that and also add a small check just in case it is if necessary
  396.     //Any unused part of the code segment with 4 instructions would technically work. Originally i needed 13 instructions for my code which is why I did the modification and got 13 total, but now only 4 is required because it only uses patchinjump
  397.    
  398.     //0x38A048 has 10 instructions to work with
  399.     //0xA104F0 has 11 instructions to work with
  400.     //with a slgiht modification (below), 0xA104E8 can be used with 13 instructions and never be ran under normal circumstances
  401.     *(int*)0xA104E4 = 0x48000038;//change this to always branch and squeeze out 2 more instructions
  402.  
  403.     PatchInJump2(0xA104E8/* + 4*3*/, (int)one_hook_intermediate, false);//4 instructions, false to make it unlinked
  404.  
  405. }
  406.  
  407. void create_hook_one(unsigned int address, unsigned int hookinsprx) {
  408.     static int hook_counter = 0;
  409.     one_hooks[hook_counter].hookaddress = address;
  410.     one_hooks[hook_counter].firstinstruction = *(unsigned int*)address;
  411.     one_hooks[hook_counter].functionToCallInSprxOPD = hookinsprx;
  412.     hook_counter++;
  413.  
  414.  
  415.     //initialize the setup if not done yet
  416.     if (onehookhasbeensetup == false) {
  417.         onehookhasbeensetup = true;
  418.         setup_one_hook();
  419.     }
  420.  
  421.     //this cannot cannot be a bl, or else the link register for the previous function will be lost
  422.     //must be unlinked
  423.     unsigned int branch_to = 0xA104E8;//address we did patchinjump to.
  424.     unsigned int branch_from = address;
  425.     unsigned int instruction = 0;
  426.     int dif = branch_to - branch_from;
  427.     instruction = 0x48000000 + ((dif) & 0x3FFFFFF);//b instruction forwards and backwards. Last 26 bits are the value :)
  428.     *(int*)address = instruction;
  429.     printf("[Hook] set address 0x%X to instruction 0x%X\n",address,instruction);
  430.  
  431. }
  432.  
  433. uint64_t EXPLOSION_EVENT_local_hook(one_hook_function_call hooked_func, uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) {
  434.     printf("You created an explosion!\n");
  435.     return hooked_func(r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16,r17,r18,r19,r20,r21);
  436. }
  437.  
  438. void setup_hooks() {
  439.     create_hook_one(0x12C5728, (int)EXPLOSION_EVENT_local_hook);
  440. }
  441.  
  442.  
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483. -------------------------------------------------------------------------------------------------------------------------------
  484. Initial Commit by gopro2027
  485.  
  486.  
  487. #define NUM_HOOKS 1
  488.  
  489. //two free memory locations (16 bytes)
  490. #define ONE_HOOK_LR *(unsigned int*)0x10065600
  491. #define ONE_HOOK_BRANCHDATA *(unsigned int*)0x10065608
  492.  
  493. struct hook_pairs {
  494.    unsigned int hookaddress;
  495.    unsigned int firstinstruction;
  496.    unsigned int functionToCallInSprxOPD;
  497. };
  498.  
  499. hook_pairs one_hooks[NUM_HOOKS];
  500.  
  501. #define one_hook_stub \
  502.     __asm("lis %r11, 0x1006");\
  503.     __asm("addi %r11, %r11, 0x5608");\
  504.     __asm("lwz %r11, 0x0(%r11)");\
  505.     __asm("mtctr %r11");\
  506.     __asm("bctr");//branches to hooked function
  507.  
  508.  
  509.  
  510. //need to add another one of these functions if the function you are hooking does not start with one of these two instructions
  511. __attribute__((naked)) int one_hook_stub_mflrr0(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) {
  512.    __asm("mflr %r0");
  513.  
  514.    one_hook_stub;
  515. }
  516.  
  517. __attribute__((naked)) int one_hook_stub_r170(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) {
  518.    __asm("stdu %r1, -0x70(%r1)");
  519.  
  520.    one_hook_stub;
  521. }
  522.  
  523.  
  524.  
  525. int one_hook(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) {
  526.    unsigned int lr_val = ONE_HOOK_LR;
  527.  
  528.    printf("LR found: 0x%X\n", lr_val);//lr val was the original bytes for some reason 0x636C6544.....
  529.  
  530.    unsigned int branched_from = ONE_HOOK_LR - 0x4;
  531.    unsigned int dif = *(unsigned int*)(branched_from) & 0xFFFFFF;
  532.    unsigned int extra = dif % 4;//should return 0, 1, 2, or 3
  533.    dif = dif - extra;//now dif should be the proper dif
  534.    unsigned int branched_to = dif + branched_from;//should be correct!
  535.  
  536.    unsigned int hooked_address = branched_to;
  537.    printf("hooked address discovered: 0x%X\n", hooked_address);
  538.  
  539.    unsigned int instruction = 0;
  540.    unsigned int functionToCallInSprxOPD = 0;
  541.    for (int i = 0; i < NUM_HOOKS; i++) {
  542.       if (one_hooks[i].hookaddress == hooked_address) {
  543.          instruction = one_hooks[i].firstinstruction;
  544.          functionToCallInSprxOPD = one_hooks[i].functionToCallInSprxOPD;
  545.       }
  546.    }
  547.  
  548.    bool shouldCallOrig = true;
  549.  
  550.    if (functionToCallInSprxOPD != 0) {
  551.       //need to fix the function first before we call it
  552.       opd_s func_ = { *(int*)functionToCallInSprxOPD , *(int*)(functionToCallInSprxOPD + 0x4) };
  553.       uint64_t(*func)(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21) = (uint64_t(*)(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6, uint64_t r7, uint64_t r8, uint64_t r9, uint64_t r10, uint64_t r11, uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15, uint64_t r16, uint64_t r17, uint64_t r18, uint64_t r19, uint64_t r20, uint64_t r21)) & func_;
  554.  
  555.       shouldCallOrig = func(r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21);
  556.    }
  557.  
  558.  
  559.    ONE_HOOK_BRANCHDATA = hooked_address;
  560.  
  561.  
  562.    int ret = 0;
  563.    if (shouldCallOrig) {
  564.       //printf("About to call on instruction: 0x%X\n", instruction);
  565.       if (instruction == 0x7C0802A6)//mflr %r0
  566.          ret = one_hook_stub_mflrr0(r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21);
  567.       else if (instruction == 0xF821FF91)//stdu %r1, -0x70(%r1)
  568.          ret = one_hook_stub_r170(r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21);
  569.       else
  570.          printf("Hook at 0x%X does not have a registered stub for instruction 0x%X !!\n", hooked_address, instruction);
  571.    }
  572.  
  573.    return ret;
  574. }
  575.  
  576. __attribute__((naked)) int one_hook_intermediate()
  577. {
  578.    __asm("mflr %r0");//this will link back to the previous func
  579.    __asm("stdu %r1, -0x70(%r1)");
  580.    __asm("std %r0, 0x60(%r1)");
  581.  
  582.    //now locate the link register from the previous function
  583.    //branched to - branched from = dif (lower 3 bytes of instruction)
  584.    //branched to = dif + branched from
  585.    __asm("lis %r11, 0x1006");//assume r11 is never used
  586.    __asm("addi %r11, %r11, 0x5600");
  587.    __asm("stw %r0, 0x0(%r11)");//stores the lr value into the spot we like
  588.  
  589.  
  590.    __asm("bl ._Z8one_hookyyyyyyyyyyyyyyyyyyy");
  591.  
  592.  
  593.  
  594.    __asm("ld %r0, 0x60(%r1)");
  595.    __asm("mtlr %r0");//this will be the link register to the
  596.    __asm("addi %r1, %r1, 0x70");
  597.    __asm("blr");//goes all the way back to the function that called our hooked function
  598. }
  599.  
  600.  
  601. bool onehookhasbeensetup = false;
  602. void setup_one_hook() {
  603.    //address we are putting it at is X
  604.    //anything between X and X+Y is guaranteed to hit a trap, so it's probably never executed. We assume that and also add a small check just in case it is if necessary
  605.  
  606.    //0x38A048 has 10 instructions to work with
  607.    //0xA104F0 has 11 instructions to work with
  608.    //with a signed int modification (below), 0xA104E8 can be used with 13 instructions and never be ran under normal circumstances
  609.    *(int*)0xA104E4 = 0x48000038;//change this to always branch and squeeze out 2 more instructions
  610.  
  611.    //bytes based off this function: 0x474054 entityToIndex
  612.    unsigned char bytes_storelr[] = { 0xF8, 0x21, 0xFF, 0x91, 0x7C, 0x08, 0x02, 0xA6, 0xF8, 0x01, 0x00, 0x80 };//3 instructions
  613.    unsigned char bytes_retreivelrandbranch[] = { 0xE8, 0x01, 0x00, 0x80, 0x7C, 0x08, 0x03, 0xA6, 0x38, 0x21, 0x00, 0x70, 0x4E, 0x80, 0x00, 0x20 };//4 instructions
  614.  
  615.    //memcpy(0xA104E8 + 4*0, bytes_storelr, 4*3);//3 instructions
  616.    PatchInJump((uint32_t*)0xA104E8/* + 4*3*/, (uint32_t)one_hook_intermediate, false);//4 instructions
  617.    //memcpy(0xA104E8 + 4*7, bytes_retreivelrandbranch, 4 * 4);//4 instructions
  618.  
  619.    //this code will
  620.  
  621. }
  622.  
  623. void create_hook_one(unsigned int address, unsigned int hookinsprx)
  624. {
  625.    static int hook_counter = 0;
  626.    one_hooks[hook_counter].hookaddress = address;
  627.    one_hooks[hook_counter].firstinstruction = *(unsigned int*)address;
  628.    one_hooks[hook_counter].functionToCallInSprxOPD = hookinsprx;
  629.    hook_counter++;
  630.  
  631.  
  632.    //initialize the setup if not done yet
  633.    if (onehookhasbeensetup == false)
  634.     {
  635.       onehookhasbeensetup = true;
  636.       setup_one_hook();
  637.    }
  638.  
  639.    //this cannot cannot be a bl, or else the link register for the previous function will be lost
  640.    //must be unlinked
  641.    unsigned int branch_to = 0xA104E8;//address we did patchinjump to
  642.    unsigned int branch_from = address;
  643.    unsigned int instruction = 0;
  644.    int dif = branch_to - branch_from;
  645.    if (dif < 0)
  646.     {
  647.       instruction = 0x4b000000 + ((dif) & 0xFFFFFF);//b but backwards direction
  648.    }
  649.    else
  650.     {
  651.       instruction = 0x48000000 + ((dif) & 0xFFFFFF);//b instruction
  652.    }
  653.    *(int*)address = instruction;
  654.    printf("[Hook] set address 0x%X to instruction 0x%X\n", address, instruction);
  655. }
  656.  
  657. bool GetLabelTextByHashHook(int32_t unk_20668B0, int32_t label_hash, int32_t unk_1809560)
  658. {
  659.    printf("GetLabelTextByHashHook\n");
  660.    printf("label_hash: 0x%X\n", label_hash);
  661.     if (label_hash == 0x478FDC87)
  662.         printf("????\n");
  663.  
  664.     return true; // return true to get original
  665. }
  666.  
  667. void setup_hooks()
  668. {
  669.    printf("Creating hooks...");
  670.    create_hook_one(0xD91468, (int)GetLabelTextByHashHook);
  671.    printf("Done creating hooks.");
  672. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement