Note: you will need some knowledge of ppc for this.
I'll try to explain some methods of hooking as good as possible. But it still can be hard without knowledge of ppc since you will need to reverse the number of arguments and also the type.
I will not explain this process.
Download vsh.elf
METHOD 1: Intercepting calls of separate functions
This method is really simple. All it does is edit the call to make it branch to a subroutine you have written inside the .self. Note that the difference between the address of the call and your subroutine can't be bigger than 0x1FFFFFC. That's the range of a 'bl'.
If I press X on that call I can see that subroutine is referenced multiple times, but we will be intercepting only the calls coming from the subroutine i'm currently in. In this case sub_23286C. The function I will be hooking is cellHttpSendRequest btw.
This method is not the best one. You will either need to write the subroutine by hand and then copy it somewhere into memory where it can be executed, or write it in C/C++, compile the code and then edit the addresses by hand.
your code should look like this
Spoiler
Code:
void Hook(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6)
{
printf("r3 = 0x%llx | r4 = 0x%llx | r5 = 0x%llx | r6 = 0x%llx", r3, r4, r5, r6);
void(*hooked_func)(uint64_t, uint64_t, uint64_t, uint64_t) = (void(*)(uint64_t, uint64_t, uint64_t, uint64_t))0x006F84A0; <-- 0x006F84A0 is the OPD_s of the function I am hooking.
hooked_func(r3, r4, r5, r6);
}
What I mean by edit addresses by hand is that you will need to edit the opcodes for the call to printf to make it call the printf function inside the .self.
METHOD 2: Intercepting calls of separate functions using a sprx and a stub. (I will explain this using the same subroutine as previous method.)
This method is I think the easiest one. I will make it branch to a stub which will then branch to a function inside my sprx.
This method has 4 arguments: r3 - r6. The first thing to do in the stub is to save these arguments and the link register.
Code:
stdu r1, -0x60(r1)
mflr r0 //move link register to r0
std r0, 0x70(r1) // save link register
std r3, 0x40(r1) // save r3
std r4, 0x48(r1) // save r4
std r5, 0x50(r1) // save r5
std r6, 0x58(r1) // save r6
nop//we will rewrite this using our sprx. If you're using a static address then you can replace that by lis r11, [your_sub_address_high]
nop // ori r11, r11, [your_sub_address_low]
mtctr r11
bctrl // this is where the stub will jump to the sprx.
...
Copy this code in your plugin. This code willl replace the call on the first image to make it branch to our stub.
Spoiler
Code:
sys_pid_t get_process_id()
{
system_call_0(1);
return_to_user_prog(sys_pid_t);
}
int32_t write_process(uint64_t ea, const void * data, uint32_t size)
{
sys_pid_t pid = get_process_id();
system_call_4(0x389, (uint64_t)pid, ea, (uint64_t)data, size);
return_to_user_prog(int32_t);
}
void branch_link(uint32_t branchTo, uint32_t branchFrom)
{
uint32_t branch;
if (branchTo > branchFrom)
{
branch = 0x48000001 + (branchTo - branchFrom);
}
else
{
branch = 0x4C000001 - (branchFrom - branchTo);
}
write_process(branchFrom, &branch, 4);
}
Copy this code aswell. It will replace the nops inside your stub to make it branch to your sprx. This is done at runtime because the sprx has no fixed address.
Spoiler
Code:
void hook_function(uint64_t r3, uint64_t r4, uint64_t r5, uint64_t r6) <--- Notice how this function has the same amount of arguments as the subroutine i'm hooking. The types can be wrong though. It might be any integer argument. int32_t, char*, float*,...
{
printf("r3 = 0x%llx.\nr4 = 0x%llx.\nr5 = 0x%llx.\nr6 = 0x%llx", r3, r4, r5, r6);
}
void write_stub_hook(uint32_t address, uint32_t function)
{
uint32_t opcode[2];
opcode[0] = 0x3D600000 + ((function >> 16) & 0xFFFF); // lis r11, function@high
opcode[1] = 0x616B0000 + (function & 0xFFFF); // ori r11, r11, function@low
write_process(address, &opcode, 8);
}
When our hook_function returns to the stub, we will then need to forward the call to the original subroutine. For me it is sub_56FA7.
Code:
seg001:00500000 stdu r1, -0x60(r1) // 0x00500000 is not the best address to write the stub at.
seg001:00500004 mflr r0
seg001:00500008 std r0, 0x70(r1)
seg001:0050000C std r3, 0x40(r1)
seg001:00500010 std r4, 0x48(r1)
seg001:00500014 std r5, 0x50(r1)
seg001:00500018 std r6, 0x58(r1)
seg001:0050001C nop
seg001:00500020 nop
seg001:00500024 mtctr r11
seg001:00500028 bctrl
seg001:0050002C ld r3, 0x40(r1)
seg001:00500030 ld r4, 0x40(r1)
seg001:00500034 ld r5, 0x40(r1)
seg001:00500038 ld r6, 0x40(r1)
seg001:0050003C nop // we will replace this by "bl sub_56FA7" using the sprx.
seg001:00500040 ld r0, 0x70(r1)
seg001:00500044 mtlr r0
seg001:00500048 addi r1, r1, 0x60
seg001:0050004C blr
This is our stub. You can write it into vsh.elf and then encrypt it back to .self or just write it in asm and copy it into memory using our sprx. (You will need to calculate the size yourself)
Spoiler
Code:
void hook_stub()
{
__asm__
(
"stdu 1, -0x60(1);"
"mflr 0;"
"std 0, 0x70(1);"
"std 3, 0x40(1);"
"std 4, 0x48(1);"
"std 5, 0x50(1);"
"std 6, 0x58(1);"
"nop;"
"nop;"
"mtctr 11;"
"bctrl;"
"ld 3, 0x40(1);"
"ld 4, 0x40(1);"
"ld 5, 0x40(1);"
"ld 6, 0x40(1);"
"nop;"
"ld 0, 0x70(1);"
"mtlr 0;"
"addi 1, 1, 0x60;"
"blr;"
);
}
Everything is now setup.
All we need to do now is write the code inside our sprx.
Code:
extern "C" int _Project_prx_entry(void)
{
write_process(0x00500000/*the address of the stub*/, (void*)&hook_stub, 0x50/*size of hook_stub*/);
write_stub_hook(0x0050001C/*the address of the first nop*/, *(uint32_t*)&hook_function);
branch_link(0x0056FA74/*the address of the sub i'm hooking*/, 0x0050003C/*the address of the third nop in my stub*/);
branch_link(0x00500000/*the address of the stub*/, 0x00232DF0/*the original call to the function i'm hooking*/);
return SYS_PRX_RESIDENT;
}
PS: you can forward other functions calling 0x0056FA74 to the stub too.
Download VS2010 Project
METHOD 3: Intercepting every call to a function.
coming soon
METHOD 4: Intercepting every call to a function using a stub and a sprx.
coming soon