Last active
February 25, 2022 12:40
-
-
Save TheRouletteBoi/f4fb4fda8ab957920eb5d07e191793cb to your computer and use it in GitHub Desktop.
Hooking method by using a single branch. PowerPC, PPC, PS3, Playstation 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** Initial Commit by gopro2027 **/ | |
/** Revision #2 by gopro2027 **/ | |
/** | |
* Added "original" into function hook | |
* Fixed branch instruction | |
*/ | |
/** Revision #3 by TheRouLetteBoi **/ | |
/** | |
* Addded 2 examples | |
* Automatically increment and find hooks using STL | |
* Cleaned up code so it is easier to understand | |
* Changed detour location to 0x10080 to support all games | |
* Renamed one_hook to HookHandler | |
* Removed PatchInJump | |
* Removed "some" not all redundant parameters | |
* Fixed warnings | |
*/ | |
/** | |
reference https://pastebin.com/yezsesij (enstone hooking. scroll to the bottom) | |
reference https://pastebin.com/RBYPZEb5 (original) | |
GOAL: | |
- Make a hooking method without the need of a stub. that way we can use it on HEN and hopefully in Kernel LV2 | |
- Have the ability to hook functions with less than 4 instructions | |
TODO | |
- Change executable detour location from 0xA104E8 to 0x10000 (ELF segment) so it works on any game | |
- Get rid of empty memory addresses (0x10065600) and use the stack | |
- Get rid of redundant parameters | |
- Fix warnings | |
- Make into a class? | |
- Find a better way to using get "original" | |
- Use __builtin_return_address() to get LR | |
- Use __builtin_get_toc() to get r2 | |
- Use __reg(3) __reg(4) ect.. to get registers | |
*/ | |
#undef vector | |
#include <vector> | |
#include <algorithm> | |
#define MAKE_JUMP(addr, to) *(uint32_t *)(addr) = (0x12 << 26) | ((((to-(addr))>>2)&0xFFFFFF) << 2) | |
#define __NAKED __attribute__((naked)) | |
using original_t = void(*)(); | |
using hooked_t = | |
uint64_t(*)(original_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, uint64_t); | |
struct hookCache | |
{ | |
uint32_t hookAddress; | |
uint32_t originalInstruction; | |
uint64_t functionCallback; | |
}; | |
std::vector<hookCache> hookList; | |
// three free memory locations (24 bytes) | |
#define ONE_HOOK_LR *(uint32_t*)0x10065600 | |
#define ONE_HOOK_R2 *(uint32_t*)0x10065610 | |
#define ONE_HOOK_BRANCHDATA *(uint32_t*)0x10065608 | |
// need to add another one of these functions if the function you are hooking does not start with one of these two instructions | |
__NAKED void Stub_mflr_r0() | |
{ | |
__asm("mflr %r0"); | |
// can't put comments on the code below but it's grabbing the address to branch to and r2 and loading them up | |
__asm("lis %r11, 0x1006"); | |
__asm("addi %r11, %r11, 0x5610"); | |
__asm("lwz %r2, 0x0(%r11)"); // r2 = *(uint32_t*)(0x10065610) | |
__asm("lis %r11, 0x1006"); | |
__asm("addi %r11, %r11, 0x5608"); | |
__asm("lwz %r11, 0x0(%r11)"); // r11 = *(uint32_t*)(0x10065608) | |
__asm("mtctr %r11"); | |
__asm("bctr"); // jump_to r11 | |
} | |
__NAKED void Stub_r1_0x70() | |
{ | |
__asm("stdu %r1, -0x70(%r1)"); | |
// can't put comments on the code below but it's grabbing the address to branch to and r2 and loading them up | |
__asm("lis %r11, 0x1006"); | |
__asm("addi %r11, %r11, 0x5610"); | |
__asm("lwz %r2, 0x0(%r11)"); // r2 = *(uint32_t*)(0x10065610) | |
__asm("lis %r11, 0x1006"); | |
__asm("addi %r11, %r11, 0x5608"); | |
__asm("lwz %r11, 0x0(%r11)"); // r11 = *(uint32_t*)(0x10065608) | |
__asm("mtctr %r11"); | |
__asm("bctr"); // jump_to r11 | |
} | |
uint32_t ResolveBranch(uint32_t branchAddress) | |
{ | |
uint32_t instruction = *(uint32_t*)(branchAddress); | |
int32_t offset = instruction & 0x3FFFFFC; | |
if (offset & (1 << 25)) | |
offset |= ~0x03FFFFFF; | |
return branchAddress + offset; | |
} | |
uint64_t HookHandler(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) | |
{ | |
uint32_t lr_val = ONE_HOOK_LR; | |
printf("LR found: 0x%X\n", lr_val); | |
uint32_t branched_from = lr_val - 0x4; // link register -0x4 is the branch command | |
uint32_t hookedAddress = ResolveBranch(branched_from); | |
printf("hooked address discovered: 0x%X\n", hookedAddress); | |
auto currentHook = std::find_if(hookList.begin(), hookList.end(), [&hookedAddress](const hookCache& cache) | |
{ | |
return cache.hookAddress == hookedAddress; | |
}); | |
ONE_HOOK_BRANCHDATA = hookedAddress + 4; // go to the next instruction after it | |
original_t original = nullptr; | |
uint64_t ret = 0; | |
if (hookList.end() != currentHook) | |
{ | |
// find the original instruction depending on our hook | |
if ((*currentHook).originalInstruction == 0x7C0802A6) // mflr %r0 | |
original = &Stub_mflr_r0; | |
else if ((*currentHook).originalInstruction == 0xF821FF91) // stdu %r1, -0x70(%r1) | |
original = &Stub_r1_0x70; | |
if (original != nullptr) | |
{ | |
hooked_t func = (hooked_t)&(*currentHook).functionCallback; | |
ret = func(original, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21); | |
} | |
} | |
return ret; | |
} | |
__NAKED void HookHandlerAsm() | |
{ | |
__asm("mflr %r0");//this will link back to the previous func | |
__asm("stdu %r1, -0x70(%r1)"); | |
__asm("std %r0, 0x60(%r1)"); | |
//now locate the link register from the previous function | |
//branched to - branched from = dif (lower 26 bits of instruction) | |
//branched to = dif + branched from | |
__asm("lis %r11, 0x1006");//assume r11 is never used | |
__asm("addi %r11, %r11, 0x5600");//ONE_HOOK_LR | |
__asm("stw %r0, 0x0(%r11)");//stores the lr to get back to the original call point into the spot we like | |
__asm("lis %r11, 0x1006");//assume r11 is never used | |
__asm("addi %r11, %r11, 0x5610");//ONE_HOOK_R2 | |
__asm("stw %r2, 0x0(%r11)");//stores the r2 for us to reload later because it is used in many functions | |
__asm("bl ._Z11HookHandleryyyyyyyyyyyyyyyyyyy");//if you get a linker error then it is probably because of this | |
__asm("ld %r0, 0x60(%r1)"); | |
__asm("mtlr %r0");//this will be the link register to the | |
__asm("addi %r1, %r1, 0x70"); | |
__asm("blr");//goes all the way back to the function that called our hooked function | |
} | |
void SetupHook(uint32_t fnAddress, uintptr_t fnCallback) | |
{ | |
uint32_t instructions[4]{}; | |
instructions[0] = 0x3D600000 + ((fnCallback >> 16) & 0xFFFF); // lis %r11, fnCallback@h | |
instructions[1] = 0x616B0000 + (fnCallback & 0xFFFF); // ori %r11, %r11, fnCallback@l | |
instructions[2] = 0x7D6903A6; // mtctr %r11 | |
instructions[3] = 0x4E800420; // bctr | |
WriteProcessMemory(sys_process_getpid(), (void*)fnAddress, instructions, sizeof(instructions)); | |
} | |
void InstallHook() | |
{ | |
SetupHook(0x10080, *(uintptr_t*)HookHandlerAsm); | |
} | |
void AddToHandler(uint32_t fnAddress, uintptr_t fnCallback) | |
{ | |
hookList.push_back({ | |
fnAddress, | |
*reinterpret_cast<uint32_t*>(fnAddress), | |
*reinterpret_cast<uint64_t*>(fnCallback) | |
}); | |
MAKE_JUMP(fnAddress, 0x10080); | |
} | |
/** EXAMPLES **/ | |
using GetLabelTextByHash_t = const char*(*)(uintptr_t labelHashMap, uint32_t labelHash, uintptr_t nameHash); | |
const char* GetLabelTextByHashHook(GetLabelTextByHash_t original, uintptr_t labelHashMap, uint32_t labelHash, uintptr_t nameHash) | |
{ | |
if (labelHash == 0x478FDC87) | |
return "EPIC GAMER STYLE"; | |
return original(labelHashMap, labelHash, nameHash); | |
} | |
using AssignPhysicalIndex_t = uintptr_t(*)(uintptr_t networkPlayerMgr, uintptr_t netGamePlayer, uint8_t index); | |
uintptr_t AssignPhysicalIndexHook(AssignPhysicalIndex_t original, uintptr_t networkPlayerMgr, uintptr_t netGamePlayer, uint8_t index) | |
{ | |
printf("AssignPhysicalIndexHook\n"); | |
printf("netGamePlayer 0x%X\n", netGamePlayer); | |
return original(networkPlayerMgr, netGamePlayer, index); | |
} | |
int main() | |
{ | |
InstallHook(); | |
// https://imgur.com/usuPNXK | |
AddToHandler(0xD91468, (uintptr_t)GetLabelTextByHashHook); | |
// https://imgur.com/yMbnnDC | |
AddToHandler(0xA15618, (uintptr_t)AssignPhysicalIndexHook); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment