Example #1
0
EASYHOOK_NT_INTERNAL DbgRelocateRIPRelative(
	        ULONGLONG InOffset,
	        ULONGLONG InTargetOffset,
            BOOL* OutWasRelocated)
{
/*
Description:

    Check whether the given instruction is RIP relative and
    relocates it. If it is not RIP relative, nothing is done.

Parameters:

    - InOffset

        The instruction pointer to check for RIP addressing and relocate.

    - InTargetOffset

        The instruction pointer where the RIP relocation should go to.
        Please note that RIP relocation are relocated relative to the
        offset you specify here and therefore are still not absolute!

    - OutWasRelocated

        TRUE if the instruction was RIP relative and has been relocated,
        FALSE otherwise.
*/
#ifndef _M_X64
	return FALSE;
#else
	NTSTATUS            NtStatus;
	CHAR					Buf[MAX_PATH];
	ULONG					AsmSize;
	ULONG64					NextInstr;
	CHAR					Line[MAX_PATH];
	LONG					Pos;
	LONGLONG				RelAddr;
	LONGLONG				MemDelta = InTargetOffset - InOffset;

	ASSERT(MemDelta == (LONG)MemDelta);

    *OutWasRelocated = FALSE;

	// test field...
	/*BYTE t[10] = {0x8b, 0x05, 0x12, 0x34, 0x56, 0x78};

	InOffset = (LONGLONG)t;

	MemDelta = InTargetOffset - InOffset;
*/
	if(!RTL_SUCCESS(DebugControl->Disassemble(InOffset, 0, Buf, sizeof(Buf), &AsmSize, &NextInstr)))
		THROW(STATUS_INVALID_PARAMETER_1, L"Unable to disassemble entry point. ");

	Pos = RtlAnsiIndexOf(Buf, '[');

	if(Pos < 0)
		RETURN;

	// parse content
	if(RtlAnsiSubString(Buf, Pos + 1, RtlAnsiIndexOf(Buf, ']') - Pos - 1, Line, MAX_PATH) != 16)
		RETURN;

	if(!RtlAnsiHexToLongLong(Line, 16, &RelAddr))
		RETURN;
	
	// verify that we are really RIP relative...
	RelAddr -= NextInstr;

	if(RelAddr != (LONG)RelAddr)
		RETURN;

	if(*((LONG*)(NextInstr - 4)) != RelAddr)
		RETURN;

	/*
		Just relocate this instruction...
	*/
	RelAddr = RelAddr - MemDelta;

	if(RelAddr != (LONG)RelAddr)
		THROW(STATUS_NOT_SUPPORTED, L"The given entry point contains at least one RIP-Relative instruction that could not be relocated!");

	// copy instruction
	RtlCopyMemory((void*)InTargetOffset, (void*)InOffset, (ULONG)(NextInstr - InOffset));

	*((LONG*)(InTargetOffset + (NextInstr - InOffset) - 4)) = (LONG)RelAddr;

    *OutWasRelocated = TRUE;

	RETURN;

THROW_OUTRO:
FINALLY_OUTRO:
    return NtStatus;
#endif
}
Example #2
0
EASYHOOK_NT_INTERNAL LhRelocateRIPRelativeInstruction(
            ULONGLONG InOffset,
            ULONGLONG InTargetOffset,
            BOOL* OutWasRelocated)
{
/*
Description:

    Check whether the given instruction is RIP relative and
    relocates it. If it is not RIP relative, nothing is done.
    Only applicable to 64-bit processes, 32-bit will always
    return FALSE.

Parameters:

    - InOffset

        The instruction pointer to check for RIP addressing and relocate.

    - InTargetOffset

        The instruction pointer where the RIP relocation should go to.
        Please note that RIP relocation are relocated relative to the
        offset you specify here and therefore are still not absolute!

    - OutWasRelocated

        TRUE if the instruction was RIP relative and has been relocated,
        FALSE otherwise.
*/

#ifndef _M_X64
    return FALSE;
#else
#ifndef MAX_INSTR
#define MAX_INSTR 100
#endif
    NTSTATUS            NtStatus;
	CHAR                Buf[MAX_INSTR];
    ULONG               AsmSize;
    ULONG64             NextInstr;
	CHAR                Line[MAX_INSTR];
    LONG                Pos;
    LONGLONG            RelAddr;
    LONGLONG            MemDelta = InTargetOffset - InOffset;

	ULONGLONG           RelAddrOffset = 0;
    LONGLONG            RelAddrSign = 1;

    ASSERT(MemDelta == (LONG)MemDelta,L"reloc.c - MemDelta == (LONG)MemDelta");

    *OutWasRelocated = FALSE;

    // test field...
    /*
    BYTE t[10] = {0x8b, 0x05, 0x12, 0x34, 0x56, 0x78};
    // udis86 outputs: 0000000000000000 8b0512345678     mov eax, [rip+0x78563412]

    InOffset = (LONGLONG)t;

    MemDelta = InTargetOffset - InOffset;
    */
    // Disassemble the current instruction
    if(!RTL_SUCCESS(LhDisassembleInstruction((void*)InOffset, &AsmSize, Buf, sizeof(Buf), &NextInstr)))
        THROW(STATUS_INVALID_PARAMETER_1, L"Unable to disassemble entry point. ");
    
    // Check that the address is RIP relative (i.e. look for "[rip+")
    Pos = RtlAnsiIndexOf(Buf, '[');
      if(Pos < 0)
        RETURN;

    if (Buf[Pos + 1] == 'r' && Buf[Pos + 2] == 'i' && Buf[Pos + 3] == 'p' &&  (Buf[Pos + 4] == '+' || Buf[Pos + 4] == '-'))
    {
        /*
          Support negative relative addresses
          
          https://easyhook.codeplex.com/workitem/25592
            e.g. Win8.1 64-bit OLEAUT32.dll!VarBoolFromR8
            Entry Point:
              66 0F 2E 05 DC 25 FC FF   ucomisd xmm0, [rip-0x3da24]   IP:ffc46d4
            Relocated:
              66 0F 2E 05 10 69 F6 FF   ucomisd xmm0, [rip-0x996f0]   IP:100203a0
        */
        if (Buf[Pos + 4] == '-')
            RelAddrSign = -1;
        
        Pos += 4;
        // parse content
		if (RtlAnsiSubString(Buf, Pos + 1, RtlAnsiIndexOf(Buf, ']') - Pos - 1, Line, MAX_INSTR) <= 0)
            RETURN;

        // Convert HEX string to LONGLONG
		RelAddr = RtlAnsiHexToLongLong(Line, MAX_INSTR);
        if (!RelAddr)
            RETURN;

        // Apply correct sign
        RelAddr *= RelAddrSign;

        // Verify that we are really RIP relative (i.e. must be 32-bit)
        if(RelAddr != (LONG)RelAddr)
            RETURN;
        
        /*
          Ensure the RelAddr is equal to the RIP address in code
         
          https://easyhook.codeplex.com/workitem/25487
		  Thanks to Michal for pointing out that the operand will not always 
          be at *(NextInstr - 4)
		  e.g. Win8.1 64-bit OLEAUT32.dll!GetVarConversionLocaleSetting 
              Entry Point:
                 83 3D 71 08 06 00 00    cmp dword [rip+0x60871], 0x0  IP:ffa1937
              Relocated:
                 83 3D 09 1E 0B 00 00    cmp dword [rip+0xb1e09], 0x0  IP:ff5039f
        */
		for (Pos = 1; Pos <= NextInstr - InOffset - 4; Pos++) {
			if (*((LONG*)(InOffset + Pos)) == RelAddr) {
				if (RelAddrOffset != 0) {
					// More than one offset matches the address, therefore we can't determine correct offset for operand
                    RelAddrOffset = 0;  
                    break;
				}

				RelAddrOffset = Pos;
			}
		}

		if (RelAddrOffset == 0) {
			THROW(STATUS_INTERNAL_ERROR, L"The given entry point contains a RIP-relative instruction for which we can't determine the correct address offset!");
		}

		/*
            Relocate this instruction...
        */
        // Adjust the relative address
        RelAddr = RelAddr - MemDelta;
        // Ensure the RIP address can still be relocated
        if(RelAddr != (LONG)RelAddr)
            THROW(STATUS_NOT_SUPPORTED, L"The given entry point contains at least one RIP-Relative instruction that could not be relocated!");

        // Copy instruction to target
        RtlCopyMemory((void*)InTargetOffset, (void*)InOffset, (ULONG)(NextInstr - InOffset));
        // Correct the rip address
        *((LONG*)(InTargetOffset + RelAddrOffset)) = (LONG)RelAddr;

        *OutWasRelocated = TRUE;
    }

    RETURN;

THROW_OUTRO:
FINALLY_OUTRO:
    return NtStatus;
#endif
}