Hooks?
Hooks?
Can someone explain me how to hook a function?
i know on windows how hook works, is that similar to this or there are some differences?
i know on windows how hook works, is that similar to this or there are some differences?
-
- Posts: 409
- Joined: Tue Oct 09, 2007 4:22 am
In the CFW systemctrl_kernel library(probably others too, but that's the one I know off the top of my head), you can hook syscalls like
int func_addr = sctrlHENFindFunction(modname, libname, nid);
sctrlHENPatchSyscall(func_addr, &function_name);
That's one of the easier ways to do it.
int func_addr = sctrlHENFindFunction(modname, libname, nid);
sctrlHENPatchSyscall(func_addr, &function_name);
That's one of the easier ways to do it.
Programming with:
Geany + Latest PSPSDK from svn
Geany + Latest PSPSDK from svn
For hooking user to kernel syscall functions the above method is used. This will not effect a call to the function from a kernel module, it only effects user mode to kernel syscalls.
For hooking kernel-kernel or user-user functions, you need to go the address of the function, and replace the first instructions to jump to the address of your hook function. Then in your hook function, you can either process the data, or jump back into the original function.
For hooking kernel-kernel or user-user functions, you need to go the address of the function, and replace the first instructions to jump to the address of your hook function. Then in your hook function, you can either process the data, or jump back into the original function.
-
- Posts: 409
- Joined: Tue Oct 09, 2007 4:22 am
-
- Posts: 91
- Joined: Sun Feb 22, 2009 8:32 am
- Location: Melbourne Australia ZOMG
Code: Select all
#define JAL_OPCODE 0x0C000000
#define J_OPCODE 0x08000000
#define MAKE_JUMP(a, f) _sw(J_OPCODE | (((u32)(f) & 0x0ffffffc) >> 2), a);
#define MAKE_CALL(a, f) _sw(JAL_OPCODE | (((u32)(f) >> 2) & 0x03ffffff), a);
...
...
int orig_jump(int var1, int var2...)
{
asm("1st instruction from original function");
asm("2nd instruction from original function");
asm("j original_function_address+8"); //will return back to 'hooked' after original function is finished
asm("nop");
return 0; //should not reach here
}
int hooked(int var1, int var2...)
{
//do stuff
return orig_jump(var1, var2...) //calls original function
}
//To do the patch
MAKE_JUMP(address of original, hooked)
//you need to add a nop after the jump too
Last edited by Torch on Sun Mar 08, 2009 8:59 pm, edited 2 times in total.
branch control instructions are : J, JAL, JR, JALR, Bxx, etc.
NOTE: if one of the first two instructions in the original function is a relative branch transfer, you'll have an issue because you need to recompute the target offset so you need a stub like it if insn2 is a relative branch instruction :
examples of auto-generated stub functions :
examples of patched functions :
your hooked functions :
Here is an example of an untested function to do all the stuff :
NOTE: if one of the first two instructions in the original function is a relative branch transfer, you'll have an issue because you need to recompute the target offset so you need a stub like it if insn2 is a relative branch instruction :
Code: Select all
original_function_stub:
insn1
beq ..., 0f // insn2 modified (was beq ..., original_function_exit)
insn3
j original_function_fallback
nop
0: j original_function_exit // ok
nop
...
and
/* existing function to patch in a module */
original_function:
insn1 ----> J hooked_function
insn2 ----> nop
insn3
original_function_fallback: // = ((int)&original_function_1) + 3
...
Code: Select all
original_function_1_stub:
insn1
j original_function_1_fallback
insn2
original_function_2_stub:
insn1 // insn1 is a branch control instruction
insn2 // only insn2 can fit a branch delay slot here
j original_function_2_fallback
nop
original_function_3_stub:
insn1
insn2 // insn2 is a branch control instruction
nop // necessary because the next J cannot fit a branch delay slot
j original_function_3_fallback
nop
...
Code: Select all
/* existing function 1 to patch in a module */
original_function_1:
insn1 ----> J hooked_function_1
insn2 ----> nop
original_function_1_fallback: // = ((int)&original_function_1) + 2
...
/* existing function 2 to patch in a module */
original_function_2:
insn1 ----> J hooked_function_2
insn2 ----> nop
original_function_2_fallback: // = ((int)&original_function_2) + 2
...
/* existing function 3 to patch in a module */
original_function_3:
insn1 ----> J hooked_function_3
insn2 ----> nop
original_function_3_fallback: // = ((int)&original_function_3) + 2
...
Code: Select all
... hooked_function_1(...)
{
... your code ...
... original_function_1_stub(...);
[... your code ...]
}
... hooked_function_2(...)
{
... your code ...
... original_function_2_stub(...);
[... your code ...]
}
... hooked_function_3(...)
{
... your code ...
... original_function_3_stub(...);
[... your code ...]
}
...
Code: Select all
void *patch_jump(int *original, int *hooked, int *stub)
{
if (is_branch_control_instruction(original[0]))
{
if (is_relative_branch_control_instruction(original[0]))
{
stub[0] = (original[0]&0xFFFF0000)|4; // insn1 modified
stub[1] = original[1]; // insn2
MAKE_JUMP(&stub[2], (int)(original + 2)); // J original_function_fallback
stub[3] = 0; // nop
MAKE_JUMP(&stub[4], (int)(original + 0 + (original[0]&0xFFFF)));
stub[5] = 0; // nop
writeback_dcache_and_invalidate_icache_range(stub, stub + 6);
}
else
{
stub[0] = original[0]; // insn1
stub[1] = original[1]; // insn2
MAKE_JUMP(&stub[2], (int)(original + 2)); // J original_function_fallback
stub[3] = 0; // nop
writeback_dcache_and_invalidate_icache_range(stub, stub + 4);
}
}
else if (is_branch_control_instruction(original[1]))
{
if (is_relative_branch_control_instruction(original[1]))
{
stub[0] = original[0]; // insn1
stub[1] = (original[1]&0xFFFF0000)|4; // insn2 modified
stub[2] = original[2]; // insn3
MAKE_JUMP(&stub[3], (int)(original + 3)); // J original_function_fallback
stub[4] = 0; // nop
MAKE_JUMP(&stub[5], (int)(original + 1 + (original[1]&0xFFFF)));
stub[6] = 0; // nop
writeback_dcache_and_invalidate_icache_range(stub, stub + 7);
}
else
{
stub[0] = original[0]; // insn1
stub[1] = original[1]; // insn2
stub[2] = 0; // nop
MAKE_JUMP(&stub[3], (int)(original + 2)); // J original_function_fallback
stub[4] = 0; // nop
writeback_dcache_and_invalidate_icache_range(stub, stub + 5);
}
}
else
{
stub[0] = original[0]; // insn1
MAKE_JUMP(&stub[1], (int)(original + 2)); // J original_function_fallback
stub[2] = original[1]; // insn2
writeback_dcache_and_invalidate_icache_range(stub, stub + 3);
}
MAKE_JUMP(&original[0], hooked); // insn1 ---> J hooked_function
original[1] = 0; // insn2 ---> nop
writeback_dcache_and_invalidate_icache_range(original, original + 2);
return stub;
}
I edited heavily the previous post so the stub generator can handle the case when one of first two instructions in the original function contains a relative branch instruction. You need a .S file to contain your stub to overwrite (for each original function to patch, you need a stub function of 8 instructions) :
when you want to patch an original function with your hooked function, you also pass the stub function address :
Code: Select all
.global your_stub_function
.enter your_stub_function
your_stub_function:
jr $ra
nop
nop
nop
nop
nop
nop
nop
.end your_stub_function
...
Code: Select all
extern int stub_function(int);
int hooked_function(int a0)
{
int result;
// do your stuff here
result = stub_function(a0);
// do your other stuff here
return result;
}
...
patch_jump((int *)&original_function, (int *)&hooked_function, (int *)&stub_function);
...
-
- Posts: 409
- Joined: Tue Oct 09, 2007 4:22 am