Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- *****IMPORTANT*****
- *****SEE LINK FOR UPDATED HOOKING METHODS https://pastebin.com/p7nKwnDx *****
- #include <ppu_asm_intrinsics.h> // __ALWAYS_INLINE
- #include <sys/process.h> // sys_process_getpid
- #define MARK_AS_EXECUTABLE __attribute__((section(".text")))
- #define GetRawDestination(type, destination) (type)*(type*)(destination)
- #define PROC_TOC 0x01C85330
- struct opd_s
- {
- uint32_t sub;
- uint32_t toc;
- };
- bool use_hen_syscalls = false;
- uint32_t sys_dbg_write_process_memory(uint32_t pid, void* address, const void* data, size_t size)
- {
- system_call_4(905, (uint64_t)pid, (uint64_t)address, (uint64_t)size, (uint64_t)data);
- return_to_user_prog(uint32_t);
- }
- uint32_t sys_hen_write_process_memory(uint32_t pid, void* address, const void* data, size_t size)
- {
- system_call_6(8, 0x7777, 0x32, (uint64_t)pid, (uint64_t)address, (uint64_t)data, (uint64_t)size);
- return_to_user_prog(uint32_t);
- }
- uint32_t WriteProcessMemory(uint32_t pid, void* address, const void* data, size_t size)
- {
- if (!use_hen_syscalls)
- {
- uint32_t write = sys_dbg_write_process_memory(pid, address, data, size);
- if (write == SUCCEEDED)
- {
- return write;
- }
- }
- use_hen_syscalls = true;
- return sys_hen_write_process_memory(pid, address, data, size);
- }
- uint32_t GetCurrentToc()
- {
- uint32_t* entry_point = *reinterpret_cast<uint32_t**>(0x1001C); // ElfHeader->e_entry
- return entry_point[1];
- }
- template <typename R>
- __ALWAYS_INLINE R(*GameCall(std::uint32_t addr, std::uint32_t toc = PROC_TOC))(...)
- {
- volatile opd_s opd = { addr, toc };
- R(*func)(...) = (R(*)(...))&opd;
- return func;
- }
- // when calling some game functions with GameCallV2 the game crashes in Minecraft PS3 Edition so use GameCall instead
- template <typename R, typename... TArgs>
- __ALWAYS_INLINE R GameCallV2(std::uint32_t addr, TArgs... args)
- {
- volatile opd_s opd = { addr, PROC_TOC };
- R(*func)(TArgs...) = (R(*)(TArgs...))&opd;
- return func(args...);
- }
- template <typename R>
- __ALWAYS_INLINE R(*VmtCall(std::uint32_t vmt, std::uint32_t offset))(...)
- {
- std::uint32_t* funcAdr = (std::uint32_t*)(*(volatile std::uint32_t*)(vmt + offset));
- volatile opd_s opd = { funcAdr[0], funcAdr[1] };
- R(*func)(...) = (R(*)(...))&opd;
- return func;
- }
- template <typename var>
- bool write_mem(uint32_t address, var value)
- {
- return (WriteProcessMemory(sys_process_getpid(), (void*)address, &value, sizeof(var)) == SUCCEEDED);
- }
- __attribute__((naked)) void _savegpr0_N()
- {
- // https://pastebin.com/a7Ci8aAi
- __asm
- (
- "std %r14, -144(%r1);" // _savegpr0_14
- "std %r15, -136(%r1);" // _savegpr0_15
- "std %r16, -128(%r1);" // _savegpr0_16
- "std %r17, -120(%r1);" // _savegpr0_17
- "std %r18, -112(%r1);" // _savegpr0_18
- "std %r19, -104(%r1);" // _savegpr0_19
- "std %r20, -96(%r1);" // _savegpr0_20
- "std %r21, -88(%r1);" // _savegpr0_21
- "std %r22, -80(%r1);" // _savegpr0_22
- "std %r23, -72(%r1);" // _savegpr0_23
- "std %r24, -64(%r1);" // _savegpr0_24
- "std %r25, -56(%r1);" // _savegpr0_25
- "std %r26, -48(%r1);" // _savegpr0_26
- "std %r27, -40(%r1);" // _savegpr0_27
- "std %r28, -32(%r1);" // _savegpr0_28
- "std %r29, -24(%r1);" // _savegpr0_29
- "std %r30, -16(%r1);" // _savegpr0_30
- "std %r31, -8(%r1);" // _savegpr0_31
- "std %r0, 16(%r1);"
- "blr;"
- );
- }
- uint32_t RelinkGPLR(uint32_t SFSOffset, uint32_t* SaveStubAddress, uint32_t* OriginalAddress)
- {
- uint32_t Instruction = 0, Replacing;
- uint32_t* Saver = *(uint32_t**)_savegpr0_N;
- if (SFSOffset & 0x2000000)
- SFSOffset |= 0xFC000000;
- Replacing = OriginalAddress[SFSOffset / 4];
- for (int i = 0; i < 20; i++)
- {
- if (Replacing == Saver[i])
- {
- int NewOffset = (int)&Saver[i] - (int)SaveStubAddress;
- Instruction = 0x48000001 | (NewOffset & 0x3FFFFFC);
- }
- }
- return Instruction;
- }
- void PatchInJump(uint32_t* address, uint32_t destination, bool linked)
- {
- uint32_t inst_lis = 0x3D600000 + ((destination >> 16) & 0xFFFF); // lis %r11, dest>>16
- write_mem<uint32_t>((uint32_t)&address[0], inst_lis);
- if (destination & 0x8000) // if bit 16 is 1
- write_mem<uint32_t>((uint32_t)&address[0], inst_lis += 1);
- write_mem<uint32_t>((uint32_t)&address[1], 0x396B0000 + (destination & 0xFFFF)); // addi %r11, %r11, dest&OxFFFF
- write_mem<uint32_t>((uint32_t)&address[2], 0x7D6903A6); // mtctr %r11
- write_mem<uint32_t>((uint32_t)&address[3], 0x4E800420); // bctr
- if (linked)
- write_mem<uint32_t>((uint32_t)&address[3], 0x4E800421); // bctrl
- __dcbst(address);
- __sync();
- __isync();
- }
- void HookFunctionStart(uint32_t* address, uint32_t destination, uint32_t* original)
- {
- uint32_t addressRelocation = (uint32_t)(&address[4]); // Replacing 4 instructions with a jump, this is the stub return address
- // build the stub
- // make a jump to go to the original function start+4 instructions
- uint32_t inst_lis = 0x3D600000 + ((addressRelocation >> 16) & 0xFFFF); // lis r11, 0 | Load Immediate Shifted
- write_mem<uint32_t>((uint32_t)&original[0], inst_lis);
- if (addressRelocation & 0x8000) // If bit 16 is 1
- write_mem<uint32_t>((uint32_t)&original[0], inst_lis += 1); // lis r11, 0 | Load Immediate Shifted
- write_mem<uint32_t>((uint32_t)&original[1], 0x396B0000 + (addressRelocation & 0xFFFF)); // addi r11, r11, (value of AddressRelocation & 0xFFFF) | Add Immediate
- write_mem<uint32_t>((uint32_t)&original[2], 0x7D6903A6); // mtspr CTR, r11 | Move to Special-Purpose Register CTR
- // Instructions [3] through [6] are replaced with the original instructions from the function hook
- // Copy original instructions over, relink stack frame saves to local ones
- for (int i = 0; i < 4; i++)
- {
- if ((address[i] & 0xF8000000) == 0x48000000) // branch with link
- {
- write_mem<uint32_t>((uint32_t)&original[i + 3], RelinkGPLR((address[i] & ~0x48000003), &original[i + 3], &address[i]));
- }
- else
- {
- write_mem<uint32_t>((uint32_t)&original[i + 3], address[i]);
- }
- }
- write_mem<uint32_t>((uint32_t)&original[7], 0x4E800420); // bctr | Branch unconditionally
- __dcbst(original); // Data Cache Block Store | Allows a program to copy the contents of a modified block to main memory.
- __sync(); // Synchronize | Ensure the dcbst instruction has completed.
- __isync(); // Instruction Synchronize | Refetches any instructions that might have been fetched prior to this instruction.
- PatchInJump(address, *(uint32_t*)destination, false); // Redirect Function to ours
- /*
- * So in the end, this will produce:
- *
- * lis r11, ((AddressRelocation >> 16) & 0xFFFF [+ 1])
- * addi r11, r11, (AddressRelocation & 0xFFFF)
- * mtspr CTR, r11
- * branch (GPR)
- * dcbst (SaveStub)
- * sync
- */
- }
- #define MAX_HOOKFUNCTIONS_ASM_SIZE 300
- MARK_AS_EXECUTABLE uint8_t g_hookFunctionsAsm[300];
- int g_hookFunctionsAsmCount = 0;
- bool HookFunctionStartAuto(uint32_t* address, uint32_t destination, uint32_t** original)
- {
- // check for buffer overflow
- if (g_hookFunctionsAsmCount > (MAX_HOOKFUNCTIONS_ASM_SIZE - 2))
- return false;
- uint32_t* stubAddr = (uint32_t*)&g_hookFunctionsAsm[g_hookFunctionsAsmCount];
- HookFunctionStart(address, destination, stubAddr);
- // write an opd into memory
- write_mem<uint64_t>((uint32_t)&stubAddr[8], ((uint64_t)stubAddr << 32) | GetCurrentToc()); // (uint32_t)__builtin_get_toc()
- *original = &stubAddr[8];
- // Increment asm byte count
- // 0x20 bytes from HookFunctionStart
- // 0x8 bytes for opd
- g_hookFunctionsAsmCount += 0x28;
- return true;
- }
- void PatchInBranch(uint32_t* address, uint32_t destination, bool linked)
- {
- destination = GetRawDestination(uint32_t, destination);
- uint32_t inst_branch = 0x48000000 + ((destination - (uint32_t)address) & 0x3FFFFFF); // b Destination
- write_mem<uint32_t>((uint32_t)&address[0], inst_branch);
- if (linked)
- write_mem<uint32_t>((uint32_t)&address[0], inst_branch += 1); // bl Destination
- }
- void PatchInVmt(uint32_t* address, uint32_t destination)
- {
- write_mem<uint64_t>((uint32_t)&address[0], GetRawDestination(uint64_t, destination)); // uint64_t so it includes the toc
- }
- EXAMPLES:
- // restore hook method
- #define GetLabelTextByGXTFn(gtxDictionary, gxtLabel) GameCall<const char*>(0xD914CC)(gtxDictionary, gxtLabel)
- char backup_GetLabelTextByGXT[16];
- const char* GetLabelTextByGXT(uint32_t gtxDictionary, const char* labelName)
- {
- if (!strcmp(labelName, "LOADING_MPLAYER_L"))
- return "Loading Online With Mod Menu";
- else if (!strcmp(labelName, "LOADING_SPLAYER_L"))
- return "Loading Story Mode With Mod Menu";
- // backup hook, revert, call, hook
- char backup_hook[16];
- WriteProcessMemory(sys_process_getpid(), backup_hook, (const void *)0xD914CC, 16);
- WriteProcessMemory(sys_process_getpid(), (void *)0xD914CC, backup_GetLabelTextByGXT, 16);
- const char *ret = GetLabelTextByGXTFn(gtxDictionary, labelName);
- WriteProcessMemory(sys_process_getpid(), (void *)0xD914CC, backup_hook, 16);
- return ret;
- }
- https://imgur.com/rGsg4iV
- WriteProcessMemory(sys_process_getpid(), backup_GetLabelTextByGXT, (const void *)0xD914CC, 16);
- PatchInJump((uint32_t*)0xD914CC, *(uint32_t*)GetLabelTextByGXT, false);
- // virtual table function method
- #define networkObjectMgr_HandleCloneRemoveFn(networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, objectId, bitFlags) GameCall<bool>(0x133DC5C)(networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, objectId, bitFlags)
- bool networkObjectMgr_HandleCloneRemove(uintptr_t networkObjectMgr, uintptr_t netGamePlayerClient, uintptr_t netGamePlayerSelf, uint16_t objectId, uint32_t bitFlags)
- {
- printf("networkObjectMgr_HandleCloneRemove\n");
- printf("netGamePlayerClient 0x%X\n", netGamePlayerClient);
- return networkObjectMgr_HandleCloneRemoveFn(networkObjectMgr, netGamePlayerClient, netGamePlayerSelf, objectId, bitFlags);
- }
- https://imgur.com/ycGbthr
- PatchInVmt((uint32_t*)0x1C70800, (uint32_t)networkObjectMgr_HandleCloneRemove);
- // branch or mid function method
- #define netObjectMgrBase_GetNetworkObjectFn(cNetworkObjectMgr, id, evenIfDeleting) GameCall<uintptr_t>(0x9F8C38)(cNetworkObjectMgr, id, evenIfDeleting)
- #define netObjectMgrBase_RegisterNetworkObjectFn(netObjectMgr, netObject) GameCall<uint32_t>(0xA12890)(netObjectMgr, netObject)
- void netObjectMgrBase_RegisterNetworkObject(uintptr_t networkObjectMgr, uintptr_t netObj)
- {
- uintptr_t netObjPtr = netObjectMgrBase_GetNetworkObjectFn(networkObjectMgr, *(uint16_t*)(netObj + 0x6), 1);
- if (netObjPtr)
- {
- uintptr_t vmt = *(uintptr_t*)(netObj);
- VmtCall<void>(vmt, 0xC8)(netObj);
- printf("re registering existing network object\n");
- return;
- }
- netObjectMgrBase_RegisterNetworkObjectFn(networkObjectMgr, netObj);
- }
- https://imgur.com/8sb4PwH
- PatchInBranch((uint32_t*)0x1339684, (uint32_t)netObjectMgrBase_RegisterNetworkObject, true);
- // hook functions with GPLR
- 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);
- parManager_LoadFromStructure_t parManager_LoadFromStructure_Original = nullptr;
- 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)
- {
- printf("parManager_LoadFromStructure\n");
- printf("filePath %s\n", filePath);
- return parManager_LoadFromStructure_Original(parStructureInstance, filePath, extension, parStructure, vars, r8, r9);
- }
- https://imgur.com/gigHt7F
- HookFunctionStartAuto((uint32_t*)0xAC709C, (uint32_t)parManager_LoadFromStructure, (uint32_t**)&parManager_LoadFromStructure_Original);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement