Random Homebrew: 3D dot ball
Demo effect of a 3-D ball made from dots.
Friends: Coding 'n Cracking - Nymphaea - PS3 Forum - darkforestgroup - daxhordes.org - Tgames - coldbird - gopsp.it - pspstation.org - prometheus - hgoel.info - MakeSmartTV - ps vita

Hook/patch sub routines of a game

Forum rules
Any post not directly related to programming will be moderated.
Do not request people to code something for you.
Avoid posting messages that do not bring anything to the conversation. We want the threads in this subforum to stay focused.

Hook/patch sub routines of a game

Postby PSPWizard » Mon Sep 19, 2011 7:17 pm

Hi there,

I'm currently trying to patch a sub routine like this one to pass it to my kernel plugin:
Code: Select all
; ======================================================
; Subroutine sub_0041088C - Address 0x0041088C
sub_0041088C:      ; Refs: 0x0040E6E0 0x00412868
   0x0041088C: 0x27BDFF60 '`..'' - addiu      $sp, $sp, -160
   0x00410890: 0x8C860000 '....' - lw         $a2, 0($a0)


What've done so far:
I've created my own stub and passing setting the 1st 2 instructions from the original function (as seen above). Than I do replace this 2 instructions with a syscall to my kernel mode function.
once my kernel mode function finished his stuff I do call the stub which will execute the 2 original instructions and than do a call to the position after the 2 original instruction..

The patching is done like this:
Code: Select all
int interrupt = pspSdkDisableInterrupts();
       //copy original to stub
   patchStub[0] = originalFunc[0];
   MAKE_JUMP((int)&patchStub[1], (int)(originalFunc)+8);
   patchStub[2] = originalFunc[1];
        //patching original
   MAKE_SYSCALL((int)&originalFunc[0], sceKernelQuerySystemCall(patchFunc));
   originalFunc[1] = 0x0; //nop

   sceKernelDcacheWritebackInvalidateAll();
   sceKernelIcacheInvalidateAll();

   pspSdkEnableInterrupts(interrupt);
   return patchStub;


My kernel mode function is well called - but only once and the PSP crashes once back in the original code. Does anyone has an idea what the issue might be ?

Thanks in advance for any hints...
PSPWizard
 
Posts: 125
Joined: Thu Feb 10, 2011 11:47 am

Re: Hook/patch sub routines of a game

Postby m0skit0 » Tue Sep 20, 2011 3:18 pm

- Where do you store original entry instructions for the function you want to patch (what does copy original to stub mean)?
- How do you restore them?
- Did you check they are properly restored by your kernel function?
- What exception are you getting?
I wanna lots of mov al,0xb
Image
"just not into this RA stuffz"
User avatar
m0skit0
Guru
 
Posts: 4786
Joined: Mon Sep 27, 2010 6:01 pm

Re: Hook/patch sub routines of a game

Postby codestation » Tue Sep 20, 2011 6:49 pm

