Direct Call x86 Assembly

0

I'm trying to essentially patch in a dll a far call to my own address instead of the one compiled already.

Here is the bytes I am trying to patch :

{ 0xFF, 0x15, 0x30, 0x20, 0x00, 0x10 }

Which should translate to : call DWORD PTR ds:0x10002030

Which I believe means the same thing as : call [0x10002030]

Yes, I am trying to patch an actual call to an IAT function to something else. Because the iat is essentially storing a integer that gets later assigned to the actual address of the api function, to call the function we have to dereference the address given to us from the IAT.

Now because I want to patch this to go to my own function, I am not going to be needing to dereference anything. Now the issue is the original dereference call is 6 bytes long, so I need to stay at 6 bytes or lower.

I'm trying to essentially find a way to do a call to an address, which is not relative (important!) and is not inside the current module I am in, and finally do it in less than or equal to 6 bytes.

I want something like so :

call 0xDEADBEEF

but I don't want 0xDEADBEEF to be a relative address. I want to directly call 0xDEADBEEF

To reiterate, I need to specifically patch this call, there is no other way around it. A normal IAT hook will not do in this situation.

Edit :

I've been looking into it some more and it seems that

push 0xdeadbeef

ret

might work, but I have found an issue. Because I have to handle the return myself, I can not do that in 6 bytes. But I think I know a way I can.

Original call goes from : call [0x10002030] to :

push jFunction 

ret

And jFunction would be essentially a stub of sorts :

mov eax, 0xDEADBEEF
call eax

But now the issue is how do I get back to my original execution?

Using a simple

pop ebx
ret

causes it to jmp back to the original main function, not to the instruction after the ret.

As I stated before because of the packer I am using, I can not use relative offsets, so again in this situation I cannot determine the relative offset between the start of the main function and the instruction I would like to go to. And I cannot push the wanted address to the "jFunction" because I only have 6 bytes to deal with.

I'm starting to think this is impossible without relative addresses.

Here is my current test code : x86 (debug) MSVC 2015 I am using inline assembly and __declspec(naked) to easily debug the solution instead of patching what I need and testing.

Current Testing Code

assembly
x86
call
asked on Stack Overflow Sep 11, 2016 by (unknown user) • edited Sep 13, 2016 by (unknown user)

1 Answer

0

You know the address of the call instruction you're patching, so calculate 0xdeadbeef - start_of_next_insn to get the right rel32 displacement for a normal near direct relative call (5 bytes).

The other not-crazy options are to replace the function pointer in memory, or to change the addressing mode to load the pointer from somewhere else, but making it a simple direct call is obviously best.

This always works in 32-bit mode, but in 64-bit mode it's possible for two addresses to be more than +-2GiB away (out of range for a rel32). But we know you're in 32-bit mode because FF 15 4bytes decodes as an absolute addressing mode. In 64-bit mode, that would be a RIP-relative function pointer. RIP-relative took over the no-SIB encoding for a [disp32] addressing mode.

This is almost a duplicate of Call an absolute pointer in x86 machine code, answering mostly to address padding efficiently instead of putting a NOP before or after the call.

Pad it with a 0x67 address-size prefix (which will have no effect) to make it 6 bytes. GNU ld already does this when relaxing an indirect call to a near direct call, with objdump -d /bin/ls I can see some addr32 call ... instructions, so this is safe (CPU vendors can't change the meaning of 67 E8 into some new instruction without breaking lots of existing binaries).

In general it's not safe to assume that a prefix will have no effect in the future (e.g. rep bsr runs as lzcnt on CPUs that support it), but this case is safe because of existing usage, like rep ret.

answered on Stack Overflow Apr 27, 2018 by Peter Cordes

User contributions licensed under CC BY-SA 3.0