0

I am trying to perform a live patch to some 64 bit intel code.

Basically, I like to replace a few instructions with a larger set of instructions.

The patching will be performed by a program written in C, and I like to make use of GCC's inline assembler for that.

What I am struggling with is how to calculate the jmp and call instructions, knowing only the absolute 64bit addresses of the original code and my replacement routine.

To give some background, I am trying to perform the patch that's outlined here: Hacking the OS X Kernel for Fun and Profiles.

But instead of modifying the kernel file, I am writing a KEXT that is already able to locate the relevant set of these 6 instructions that need to be changed:

    mov    %r15,%rdi
    xor    %esi,%esi
    xor    %edx,%edx
    xor    %ecx,%ecx
    mov    $0x1b,%r8d
    callq  <threadsignal+224>

I know the address of each of these above instructions.

Now, I would want to write the replacement code like this:

void patchcode ()
{
    current_thread (); // leaves result in rax, apparently
    __asm__ volatile (
        "xor    %edi,%edi           \n"
        "xor    %esi,%esi           \n"
        "mov    %rax,%rdx           \n" // current_thread()'s result
        "mov    $0x4,%ecx           \n"
        "pushl  $0x01234567         \n"
        "pushl  $0x89ABCDEF         \n"
        "ret                        \n"
    );
}

The challenges for me are:

  • Apparently, the compiler puts some code at the start of the patchcode() function that changes the stack. That's not good because I leave the routine with a jmp, not by the function's usual return path. How do I deal with that, can I tell the compiler not to generate that lead-in code?

  • How do I code the two jmps, one jmp from the to-be-patched area to the above patchcode() function, and then the jmp inside patchcode() back to the instruction of which I only know the absolute address, at runtime? As you can see above, I imagine pushing two 32 bit values onto the stack (I'll patch those values at runtime once I know the actual address where I want to jump to) and then jump to them using a ret instruction. Will that work?

Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149
  • The OS X Mach-O ABI uses relocatable code, 64-bit code shouldn't make references using absolute addresses. – l'L'l Sep 27 '14 at 16:48
  • In fact, this answer told me how to get the absolute jump working: http://stackoverflow.com/questions/9815448/jmp-instruction-hex-code - the push+ret method doesn't work for some reason. – Thomas Tempelmann Sep 27 '14 at 17:24
  • AT&T and Intel assembly syntax are quite different, also on Linux for example `mov $main` would be translated automatically to reference it's address in the GOT table, whereas on OS X it's done via stub helpers, which are not translated the same. – l'L'l Sep 27 '14 at 18:04

0 Answers0