How do you return exactly you return after you execute those 2 instructions in the stub? you can't JAL directly since that won't work, you need to go back via the jr $ra method so the interrupt manager (or whatever module deal with this) can put you back after the syscall (if you give a look, that $ra doesn't point back to usermode, it goes to another module who redirects you back to the userspace).

You still have a 2nd problem, IIRC, the context change from user to kernel mode will also switch the stack pointer ($sp) to the kernel mode one, so if you are executing those 2 opcodes in kernel mode, then when you go back the $sp register will remain the same since you only changed the kernel stack pointer.

I used this method with my early version of one of my plugins with good results:
Spoiler
You need to allocate a trampoline located in user space, copy these 2 opcodes to that space, write a JA at the end of the trampoline to return to the original code and make a JA and a nop from the original code to that space, do your syscall, then when you go back it will execute those 2 opcodes and return to the original function.

Code: Select all
trampoline:
syscall 0xC0DE // overwrite it with your syscall
nop   // put your opcodes here
nop   // and here
JA orig_code+4 // calculate the jump and write it in here
nop
Plugin list
Working on: Python (django, sqlalchemy, PyQt, etc) + Lua
Repositories: github, bitbucket, google code
Just feel the code..
opencma/vitamtp for Archlinux
User avatar
codestation
Big Beholder
 
Posts: 1277
Joined: Wed Jan 19, 2011 3:45 pm
Location: /dev/negi

Re: Hook/patch sub routines of a game

Postby PSPWizard » Tue Sep 20, 2011 6:51 pm

Hi,

well....I've defined a stub function in my plugin like this:
Code: Select all
.global gameFunction_Stub
.ent gameFunction_Stub

gameFunction_Stub:
   j   $ra
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
.end gameFunction_Stub


"copying" the original instructions to the stub and doing the "call back" to original is done with this lines:
Code: Select all
patchStub[0] = originalFunc[0];
   MAKE_JUMP((int)&patchStub[1], (int)(originalFunc)+8);
   patchStub[2] = originalFunc[1];

where patchStub is the address of the stub function and originalFunc is the address of the original function I do patch with this...

within my coding I do have my own function just calling the stub function containing the original instructions copied like you see above:
Code: Select all
void gameFunction_Patched(int a0, int a1){

   int k1 = pspSdkSetK1(0);
   char txt[100];
   sprintf(txt, "GameFunction 0x%X, 0x%X\r\n", a0, a1);
   debuglog(txt, 0);

   pspSdkSetK1(k1);
   gameFunction_Stub(a0, a1);
}


The exeption is mainly a bus error or I/O exception which is somewhere in the original coding. It looks a bit randomly to my but it seem to have the same root cause in the majority of the cases:
the coding is trying to recieve or store data to a specific address like "lw $a0, 10($sp)" or "sw $a1, 0($t0) where the values in the adress registers seem to be valid, but do not point to the right location.

What I've seen from the disasm using psplink the original function is e.g. at adress 0x04422110 before the syscall, but is at 0x84422110 after the syscall. I don't know whether this has to do with each other, or the 0x80000000 is just a different "view" on the same data in the memory (like the cached/uncached accesses to the same memory address)..

I do hope it will help to understand what I've done so far and enable you to provide some hints :)
PSPWizard
 
Posts: 125
Joined: Thu Feb 10, 2011 11:47 am

Re: Hook/patch sub routines of a game

Postby PSPWizard » Tue Sep 20, 2011 6:55 pm

@codestation: thanks for explaining this in detail. I was not aware that the stack pointer is dependend on user/kernel mode...

Would you suggest to get user memory space for the "trampoline" with sceKernelAllocPartitionMemory ?

If I get you right I do replace the first instructions of the original function with a jal to that "userspace" trampoline and place the syscall as well as the replaced original instructions in this trampoline ?

I will try this. Sounds now a bit obvios to me :)
PSPWizard
 
Posts: 125
Joined: Thu Feb 10, 2011 11:47 am

Re: Hook/patch sub routines of a game

Postby codestation » Tue Sep 20, 2011 7:18 pm

PSPWizard wrote:Would you suggest to get user memory space for the "trampoline" with sceKernelAllocPartitionMemory ?

Exactly. Now if you want something more challenging, you can try to make it without allocations and write the stub directly on the user mode stack :D

you can try writting this in the original code:

Code: Select all
orig_func:
move $a0, $sp
syscall 0xC0DE
JA sp_value
nop


then when you are in kernel mode just write a little func in the user stack who executes these opcodes and do a JA orig_func+16. (you will know the address of the user stack since you passed it to your syscall function in its 1st param). This approach is more hard to debug if something goes wrong but its a lot cooler and you don't need memory allocations :ugeek:
Plugin list
Working on: Python (django, sqlalchemy, PyQt, etc) + Lua
Repositories: github, bitbucket, google code
Just feel the code..
opencma/vitamtp for Archlinux
User avatar
codestation
Big Beholder
 
Posts: 1277
Joined: Wed Jan 19, 2011 3:45 pm
Location: /dev/negi

Re: Hook/patch sub routines of a game

Postby PSPWizard » Tue Sep 20, 2011 7:35 pm

Hi,

again thanks alot...My trampoline does work pretty well. I only needed to add stuff to push the a0/a1 register onto the stack befor doing syscall and restoring them back once syscall has finished...
Now it works very smooth ....like a charm :)

Thanks a lot. For the time being I do keep it with memory allocation to keep it simple :) for me...

best regards
PSPWizard..
PSPWizard
 
Posts: 125
Joined: Thu Feb 10, 2011 11:47 am


Return to Programming

Who is online

Users browsing this forum: m0skit0 and 1 guest