Advertisement
TheRouletteBoi

PS3 Detour class (LEGACY) and enstone hooking

Sep 11th, 2018 (edited)
354
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.20 KB | None | 0 0
  1. static uint32_t GetFunctionBranch(uint32_t address)
  2. {
  3.     uint32_t dest, temp;
  4.     dest = *(uint32_t*)address;
  5.     temp = dest;
  6.     dest = temp & 0x03FFFFFC;
  7.     if (temp & 0x02000000) dest |= 0xFC000000;
  8.     dest = address + dest;
  9.     return dest;
  10. }
  11.  
  12. bool bCheckIfCMP(int ptr)
  13. {
  14.     unsigned char b = *(unsigned char *)ptr;
  15.     unsigned char b2 = *(unsigned char *)(ptr + 1);
  16.  
  17.     if (b == 0x40 || b == 0x41)
  18.     {
  19.         if (b2 == 0x9A || b2 == 0x82 || b2 == 0x99
  20.             || b2 == 0x81 || b2 == 0x98 || b2 == 0x80)
  21.             return true;
  22.     }
  23.     return false;
  24. }
  25.  
  26. bool IsValidPtr(void *value)
  27. {
  28.     if (value == 0)
  29.     {
  30.         return false;
  31.     }
  32.  
  33.     /*if ((uint32_t)(value) > 0x10000)
  34.     {
  35.         if (*(uint32_t *)(value) == 0)
  36.         {
  37.             return false;
  38.         }
  39.     }*/
  40.  
  41.     return true;
  42. }
  43.  
  44.  
  45.  
  46. struct importStub_s
  47. {
  48.     int16_t ssize;
  49.     int16_t header1;
  50.     int16_t header2;
  51.     int16_t imports;
  52.     int32_t zero1;
  53.     int32_t zero2;
  54.     const char* name;
  55.     uint32_t* fnid;
  56.     opd_s** stub;
  57.     int32_t zero3;
  58.     int32_t zero4;
  59.     int32_t zero5;
  60.     int32_t zero6;
  61. } *g_imports;
  62.  
  63. struct exportStub_s
  64. {
  65.     int16_t ssize;
  66.     int16_t header1;
  67.     int16_t header2;
  68.     int16_t exports;
  69.     int32_t zero1;
  70.     int32_t zero2;
  71.     const char* name;
  72.     uint32_t* fnid;
  73.     opd_s** stub;
  74. } *g_exports;
  75.  
  76.  
  77. /*
  78. skate 3
  79. + 0x30   export_adress_table
  80. + 0x38   import_adress_table
  81.  
  82. gta v
  83. + 0x38   export_adress_table   // gta v doesn't have any exports
  84. + 0x40   import_adress_table
  85.  
  86. minecraft
  87. + 0x38   export_adress_table   // minecraft doesn't have any exports
  88. + 0x40   import_adress_table
  89. */
  90. opd_s * find_export(const char* module, uint32_t fnid)
  91. {
  92.     uint32_t temp_prt = *(uint32_t *)(0x10000 + 0x1AC);
  93.     printf("temp_prt: 0x%X\n", temp_prt);
  94.  
  95.     uint32_t export_adress_table = *(uint32_t *)(temp_prt + 0x38);
  96.     printf("export_adress_table: 0x%X\n", export_adress_table);
  97.  
  98.     uint16_t *temp_exp = (uint16_t*)export_adress_table;
  99.     printf("temp_exp: 0x%X\n", temp_exp);
  100.  
  101.     // while ((--temp_exp)->ssize == 0x1C00);
  102.     g_exports = (exportStub_s*)(temp_exp + 1);
  103.     printf("g_exports: 0x%X\n", g_exports);
  104.  
  105.  
  106.  
  107.     exportStub_s* temp = g_exports;
  108.     printf("find_export temp: 0x%X\n", temp);
  109.  
  110.     while (temp->ssize == 0x1C00)
  111.     {
  112.         printf("temp->name: %s\n", temp->name);
  113.         if (!strcmp(module, temp->name))
  114.         {
  115.             printf("temp->exports: 0x%X\n", temp->exports);
  116.             for (int16_t i = 0; i < temp->exports; i++)
  117.             {
  118.                 if (temp->fnid[i] == fnid)
  119.                 {
  120.                     printf("temp->fnid[%i]: 0x%X\n", i, temp->fnid[i]);
  121.                     return temp->stub[i];
  122.                 }
  123.             }
  124.         }
  125.         temp++;
  126.     }
  127.  
  128.     return NULL;
  129. }
  130. opd_s * find_import(const char* module, uint32_t fnid)
  131. {
  132.     uint32_t temp_prt = *(uint32_t *)(0x10000 + 0x1AC);
  133.     printf("temp_prt: 0x%X\n", temp_prt);
  134.  
  135.     uint32_t import_adress_table = *(uint32_t *)(temp_prt + 0x40);
  136.     printf("import_adress_table: 0x%X\n", import_adress_table);
  137.  
  138.  
  139.     uint16_t *temp_imp = (uint16_t*)import_adress_table;
  140.     printf("temp_imp: 0x%X\n", temp_imp);
  141.  
  142.     while (*temp_imp++ != 0x2C00);
  143.     g_imports = (importStub_s*)(temp_imp - 1);
  144.     printf("g_imports: 0x%X\n", g_imports);
  145.  
  146.  
  147.  
  148.  
  149.     importStub_s* temp = g_imports;
  150.     printf("find_import temp: 0x%X\n", temp);
  151.  
  152.     while (temp->ssize == 0x2C00)
  153.     {
  154.         printf("temp->name: %s\n", temp->name);
  155.         if (!strcmp(module, temp->name))
  156.         {
  157.             printf("temp->imports: 0x%X\n", temp->imports);
  158.             for (int16_t i = 0; i < temp->imports; i++)
  159.             {
  160.                 printf("temp->fnid[%i]: 0x%X\n", i, temp->fnid[i]);
  161.                 if (temp->fnid[i] == fnid)
  162.                 {
  163.                     return temp->stub[i];
  164.                 }
  165.             }
  166.         }
  167.         temp++;
  168.     }
  169.     return NULL;
  170. }
  171.  
  172.  
  173.  
  174.  
  175. __attribute__((section(".text"))) uint8_t DetourAsm[500] = { 0 }; // was 0x3000, changed it to a smaller size because when I use 0x3000 it crashes my thread. I believe the reason it does that is because of the PS3 memory limit. use __attribute__((section(".text")))  to make the buffer executable
  176. uint32_t DetourAsmIndex;
  177.  
  178. /*
  179. TODO:
  180. - make a stub for branchHook if possible???
  181. - clean up FindExportByName FindImportByName
  182. - make derived classes for different types of hooks
  183. */
  184. template <class R>
  185. class DetourHook
  186. {
  187. public:
  188.    // Made by Xx jAmes t xX  ported and adapted to PS3 by TheRouLetteBoi
  189.    // This .h is used to edit functions to detour to your own custom one
  190.    //
  191.    // you may want to change the size of  uint8_t DetourAsm[500] = { 0 }; depending on how many hooks you have but 500 should be enough for about 10 hooks
  192.  
  193.    explicit DetourHook() : m_saveStub(0), m_moduleTOC(GAME_TOC) { } // __builtin_get_toc()
  194.    virtual ~DetourHook() { }
  195.    DetourHook(DetourHook const&) = delete;
  196.    DetourHook(DetourHook&&) = delete;
  197.    DetourHook& operator=(DetourHook const&) = delete;
  198.    DetourHook& operator=(DetourHook&&) = delete;
  199.  
  200. public:
  201.    enum class BranchhookType
  202.    {
  203.       BRANCH_HOOK,
  204.       BRANKLINK_HOOK,
  205.    };
  206.  
  207. public:
  208.    /***
  209.    * e.g
  210.    * detour_vmHook->Hook(0x9B4D00, (uint32_t)VM_HOOK);
  211.    * In the hook
  212.    * return detour_vmHook->GetOriginal(r3, globals, scrProgram, scrThread);
  213.    */
  214.    virtual bool Hook(uint32_t address, uint32_t destination)
  215.    {
  216.       // prevent buffer overflow
  217.       if (g_DetourAsmCount > (MAX_DETOUR_ASM_SIZE - 2)) // if (g_DetourAsmCount > (sizeof(g_DetourAsm) - 2))
  218.          return false;
  219.  
  220.       if (m_cache.address != address || m_saveStub == 0)
  221.       {
  222.          m_saveStub = (uint32_t)&g_DetourAsm[g_DetourAsmCount];
  223.          // save the address in case we take-down the detour
  224.          m_cache.address = address;
  225.          // Copy the asm bytes before we replace it with the hook
  226.          WriteProcessMemory(sys_process_getpid(), m_cache.originalAsm, (void*)address, 0x10);
  227.  
  228.          // increment the index for the space we are using for the stub
  229.          g_DetourAsmCount += DetourFunctionStart(address, m_saveStub, destination);
  230.          return true;
  231.       }
  232.  
  233.       return false;
  234.    }
  235.  
  236.    /***
  237.    * e.g
  238.    * detour_cloneCreateHook->HookVMT(0x1C707E0, (uint32_t)CLONE_CREATE_HOOK);
  239.    * In the hook
  240.    * return detour_cloneCreateHook->GetOriginalVMT(netObjectMgr, netGamePlayerClient, netGamePlayerSelf, netObjType, objectId, sequenceId, syncData, timestamp);
  241.    */
  242.    virtual bool HookVMT(uint32_t address, uint32_t destination)
  243.    {
  244.       if (m_cache.address != address)
  245.       {
  246.          // save the address in case we take-down the detour
  247.          m_cache.address = address;
  248.  
  249.          // Copy the opd_s before we replace it with the hook
  250.          WriteProcessMemory(sys_process_getpid(), (void*)&m_cache.originalAsm, (void*)address, m_cache.originalSize = 0x8);
  251.          return VMTSwapHook(address, destination);
  252.       }
  253.  
  254.       return false;
  255.    }
  256.  
  257.    /***
  258.    * e.g
  259.    * detour_sysPpuThreadCreate = new DetourHook<int>;
  260.    * detour_sysPpuThreadCreate->HookIAT("sysPrxForUser", 0x24A1EA07, (uint32_t)SYS_PPU_THREAD_CREATE_HOOK);
  261.    * In the hook
  262.    * return detour_sysPpuThreadCreate->GetOriginalImportExport(thread_id, entry, arg, prio, stacksize, flags, threadname);
  263.    *
  264.    * e.g
  265.    * detour_cellFsOpen = new DetourHook<CellFsErrno>;
  266.    * detour_cellFsOpen->HookIAT("sys_fs", 0x718BF5F8, (uint32_t)CELL_FS_OPEN_HOOK);
  267.    * In the hook
  268.    * return detour_cellFsOpen->GetOriginalImportExport(path, flags, fd, arg, size);
  269.    */
  270.    virtual bool HookIAT(const char* libaryName, uint32_t fnid, uint32_t destination) // IAT Hooking - "Import Address Table"
  271.    {
  272.       m_importExportCache.m_ImportExportOriginal = FindImportByName(libaryName, fnid);
  273.  
  274.       if (m_importExportCache.m_ImportExportOriginal->sub == 0)
  275.          return false;
  276.  
  277.       return Hook(m_importExportCache.m_ImportExportOriginal->sub, destination);
  278.    }
  279.  
  280.    virtual bool HookEAT(const char* libaryName, uint32_t fnid, uint32_t destination) // EAT Hooking - "Export Address Table"
  281.    {
  282.       m_importExportCache.m_ImportExportOriginal = FindExportByName(libaryName, fnid);
  283.  
  284.       if (m_importExportCache.m_ImportExportOriginal->sub == 0)
  285.          return false;
  286.  
  287.       return Hook(m_importExportCache.m_ImportExportOriginal->sub, destination);
  288.    }
  289.  
  290.    /***
  291.    * e.g
  292.    * detour_networkObjectMgr = new DetourHook<uint32_t>;
  293.    * detour_networkObjectMgr->HookClass(0x192F490, 18, (uint32_t)CLONE_CREATE_HOOK);
  294.    * detour_networkObjectMgr->HookClass(0x192F490, 20, (uint32_t)CLONE_SYNC_HOOK);
  295.    * detour_networkObjectMgr->HookClass(0x192F490, 22, (uint32_t)CLONE_REMOVE_HOOK);
  296.    * Since you have 3 hooks
  297.    * return detour_networkObjectMgr->GetOriginalClass(18, netObjectMgr, netGamePlayerClient, netGamePlayerSelf, netObjType, objectId, sequenceId, syncData, timestamp);
  298.    * return detour_networkObjectMgr->GetOriginalClass(20, networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, netObjType, objectId, syncData, sequenceId, timestamp);
  299.    * return detour_networkObjectMgr->GetOriginalClass(22, networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, objectId, r7);
  300.    */
  301.    virtual bool HookClass(uint32_t classAddr, uint16_t vmtFunctionIndex, uint32_t destination)
  302.    {
  303.       if (ScanClassForFunctions(classAddr))
  304.       {
  305.          return VMTSwapHookAtIndex(vmtFunctionIndex, destination);
  306.       }
  307.  
  308.       return false;
  309.    }
  310.  
  311.    /***
  312.    * e.g
  313.    * detour_networkObjectMgr->HookClass("17CNetworkObjectMgr", 18, (uint32_t)CLONE_CREATE_HOOK);
  314.    * detour_networkObjectMgr->HookClass("17CNetworkObjectMgr", 20, (uint32_t)CLONE_SYNC_HOOK);
  315.    * detour_networkObjectMgr->HookClass("17CNetworkObjectMgr", 22, (uint32_t)CLONE_REMOVE_HOOK);
  316.    * Since you have 3 hooks
  317.    * return detour_networkObjectMgr->GetOriginalClass(18, netObjectMgr, netGamePlayerClient, netGamePlayerSelf, netObjType, objectId, sequenceId, syncData, timestamp);
  318.    * return detour_networkObjectMgr->GetOriginalClass(20, networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, netObjType, objectId, syncData, sequenceId, timestamp);
  319.    * return detour_networkObjectMgr->GetOriginalClass(22, networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, objectId, r7);
  320.    */
  321.    virtual bool HookClass(const char* className, uint16_t vmtFunctionIndex, uint32_t destination)
  322.    {
  323.       uint32_t addr = FindClassByName(className);
  324.       if (addr == 0)
  325.          return false;
  326.  
  327.       return HookClass(addr, vmtFunctionIndex, destination);
  328.    }
  329.  
  330.    /***
  331.    * e.g
  332.    * detour_vmHook->HookInstruction(0x9B770C, (uint32_t)VM_HOOK, DetourHook<uint32_t>::BranchhookType::BRANKLINK_HOOK);
  333.    * In the hook
  334.    * return detour_vmHook->GetOriginalBranchLink(r3, globals, scrProgram, scrThread);
  335.    */
  336.    virtual bool HookInstruction(uint32_t address, uint32_t destination, BranchhookType type = BranchhookType::BRANKLINK_HOOK) // HookSingleInstruction
  337.    {
  338.       if (m_cache.address != address)
  339.       {
  340.          m_cache.address = address;
  341.          WriteProcessMemory(sys_process_getpid(), (void*)&m_cache.originalAsm, (void*)address, m_cache.originalSize = 0x4);
  342.  
  343.          // this should be a new variable instead of using the cache, but doing it for memory's sake
  344.          m_cache.originalAsm[1] = GetFunctionBranch(m_cache.address);
  345.  
  346.          return BranchHook(address, destination, type);
  347.       }
  348.       return false;
  349.    }
  350.  
  351.    // TODO: this is untested so test it soon
  352.    virtual void UnHook()
  353.    {
  354.       if (m_cache.address)
  355.       {
  356.          WriteProcessMemory(sys_process_getpid(), (void*)m_cache.address, (const void*)m_cache.originalAsm, 0x10);
  357.       }
  358.    }
  359.    // TODO: this is untested so test it soon
  360.    virtual void UnHookVMT()
  361.    {
  362.       if (m_cache.address)
  363.       {
  364.          WriteProcessMemory(sys_process_getpid(), (void*)m_cache.address, (const void*)m_cache.originalAsm, 0x8);
  365.       }
  366.    }
  367.    // TODO: this is untested so test it soon
  368.    virtual void UnHookClass()
  369.    {
  370.       if (m_classCache.m_hasBeenScanned)
  371.       {
  372.          for (int i = 0; i < m_classCache.m_vmtFunctionCount; i++)
  373.          {
  374.             WriteProcessMemory(sys_process_getpid(), (void*)m_classCache.m_vmt[i], (const void*)&m_classCache.m_redirectMap[i], 0x8);
  375.          }
  376.  
  377.          if (m_classCache.m_redirectMap)
  378.          {
  379.             delete[] m_classCache.m_redirectMap;
  380.          }
  381.  
  382.          m_classCache.m_hasBeenScanned = false;
  383.       }
  384.    }
  385.    // TODO: this is untested so test it soon
  386.    virtual void UnHookInstruction()
  387.    {
  388.       if (m_cache.address)
  389.       {
  390.          WriteProcessMemory(sys_process_getpid(), (void*)m_cache.address, (const void*)m_cache.originalAsm, 0x4);
  391.       }
  392.    }
  393.  
  394.  
  395.    // No more virtual :(
  396.    template <typename... TArgs>
  397.    R GetOriginal(TArgs... args)
  398.    {
  399.       volatile opd_s opd = { m_saveStub, m_moduleTOC };
  400.       return ((R(*)(...)) & opd)(args...);
  401.    }
  402.  
  403.    template <typename... TArgs>
  404.    R GetOriginalVMT(TArgs... args)
  405.    {
  406.       volatile opd_s opd = { m_cache.originalAsm[0], m_cache.originalAsm[1] };
  407.       return ((R(*)(...)) & opd)(args...);
  408.    }
  409.  
  410.    template <typename... TArgs>
  411.    R GetOriginalClass(uint32_t vmtFunctionIndex, TArgs... args)
  412.    {
  413.       volatile opd_s opd = { m_classCache.m_redirectMap[vmtFunctionIndex].sub, m_classCache.m_redirectMap[vmtFunctionIndex].toc };
  414.       return ((R(*)(...)) & opd)(args...);
  415.    }
  416.  
  417.    template <typename... TArgs>
  418.    R GetOriginalImportExport(TArgs... args)
  419.    {
  420.       volatile opd_s opd = { m_saveStub, m_importExportCache.m_ImportExportOriginal->toc };
  421.       return ((R(*)(...)) & opd)(args...);
  422.    }
  423.  
  424.    // this will only work if you hook a function that starts with a "bl sub_123456"
  425.    template <typename... TArgs>
  426.    R GetOriginalBranchLink(TArgs... args)
  427.    {
  428.       volatile opd_s opd = { m_cache.originalAsm[1], GAME_TOC };
  429.       return ((R(*)(...)) & opd)(args...);
  430.    }
  431.  
  432.  
  433. private:
  434.    /***
  435.    * This function will get any 'b' or 'bl' and any 'cmp' function added to the stub that it replaces
  436.    * @return the size of the stub in byte lengths
  437.    */
  438.    virtual uint32_t DetourFunctionStart(uint32_t functionAddress, uint32_t stubAddress, uint32_t destination)
  439.    {
  440.       destination = GetRawDestination(uint32_t, destination);
  441.  
  442.       uint32_t writeLength = 0;
  443.       uint32_t branchBytes;
  444.       uint32_t tempFuncAddr;
  445.       bool bTemp;
  446.  
  447.       for (int i = 0; i < 4; i++)
  448.       {
  449.          tempFuncAddr = functionAddress + (i * 4);
  450.          uint8_t b = *reinterpret_cast<uint8_t*>(tempFuncAddr);
  451.  
  452.          // b or bl
  453.          if (b == 0x48 || b == 0x49 || b == 0x4B)
  454.          {
  455.             branchBytes = GetFunctionBranch(tempFuncAddr);
  456.             bTemp = (*reinterpret_cast<uint32_t*>(tempFuncAddr) & 1) != 0;
  457.  
  458.             PatchInJump(reinterpret_cast<uint32_t*>(stubAddress + writeLength), branchBytes, bTemp, false);
  459.             writeLength += 0x10;
  460.  
  461.             // if it was a 'b loc_' call, we won't need to anything else to the stub
  462.             if (!bTemp)
  463.             {
  464.                goto DoHook;
  465.             }
  466.          }
  467.  
  468.          // beq or bne, ble or bgt, bge or blt
  469.          else if (CheckIfCMP(tempFuncAddr))
  470.          {
  471.             branchBytes = *reinterpret_cast<uint32_t*>(tempFuncAddr & 0xFFFF);
  472.  
  473.             // if bTemp is true the op code is 'beq'
  474.             bTemp = b == 0x41;
  475.  
  476.             // check if the branch location is within the stub
  477.             if (branchBytes <= 0x10 && branchBytes > 0)
  478.             {
  479.                if (branchBytes <= (0x10 - (i * 4)))
  480.                {
  481.                   write_mem<uint32_t>((stubAddress + writeLength), *reinterpret_cast<uint32_t*>(tempFuncAddr));
  482.                   writeLength += 4;
  483.                }
  484.                else
  485.                {
  486.                   goto branch_else;
  487.                }
  488.             }
  489.             else
  490.             {
  491.             branch_else:
  492.                // make a jump past the call if the cmp != what it is checking                  
  493.                write_mem<uint32_t>(stubAddress + writeLength, (((0x40000000 + ((*reinterpret_cast<uint32_t*>(tempFuncAddr) & 0x00FF0000)) + 0x14)) + (bTemp ? 0x00000000 : 0x01000000)));
  494.                writeLength += 4;
  495.  
  496.                PatchInJump(reinterpret_cast<uint32_t*>(stubAddress + writeLength), (tempFuncAddr + branchBytes), false, false);
  497.                writeLength += 0x10;
  498.             }
  499.          }
  500.  
  501.          // if the function op code is null it is invalid
  502.          else if (*reinterpret_cast<uint32_t*>(tempFuncAddr) == 0)
  503.          {
  504.             break;
  505.          }
  506.          else
  507.          {
  508.             write_mem<uint32_t>((stubAddress + writeLength), *reinterpret_cast<uint32_t*>(tempFuncAddr));
  509.             writeLength += 4;
  510.          }
  511.       }
  512.  
  513.       // make the stub call the orig function
  514.       PatchInJump(reinterpret_cast<uint32_t*>(stubAddress + writeLength), (functionAddress + 0x10), false, false);
  515.       writeLength += 0x10;
  516.  
  517.    DoHook:
  518.  
  519.       // apply the hook
  520.       PatchInJump(reinterpret_cast<uint32_t*>(functionAddress), destination, false, false);
  521.       return writeLength;
  522.    }
  523.  
  524.    virtual bool VMTSwapHook(uint32_t address, uint32_t destination) // VMT Hooking / Pointer redirections
  525.    {
  526.       // replace the virtual table function with ours to intercept
  527.       if (write_mem<uint64_t>(address, *reinterpret_cast<uint64_t*>(destination)))
  528.          return true;
  529.       return false;
  530.    }
  531.  
  532.    virtual bool VMTSwapHookAtIndex(int16_t vmtFunctionIndex, uint32_t destination)
  533.    {
  534.       return VMTSwapHook(m_classCache.m_vmt[vmtFunctionIndex], destination);
  535.    }
  536.  
  537.    // makes a b or bl at the giving address
  538.    virtual bool BranchHook(uint32_t address, uint32_t destination, BranchhookType type)
  539.    {
  540.       destination = GetRawDestination(uint32_t, destination);
  541.  
  542.       uint32_t branch;
  543.       if (type == BranchhookType::BRANCH_HOOK)
  544.       {
  545.          branch = (0x48000000 + ((destination - address) & 0x3FFFFFF));
  546.       }
  547.       else // type == BranchhookType::BRANKLINK_HOOK  // branch link
  548.       {
  549.          branch = (0x48000000 + ((destination - address) & 0x3FFFFFF));
  550.          branch = branch += 1;
  551.       }
  552.  
  553.       return write_mem<uint32_t>(address, branch);
  554.    }
  555.  
  556.    uint16_t GetClassFunctionsCount()
  557.    {
  558.       uint16_t count = 0;
  559.       for (;; count++)
  560.       {
  561.          // if you have more than 500 virtual table functions you have a problem and i don't support you :)
  562.          if (m_classCache.m_vmt[count] == 0 || count > 500)
  563.             break;
  564.       }
  565.       return count;
  566.    }
  567.  
  568.    bool ScanClassForFunctions(uint32_t& classAddr)
  569.    {
  570.       if (!m_classCache.m_hasBeenScanned)
  571.       {
  572.          // save the address in case we take-down the detour
  573.          m_cache.address = classAddr;
  574.          m_classCache.m_vmt = (uint32_t*)classAddr;
  575.  
  576.          m_classCache.m_vmtFunctionCount = GetClassFunctionsCount();
  577.  
  578.          // make sure this class thats virtual functions
  579.          if (m_classCache.m_vmtFunctionCount == 0)
  580.             return false;
  581.  
  582.          // allocate an array to store our virtual table functions
  583.          m_classCache.m_redirectMap = new opd_s[m_classCache.m_vmtFunctionCount];
  584.          if (m_classCache.m_redirectMap == nullptr)
  585.             return false;
  586.  
  587.          // clear the heap memory
  588.          memset(m_classCache.m_redirectMap, 0, sizeof(opd_s) * m_classCache.m_vmtFunctionCount);
  589.  
  590.          // save a copy of the virtual table function addresses in case we need to restore them
  591.          for (int i = 0; i < m_classCache.m_vmtFunctionCount; i++)
  592.             write_mem<uint64_t>((uint32_t)&m_classCache.m_redirectMap[i], *reinterpret_cast<uint64_t*>(m_classCache.m_vmt[i]));
  593.  
  594.          m_classCache.m_hasBeenScanned = true;
  595.       }
  596.  
  597.       return true;
  598.    }
  599.  
  600. private:
  601.    struct HookCache
  602.    {
  603.       uint32_t address;
  604.       uint32_t originalAsm[4]; // 4 instructions
  605.       uint32_t originalSize;
  606.       HookCache() : address(0), originalSize(sizeof(uint32_t) * 4) { memset(originalAsm, 0, sizeof(originalAsm)); }
  607.    };
  608.    struct ClassHookCache
  609.    {
  610.       opd_s* m_redirectMap;
  611.       uint32_t* m_vmt;
  612.       uint16_t m_vmtFunctionCount;
  613.       bool m_hasBeenScanned;
  614.       ClassHookCache() : m_vmtFunctionCount(0), m_hasBeenScanned(false) { }
  615.    };
  616.    struct ImportExportHookCache
  617.    {
  618.       opd_s* m_ImportExportOriginal; // import export opd_s(sub, toc)
  619.    };
  620.  
  621.    HookCache m_cache;
  622.    ClassHookCache m_classCache;
  623.    ImportExportHookCache m_importExportCache;
  624.    uint32_t m_saveStub;
  625.    uint32_t m_moduleTOC; // get the TOC of our sprx so we can use it to call our function later
  626. };
  627.  
  628.  
  629.  
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639. -----------------------------------------------------------------------------------------------------------------------------
  640. // this was me trying to get enstones hooking method working
  641.  
  642.  
  643.  
  644.  
  645. uint64_t HookHandler(uint64_t a1, uint64_t a2)
  646. {
  647.     printf("HookHandler\n");
  648.     printf("a1: 0x%X\n", a1);
  649.     printf("a2: 0x%X\n", a2);
  650.  
  651.     /*
  652.     bool bVar1;
  653.     uint uVar2;
  654.     ulonglong uVar3;
  655.     ulonglong uVar4;
  656.     uint* puVar5;
  657.     undefined8 uVar6;
  658.     int iVar7;
  659.     uint uVar8;
  660.  
  661.     uVar6 = *(undefined8*)(param_2 + 0x100);
  662.     while (*(char*)(param_1 + 0x18) == '\0')
  663.     {
  664.         sleep(100);
  665.     }
  666.  
  667.     iVar7 = 0;
  668.     uVar8 = 0;
  669.     uVar2 = *(uint*)(param_1 + 0x14);
  670.     while (true)
  671.     {
  672.         bVar1 = uVar8 == uVar2;
  673.         uVar3 = (ulonglong)uVar8;
  674.         uVar4 = param_1 + 4U & 0xffffffff;
  675.         uVar8 = uVar8 + 1;
  676.  
  677.         if (bVar1)
  678.             break;
  679.  
  680.         puVar5 = (uint*)FUN_d00ff7ec(uVar4, uVar3);
  681.         if ((int)uVar6 - 4U == puVar5[1])
  682.         {
  683.             iVar7 = iVar7 + 1;
  684.             if (*(char*)(puVar5 + 2) == '\0')
  685.             {
  686.                 ccapi_syscall(0x241); // enable syscall
  687.                 *(undefined*)(puVar5 + 2) = 1;
  688.             }
  689.             (*(code*)(ulonglong) * (uint*)(ulonglong)*puVar5)(param_2 & 0xffffffff);
  690.         }
  691.     }
  692.  
  693.     if (iVar7 == 0)
  694.     {
  695.         trapWord(0x1f, &stack0xffffffffffffff50, &stack0xffffffffffffff50);
  696.     }
  697.     return uVar4;
  698.     */
  699.  
  700.     return 1;
  701. }
  702.  
  703.  
  704. __attribute__((naked)) uint64_t HookHandlerAsm2(uint32_t a1)
  705. {
  706.     __asm__(
  707.         "mr        %r4, %r3;"
  708.         "addis     %r3, %r2, -1;"
  709.         "addic     %r3, %r3, 0x6CFC;"
  710.         "b         ._Z11HookHandleryy;"
  711.     );
  712. }
  713.  
  714. __attribute__((naked)) uint64_t HookHandlerAsm1() // uint32_t r3, uint32_t r4, uint32_t r5, uint32_t r6, uint32_t r7, uint32_t r8, uint32_t r9, uint32_t r10, uint32_t r11, uint32_t r12, uint32_t r13, uint32_t r14, uint32_t r15, uint32_t r16, uint32_t r17, uint32_t r18, uint32_t r19, uint32_t r20, uint32_t r21
  715. {
  716.     __asm__(
  717.         "std       %r0, 0x70(%r1);"
  718.         "addi      %r0, %r1, 0x300;"
  719.         "std       %r0, 0x78(%r1);"
  720.         "std       %r4, 0x90(%r1);"
  721.         "std       %r5, 0x98(%r1);"
  722.         "std       %r6, 0xA0(%r1);"
  723.         "std       %r7, 0xA8(%r1);"
  724.         "std       %r8, 0xB0(%r1);"
  725.         "std       %r9, 0xB8(%r1);"
  726.         "std       %r10, 0xC0(%r1);"
  727.         "std       %r11, 0xC8(%r1);"
  728.         "std       %r12, 0xD0(%r1);"
  729.         "std       %r13, 0xD8(%r1);"
  730.         "std       %r14, 0xE0(%r1);"
  731.         "std       %r15, 0xE8(%r1);"
  732.         "std       %r16, 0xF0(%r1);"
  733.         "std       %r17, 0xF8(%r1);"
  734.         "std       %r18, 0x100(%r1);"
  735.         "std       %r19, 0x108(%r1);"
  736.         "std       %r20, 0x110(%r1);"
  737.         "std       %r21, 0x118(%r1);"
  738.         "std       %r22, 0x120(%r1);"
  739.         "std       %r23, 0x128(%r1);"
  740.         "std       %r24, 0x130(%r1);"
  741.         "std       %r25, 0x138(%r1);"
  742.         "std       %r26, 0x140(%r1);"
  743.         "std       %r27, 0x148(%r1);"
  744.         "std       %r28, 0x150(%r1);"
  745.         "std       %r29, 0x158(%r1);"
  746.         "std       %r30, 0x160(%r1);"
  747.         "std       %r31, 0x168(%r1);"
  748.         "mfctr     %r0;"
  749.         "std       %r0, 0x178(%r1);"
  750.         "mfcr      %r0;"
  751.         "std       %r0, 0x180(%r1);"
  752.         "mfxer     %r0;"
  753.         "std       %r0, 0x188(%r1);"
  754.         "stfd      %f0, 0x190(%r1);"
  755.         "stfd      %f1, 0x198(%r1);"
  756.         "stfd      %f2, 0x1A0(%r1);"
  757.         "stfd      %f3, 0x1A8(%r1);"
  758.         "stfd      %f4, 0x1B0(%r1);"
  759.         "stfd      %f5, 0x1B8(%r1);"
  760.         "stfd      %f6, 0x1C0(%r1);"
  761.         "stfd      %f7, 0x1C8(%r1);"
  762.         "stfd      %f8, 0x1D0(%r1);"
  763.         "stfd      %f9, 0x1D8(%r1);"
  764.         "stfd      %f10, 0x1E0(%r1);"
  765.         "stfd      %f11, 0x1E8(%r1);"
  766.         "stfd      %f12, 0x1F0(%r1);"
  767.         "stfd      %f13, 0x1F8(%r1);"
  768.         "stfd      %f14, 0x200(%r1);"
  769.         "stfd      %f15, 0x208(%r1);"
  770.         "stfd      %f16, 0x210(%r1);"
  771.         "stfd      %f17, 0x218(%r1);"
  772.         "stfd      %f18, 0x220(%r1);"
  773.         "stfd      %f19, 0x228(%r1);"
  774.         "stfd      %f20, 0x230(%r1);"
  775.         "stfd      %f21, 0x238(%r1);"
  776.         "stfd      %f22, 0x240(%r1);"
  777.         "stfd      %f23, 0x248(%r1);"
  778.         "stfd      %f24, 0x250(%r1);"
  779.         "stfd      %f25, 0x258(%r1);"
  780.         "stfd      %f26, 0x260(%r1);"
  781.         "stfd      %f27, 0x268(%r1);"
  782.         "stfd      %f28, 0x270(%r1);"
  783.         "stfd      %f29, 0x278(%r1);"
  784.         "stfd      %f30, 0x280(%r1);"
  785.         "stfd      %f31, 0x288(%r1);"
  786.         "addi      %r3, %r1, 0x70;"
  787.         "bl        ._Z15HookHandlerAsm2j;"
  788.         "nop;"
  789.         "ld        %r0, 0x170(%r1);"
  790.         "mtlr      %r0;"
  791.         "ld        %r0, 0x178(%r1);"
  792.         "mtctr     %r0;"
  793.         "ld        %r0, 0x180(%r1);"
  794.         "mtcr      %r0;"
  795.         "ld        %r0, 0x188(%r1);"
  796.         "mtxer     %r0;"
  797.         "ld        %r0, 0x70(%r1);"
  798.         "nop;"
  799.         "ld        %r2, 0x80(%r1);"
  800.         "ld        %r3, 0x88(%r1);"
  801.         "ld        %r4, 0x90(%r1);"
  802.         "ld        %r5, 0x98(%r1);"
  803.         "ld        %r6, 0xA0(%r1);"
  804.         "ld        %r7, 0xA8(%r1);"
  805.         "ld        %r8, 0xB0(%r1);"
  806.         "ld        %r9, 0xB8(%r1);"
  807.         "ld        %r10, 0xC0(%r1);"
  808.         "ld        %r11, 0xC8(%r1);"
  809.         "ld        %r12, 0xD0(%r1);"
  810.         "ld        %r13, 0xD8(%r1);"
  811.         "ld        %r14, 0xE0(%r1);"
  812.         "ld        %r15, 0xE8(%r1);"
  813.         "ld        %r16, 0xF0(%r1);"
  814.         "ld        %r17, 0xF8(%r1);"
  815.         "ld        %r18, 0x100(%r1);"
  816.         "ld        %r19, 0x108(%r1);"
  817.         "ld        %r20, 0x110(%r1);"
  818.         "ld        %r21, 0x118(%r1);"
  819.         "ld        %r22, 0x120(%r1);"
  820.         "ld        %r23, 0x128(%r1);"
  821.         "ld        %r24, 0x130(%r1);"
  822.         "ld        %r25, 0x138(%r1);"
  823.         "ld        %r26, 0x140(%r1);"
  824.         "ld        %r27, 0x148(%r1);"
  825.         "ld        %r28, 0x150(%r1);"
  826.         "ld        %r29, 0x158(%r1);"
  827.         "ld        %r30, 0x160(%r1);"
  828.         "ld        %r31, 0x168(%r1);"
  829.         "lfd       %f0, 0x190(%r1);"
  830.         "lfd       %f1, 0x198(%r1);"
  831.         "lfd       %f2, 0x1A0(%r1);"
  832.         "lfd       %f3, 0x1A8(%r1);"
  833.         "lfd       %f4, 0x1B0(%r1);"
  834.         "lfd       %f5, 0x1B8(%r1);"
  835.         "lfd       %f6, 0x1C0(%r1);"
  836.         "lfd       %f7, 0x1C8(%r1);"
  837.         "lfd       %f8, 0x1D0(%r1);"
  838.         "lfd       %f9, 0x1D8(%r1);"
  839.         "lfd       %f10, 0x1E0(%r1);"
  840.         "lfd       %f11, 0x1E8(%r1);"
  841.         "lfd       %f12, 0x1F0(%r1);"
  842.         "lfd       %f13, 0x1F8(%r1);"
  843.         "lfd       %f14, 0x200(%r1);"
  844.         "lfd       %f15, 0x208(%r1);"
  845.         "lfd       %f16, 0x210(%r1);"
  846.         "lfd       %f17, 0x218(%r1);"
  847.         "lfd       %f18, 0x220(%r1);"
  848.         "lfd       %f19, 0x228(%r1);"
  849.         "lfd       %f20, 0x230(%r1);"
  850.         "lfd       %f21, 0x238(%r1);"
  851.         "lfd       %f22, 0x240(%r1);"
  852.         "lfd       %f23, 0x248(%r1);"
  853.         "lfd       %f24, 0x250(%r1);"
  854.         "lfd       %f25, 0x258(%r1);"
  855.         "lfd       %f26, 0x260(%r1);"
  856.         "lfd       %f27, 0x268(%r1);"
  857.         "lfd       %f28, 0x270(%r1);"
  858.         "lfd       %f29, 0x278(%r1);"
  859.         "lfd       %f30, 0x280(%r1);"
  860.         "lfd       %f31, 0x288(%r1);"
  861.         "ld        %r1, 0x78(%r1);"
  862.         "blr;"
  863.     );
  864. }
  865.  
  866. // Destination = HookHandler
  867. bool SetupHookHandler(uint32_t hookHandlerInstallationAddress, void* hookHandler) // enstone hooking method
  868. {
  869.     // todo: add check to see if it's been hooked already
  870.  
  871.     printf("SetupHookHandler\n");
  872.     printf("hookHandler: 0x%X\n", hookHandler);
  873.  
  874.     uint32_t opcode[12];
  875.     opcode[0] = 0xF821FD01;     // stdu       r1,-0x300(r1)
  876.     opcode[1] = 0xF8410080;     // std        r2,0x80(r1)
  877.     opcode[2] = 0xF8610088;     // std        r3,0x88(r1)
  878.     opcode[3] = 0x7C4802A6;     // mfspr      r2,lr
  879.     opcode[4] = 0xF8410170;     // std        r2,0x170(r1)                                                  0xC699EC
  880.     opcode[5] = 0x38600000;     // li         r3, 0x0
  881.     opcode[6] = 0x64630000 + ((((uint32_t)hookHandler) >> 16) & 0xFFFF);    //  oris       r3,r3,0x188      opd@hi
  882.     opcode[7] = 0x60630000 + (((uint32_t)hookHandler) & 0xFFFF);            //  ori        r3,r3,0x150      opd@low
  883.     opcode[8] = 0x80430004;     // lwz        r2,0x4(r3)
  884.     opcode[9] = 0x80630000;     // lwz        r3,0x0(r3)                                                    0x18882B0 (sprx toc)
  885.     opcode[10] = 0x7C6803A6;    // mtspr      lr,r3
  886.     opcode[11] = 0x4E800020;    // blr
  887.     WriteProcessMemory((void*)hookHandlerInstallationAddress, opcode, sizeof(opcode));
  888.  
  889.     return true;
  890. }
  891. void HookAnyToHandler(uint32_t someTypeOfAllocator, uint32_t Destination, uint32_t Address)
  892. {
  893.     printf("HookAnyToHandler\n");
  894.     SetupHookHandler(0x10080, HookHandlerAsm1);
  895.  
  896.     //printf("Destination: 0x%X\n", Destination);
  897.     //Destination = (void*)*(uint32_t*)Destination; // opd_s
  898.     //printf("Destination: 0x%X\n", Destination);
  899.  
  900.     uint32_t branchTo = 0x10080;
  901.     uint32_t branchFrom = Address;
  902.  
  903.     // branch link hook
  904.     // 0x48000001
  905.     // 0x4C000001
  906.     // branch hook
  907.     // 0x48000000
  908.     // 0x4C000000
  909.     uint32_t branchInstruction = (branchTo > branchFrom) ?
  910.         0x48000001 + (branchTo - branchFrom) :
  911.         0x4C000001 - (branchFrom - branchTo);
  912.     printf("branchInstruction: 0x%X\n", branchInstruction);
  913.  
  914.     WriteProcessMemory((void*)branchFrom, (const void*)&branchInstruction, 4);
  915.  
  916.  
  917.     // todo: it seems to have some type of std:: function. maybe std::bind or std::invoke or something else idk
  918.  
  919. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement