Patching code/symbols into a dynamic-linked ELF binary

前端 未结 4 1447
無奈伤痛
無奈伤痛 2021-02-15 02:17

Suppose I have an ELF binary that\'s dynamic linked, and I want to override/redirect certain library calls. I know I can do this with LD_PRELOAD, but I want a solut

相关标签:
4条回答
  • 2021-02-15 02:49

    I don't seem to be able to just add comment to this question, so posting it as an "answer". Sorry about it, doing that just to hopefully help other folks who search an answer.

    So, I seem to have similar usecase, but I explicitly find any modification to existing binaries unacceptable (for me), so I'm looking for standalone proxy approach: Proxy shared library (sharedlib, shlib, so) for ELF?

    0 讨论(0)
  • 2021-02-15 02:56

    ld has the option --wrap that lets you replace a given symbol like malloc by a symbol you'd call __wrap_malloc. With that you could write some stubs for the functions you are interested in and link that to the library in question.

    0 讨论(0)
  • 2021-02-15 03:01

    I suggest the elfsh et al. tools from the ERESI project, if you want to instrument the ELF files themselves. Compatibility with i386-linux is not a problem, as I've used it myself for the same purpose.

    The relevant how-tos are here.

    0 讨论(0)
  • 2021-02-15 03:04

    You could handle some of the dynamic linking in your program itself. Read the man page for dlsym(3) in particular, and dlopen(3), dlerror(3), and dlclose(3) for the rest of the dynamic linking interface.

    A simple example -- say I want to override dup2(2) from libc. I could use the following code (let's call it "dltest.c"):

    #define _GNU_SOURCE
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <dlfcn.h>
    
    int (*prev_dup2)(int oldfd, int newfd);
    
    int dup2(int oldfd, int newfd) {
        printf("DUP2: %d --> %d\n", oldfd, newfd);
        return prev_dup2(oldfd, newfd);
    }
    
    int main(void) {
        int i;
    
        prev_dup2 = dlsym(RTLD_NEXT, "dup2");
        if (!prev_dup2) {
            printf("dlsym failed to find 'dup2' function!\n");
            return 1;
        }
        if (prev_dup2 == dup2) {
            printf("dlsym found our own 'dup2' function!\n");
            return 1;
        }
    
        i = dup2(1,3);
        if (i == -1) {
            perror("dup2() failed");
        }
    
        return 0;
    }
    

    Compile with:

    gcc -o dltest dltest.c -ldl
    

    The statically linked dup2() function overrides the dup2() from the library. This works even if the function is in another .c file (and is compiled as a separate .o).

    If your overriding functions are themselves dynamically linked, you may want to use dlopen() rather than trusting the linker to get the libraries in the correct order.

    EDIT: I suspect that if a different function within the overridden library calls an overridden function, the original function gets called rather than the override. I don't know what will happen if one dynamic library calls another.

    0 讨论(0)
提交回复
热议问题