I'm injecting a c++ DLL into a game and I'd like to hook a function to some of my own code. Since the DLL is mapped to a different location each time, It would be easier to have direct jumps and calls. Also, because this is a hook I don't want to change the stack or registers for when I go back to the function.
I 开发者_如何学Godeclare a char* to store the Asm so that I will have a pointer to it.(char* asm="\x00";) If you could provide hex, that would save me some time.
Ive tried using FF and EA for the calls and jumps but I guess I just don't understand how those work. When I used them I noticed that I now had a colon in the operation.
JMP FAR FWORD PTR DS:[00000000]
This didn't work and it still didn't work after I tried to use a pointer to the jump location.
Here's the assembly that I was using before I started trying different methods:
01270000 50 PUSH EAX
01270001 57 PUSH EDI
01270002 E8 E9CC1BFF CALL fwound.0042CCF0
01270007 5F POP EDI
01270008 58 POP EAX
01270009 50 PUSH EAX //replacements
0127000A 8D4C24 7C LEA ECX,DWORD PTR SS:[ESP+7C] //
0127000E - E9 36D11BFF JMP fwound.0042D149
I made that block using Olly, therefore it knew the relevant jumps/calls needed at the time.
After that Asm is in the memory, I then have to write over two operations(which are replaced) in the function to jump to this location.
So, How could I fix my Asm block to use direct jumps and calls?
You can code it like this (gcc-style / AT&T assembly syntax):
jmp *.Ltgtaddr
.Ltgtaddr: .long absoluteAddrOfFunctionToCall
This assembles into ten bytes (on 32bit x86) - ff 25
for the absolute jmp with 32bit memory operand, then the four bytes with the address of the following word, followed by the contents which then is the (absolute) target address of your code.
Edit: I've updated the section below with a compiled and tested example.
You can, from C sourcecode, dynamically create such a trampoline. Example source (requires 32bit x86, left as an exercise to the reader how to convert the trampoline to 64bit):
#include <sys/mman.h>
#include <stdio.h>
void oneWay(char *str, int arg)
{ printf("string is \"%s\", int is %d\n", str, arg); }
void otherWay(char *str, int arg)
{ printf(str, arg); printf("\n"); }
void *trampGen(void *tgtAddr)
{
char *trampoline = mmap(NULL, 10, PROT_EXEC | PROT_WRITE | PROT_READ,
MAP_PRIVATE | MAP_ANON, -1, 0);
trampoline[0] = (char)0xff; trampoline[1] = (char)0x25;
*(char**)(trampoline+2) = trampoline + 6;
*(void**)(trampoline+6) = tgtAddr;
return trampoline;
}
int main(int argc, char **argv)
{
void * (*funcptr)(char*, int) = trampGen(oneWay);
*funcptr("Test %d String", 12345);
*(void **)(((char *)funcptr) + 6) = otherWay;
*funcptr("Test %d String", 12345);
munmap(funcptr, 10);
return 0;
}
Output for me:
$ ./tt
string is "Test %d String", int is 12345
Test 12345 String
Note it's slightly inefficient to set aside an entire MMU page to use only ten bytes of it. Implement your own memory manager for trampolines if you need more than one of them ...
I never tried this kind of things,
but I think you should use the offset from a known memory location of the game (to find with ollydbg) so every time you add this (fixed) offset to the (variable) address. This address could be, for example, the return address found at ss:ebp
(since your function is called by the game) and the offset from that is computed with help of ollyDBG.
精彩评论