forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Hooks?

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
roby65



Joined: 01 Jun 2008
Posts: 55
Location: Mid Italy

PostPosted: Fri Mar 06, 2009 11:28 pm    Post subject: Hooks? Reply with quote

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?
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
coolkehon



Joined: 20 Oct 2008
Posts: 355

PostPosted: Sat Mar 07, 2009 1:30 am    Post subject: Reply with quote

i would like to add to this question what is a hook i keep seeing it everyonce in a while libconfig, SDL, etc and also how do i use / create a hook
Back to top
View user's profile Send private message MSN Messenger
Pirata Nervo



Joined: 09 Oct 2007
Posts: 409

PostPosted: Sat Mar 07, 2009 3:28 am    Post subject: Reply with quote

@coolkehon http://en.wikipedia.org/wiki/Hooking
@roby, http://forums.ps2dev.org/viewtopic.php?t=9245&highlight=hooking
_________________

Upgrade your PSP
Back to top
View user's profile Send private message
NoEffex



Joined: 27 Nov 2008
Posts: 108

PostPosted: Sat Mar 07, 2009 7:28 am    Post subject: Reply with quote

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.
_________________
Programming with:
Geany + Latest PSPSDK from svn
Back to top
View user's profile Send private message
Torch



Joined: 28 May 2008
Posts: 842

PostPosted: Sun Mar 08, 2009 12:46 am    Post subject: Reply with quote

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.
Back to top
View user's profile Send private message
Pirata Nervo



Joined: 09 Oct 2007
Posts: 409

PostPosted: Sun Mar 08, 2009 6:23 am    Post subject: Reply with quote

@Torch, is assembly the only way to do it?
_________________

Upgrade your PSP
Back to top
View user's profile Send private message
Torch



Joined: 28 May 2008
Posts: 842

PostPosted: Sun Mar 08, 2009 6:25 am    Post subject: Reply with quote

Pirata Nervo wrote:
@Torch, is assembly the only way to do it?

Yes. Because the user-user or kernel-kernel jumps are directly in code from one module to a function address in another module. The return address is stored in $ra register to go back to the original code which called it.
Back to top
View user's profile Send private message
slasher2661996



Joined: 22 Feb 2009
Posts: 91
Location: Melbourne Australia ZOMG

PostPosted: Sun Mar 08, 2009 8:38 am    Post subject: Reply with quote

Torch could you post an example?
Back to top
View user's profile Send private message
Torch



Joined: 28 May 2008
Posts: 842

PostPosted: Sun Mar 08, 2009 4:38 pm    Post subject: Reply with quote

Code:
#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
Back to top
View user's profile Send private message
Torch



Joined: 28 May 2008
Posts: 842

PostPosted: Sun Mar 08, 2009 8:54 pm    Post subject: Reply with quote

There was a small error, I edited the post.
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sun Mar 08, 2009 10:34 pm    Post subject: Reply with quote

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 :
Code:

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
    ...



examples of auto-generated stub functions :
Code:

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
...


examples of patched functions :
Code:

/* 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
    ...


your hooked functions :
Code:

... 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 ...]
}

...


Here is an example of an untested function to do all the stuff :
Code:

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;
}
Back to top
View user's profile Send private message
hlide



Joined: 10 Sep 2006
Posts: 750

PostPosted: Sun Mar 08, 2009 11:54 pm    Post subject: Reply with quote

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) :
Code:

.global your_stub_function
.enter your_stub_function
your_stub_function:
    jr $ra
    nop
    nop
    nop
    nop
    nop
    nop
    nop
.end your_stub_function
...


when you want to patch an original function with your hooked function, you also pass the stub function address :
Code:

    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);
    ...
Back to top
View user's profile Send private message
Pirata Nervo



Joined: 09 Oct 2007
Posts: 409

PostPosted: Mon Mar 09, 2009 2:36 am    Post subject: Reply with quote

Thank you very much hlide and Torch :)
_________________

Upgrade your PSP
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group