gaffe23 / linux-inject

Tool for injecting a shared object into a Linux process
Other
1.11k stars 249 forks source link

segfault in diff optimize level #8

Open wenxichang opened 8 years ago

wenxichang commented 8 years ago

// start of the function to inject always happens to be 2 bytes long. ? this is not reliable, this my modification:

  1. fill 32 nop in the begin of injectSharedLibrary to ensure the code copy to target is clean.

the second question is that why the last INT 3 inst. not supply in injectSharedLibrary but find and replace the RET inst. ?

the .patch:

Index:

 inject-x86_64.c
===================================================================
--- inject-x86_64.c (revision 654940)
+++ inject-x86_64.c (working copy)
@@ -25,6 +25,13 @@

 void injectSharedLibrary(long mallocaddr, long freeaddr, long dlopenaddr)
 {
+   // add nop in the function head, so that we can jump into it for diff c-compiler optimize
+   asm(
+       "nop \nnop \nnop \nnop \nnop \nnop \nnop \nnop \n"
+       "nop \nnop \nnop \nnop \nnop \nnop \nnop \nnop \n"
+       "nop \nnop \nnop \nnop \nnop \nnop \nnop \nnop \n"
+       "nop \nnop \nnop \nnop \nnop \nnop \nnop \nnop \n"
+   );
    // here are the assumptions I'm making about what data will be located
    // where at the time the target executes this code:
    //
@@ -103,7 +110,9 @@
        // call free()
        "callq *%rbx \n"
        // restore previous rbx value
-       "pop %rbx"
+       "pop %rbx \n"
+       // break to restore everything
+       "int $3"
    );

    // we already overwrote the RET instruction at the end of this function
@@ -223,8 +232,12 @@
    regs.rcx = libPathLength;
    ptrace_setregs(target, &regs);

+   // +30 to skip function header(we have 32 nop after the header)
+   // ensure clean code is copied
+   void *safeInjectSharedLibrary = (void *)((intptr_t)injectSharedLibrary + 30);
+   
    // figure out the size of injectSharedLibrary() so we know how big of a buffer to allocate. 
-   size_t injectSharedLibrary_size = (intptr_t)injectSharedLibrary_end - (intptr_t)injectSharedLibrary;
+   size_t injectSharedLibrary_size = (intptr_t)injectSharedLibrary_end - (intptr_t)safeInjectSharedLibrary;

    // also figure out where the RET instruction at the end of
    // injectSharedLibrary() lies so that we can overwrite it with an INT 3
@@ -233,7 +246,6 @@
    // which means that functions are padded with NOPs. as a result, even
    // though we've found the length of the function, it is very likely
    // padded with NOPs, so we need to actually search to find the RET.
-   intptr_t injectSharedLibrary_ret = (intptr_t)findRet(injectSharedLibrary_end) - (intptr_t)injectSharedLibrary;

    // back up whatever data used to be at the address we want to modify.
    char* backup = malloc(injectSharedLibrary_size * sizeof(char));
@@ -245,9 +257,8 @@
    memset(newcode, 0, injectSharedLibrary_size * sizeof(char));

    // copy the code of injectSharedLibrary() to a buffer.
-   memcpy(newcode, injectSharedLibrary, injectSharedLibrary_size - 1);
+   memcpy(newcode, safeInjectSharedLibrary, injectSharedLibrary_size);
    // overwrite the RET instruction with an INT 3.
-   newcode[injectSharedLibrary_ret] = INTEL_INT3_INSTRUCTION;

    // copy injectSharedLibrary()'s code to the target address inside the
    // target process' address space.