2
//src = the place to write the hook, dst is the function you jump to, len is length 
//of stolen bytes (MUST fall on a boundray between instructions)
BYTE* TrampHook32(BYTE* src, BYTE* dst, const DWORD len)
{
    //Make sure length is long enough for a jump
    if (len < 5) return 0;

    //Allocate memory to execute the stolen bytes
    BYTE* gateway = (BYTE*)VirtualAlloc(0, len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    //Copy the stolen bytes into allocated memory
    memcpy_s(gateway, len, src, len);

    //Calculate the relavibe address of the jump
    uintptr_t gatewayRelativeAddr = src - gateway - 5;

    //Add a jump at the end of the stolen bytes back to the original function
    *(gateway + len) = 0xE9;

    //Add the relative address into the jump
    *(uintptr_t*)((uintptr_t)gateway + len + 1) = gatewayRelativeAddr;

    //This inserts a jump to dst into the original function (pointed to by src.)
    //Note: the function at dst must contain a jump to gateway otherwise this won't work
    Detour32(src, dst, len);

    //Return a pointer to the gateway
    return gateway;
}

This function is from a GuidedHacking tutorial. The purpose is to hook a function without destroying its original functionality by putting all the bytes overwritten by the jump instruction in a spot in virtual memory to be executed after the injected code finishes. The line uintptr_t gatewayRelativeAddr = src - gateway - 5; seems to imply that gateway will always be less than src considering theres no such thing as a negative relative address, but how can the guy who wrote this be confident that the address returned by VirtualAlloc will be less than the one taken in to the function as the src parameter? Or maybe an RVA that goes past the limits of a DWORD will simply underflow to a huge number which the CPU will see and also end overflowing to a reasonable number therefore making this valid? pls help

1
  • Hi and welcome to RE.SE. Please turn to the help center or ask on our meta site if anything comes up.
    – 0xC0000022L
    Commented Jan 18, 2022 at 7:57

1 Answer 1

2

From the Intel 64 and IA-32 Architecture manual:

Jump instruction — The JMP (jump) instruction unconditionally transfers program control to a destination instruction. The transfer is one-way; that is, a return address is not saved. A destination operand specifies the address (the instruction pointer) of the destination instruction. The address can be a relative address or an absolute address. A relative address is a displacement (offset) with respect to the address in the EIP register. The destination address (a near pointer) is formed by adding the displacement to the address in the EIP register. The displacement is specified with a signed integer, allowing jumps either forward or backward in the instruction stream.

Because the jump used is relative (0xE9) it doesn't matter if it is negative. Because jmp is relative to the instruction and the instruction takes 5 bytes -5 is used.

Further explanation is here in Calculation of jmp address through subtraction

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.