开发者

Directly call/jump in ASM without using relevance(x86)

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