How to 'link' object file to executable/compiled binary?

后端 未结 6 1994
失恋的感觉
失恋的感觉 2020-12-24 08:41

Problem

I wish to inject an object file into an existing binary. As a concrete example, consider a source Hello.c:

#inc         


        
相关标签:
6条回答
  • 2020-12-24 09:13

    You must make room for the relocatable code to fit in the executable by extending the executables text segment, just like a virus infection. Then after writing the relocatable code into that space, update the symbol table by adding symbols for anything in that relocatable object, and then apply the necessary relocation computations. I've written code that does this pretty well with 32bit ELF's.

    0 讨论(0)
  • 2020-12-24 09:20

    You cannot do this in any practical way. The intended solution is to make that object into a shared lib and then call dlopen on it.

    0 讨论(0)
  • 2020-12-24 09:22

    The problem is that .o's are not fully linked yet, and most references are still symbolic. Binaries (shared libraries and executables) are one step closer to finally linked code.

    Doing the linking step to a shared lib, doesn't mean you must load it via the dynamic lib loader. The suggestion is more that an own loader for a binary or shared lib might be simpler than for .o.

    Another possibility would be to customize that linking process yourself and call the linker and link it to be loaded on some fixed address. You might also look at the preparation of e.g. bootloaders, which also involve a basic linking step to do exactly this (fixate a piece of code to a known loading address).

    If you don't link to a fixed address, and want to relocate runtime you will have to write a basic linker that takes the object file, relocates it to the destination address by doing the appropriate fixups.

    I assume you already have it, seeing it is your master thesis, but this book: http://www.iecc.com/linker/ is the standard introduction about this.

    0 讨论(0)
  • 2020-12-24 09:26

    If it were me, I'd look to create Embed.c into a shared object, libembed.so, like so:

    gcc -Wall -shared -fPIC -o libembed.so Embed.c
    

    That should created a relocatable shared object from Embed.c. With that, you can force your target binary to load this shared object by setting the environment variable LD_PRELOAD when running it (see more information here):

    LD_PRELOAD=/path/to/libembed.so Hello
    

    The "trick" here will be to figure out how to do your instrumentation, especially considering it's a static executable. There, I can't help you, but this is one way to have code present in a process' memory space. You'll probably want to do some sort of initialization in a constructor, which you can do with an attribute (if you're using gcc, at least):

    void __attribute__ ((constructor)) my_init()
    {
        // put code here!
    }
    
    0 讨论(0)
  • 2020-12-24 09:38

    Assuming source code for first executable is available and is compiled with a linker script that allocates space for later object file(s), there is a relatively simpler solution. Since I am currently working on an ARM project examples below are compiled with the GNU ARM cross-compiler.

    Primary source code file, hello.c

    #include <stdio.h>
    
    int main ()
    {
    
       return 0;
    }
    

    is built with a simple linker script allocating space for an object to be embedded later:

    SECTIONS
    {
        .text :
        {
            KEEP (*(embed)) ;
    
            *(.text .text*) ;
        }
    }
    

    Like:

    arm-none-eabi-gcc -nostartfiles -Ttest.ld -o hello hello.c
    readelf -s hello
    
    Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 SECTION LOCAL  DEFAULT    1 
     2: 00000000     0 SECTION LOCAL  DEFAULT    2 
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 FILE    LOCAL  DEFAULT  ABS hello.c
     5: 00000000     0 NOTYPE  LOCAL  DEFAULT    1 $a
     6: 00000000     0 FILE    LOCAL  DEFAULT  ABS 
     7: 00000000    28 FUNC    GLOBAL DEFAULT    1 main
    

    Now lets compile the object to be embedded whose source is in embed.c

    void func1()
    {
       /* Something useful here */
    }
    

    Recompile with the same linker script this time inserting new symbols:

    arm-none-eabi-gcc -c embed.c
    arm-none-eabi-gcc -nostartfiles -Ttest.ld -o new_hello hello embed.o
    

    See the results:

    readelf -s new_hello
    Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 SECTION LOCAL  DEFAULT    1 
     2: 00000000     0 SECTION LOCAL  DEFAULT    2 
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 FILE    LOCAL  DEFAULT  ABS hello.c
     5: 00000000     0 NOTYPE  LOCAL  DEFAULT    1 $a
     6: 00000000     0 FILE    LOCAL  DEFAULT  ABS 
     7: 00000000     0 FILE    LOCAL  DEFAULT  ABS embed.c
     8: 0000001c     0 NOTYPE  LOCAL  DEFAULT    1 $a
     9: 00000000     0 FILE    LOCAL  DEFAULT  ABS 
    10: 0000001c    20 FUNC    GLOBAL DEFAULT    1 func1
    11: 00000000    28 FUNC    GLOBAL DEFAULT    1 main
    
    0 讨论(0)
  • 2020-12-24 09:38

    Have you looked at the DyninstAPI? It appears support was recently added for linking a .o into a static executable.

    From the release site:

    Binary rewriter support for statically linked binaries on x86 and x86_64 platforms

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