Problem
I wish to inject an object file into an existing binary. As a concrete example, consider a source Hello.c
:
#include <stdlib.h>
int main(void)
{
return EXIT_SUCCESS;
}
It can be compiled to an executable named Hello
through gcc -std=gnu99 -Wall Hello.c -o Hello
. Furthermore, now consider Embed.c
:
func1(void)
{
}
An object file Embed.o
can be created from this through gcc -c Embed.c
. My question is how to generically insert Embed.o
into Hello
in such a way that the necessary relocations are performed, and the appropriate ELF internal tables (e.g. symbol table, PLT, etc.) are patched properly?
Assumptions
It can be assumed that the object file to be embedded has its dependencies statically linked already. Any dynamic dependencies, such as the C runtime can be assumed to be present also in the target executable.
Current Attempts/Ideas
- Use
libbfd
to copy sections from the object file into the binary. The progress I have made with this is that I can create a new object with the sections from the original binary and the sections from the object file. The problem is that since the object file is relocatable, its sections can not be copied properly to the output without performing the relocations first. - Convert the binary back to an object file and relink with
ld
. So far I tried usingobjcopy
to perform the conversionobjcopy --input elf64-x86-64 --output elf64-x86-64 Hello Hello.o
. Evidently this does not work as I intend sinceld -o Hello2 Embed.o Hello.o
will then result inld: error: Hello.o: unsupported ELF file type 2
. I guess this should be expected though sinceHello
is not an object file. - Find an existing tool which performs this sort of insertion?
Rationale (Optional Read)
I am making a static executable editor, where the vision is to allow the instrumentation of arbitrary user-defined routines into an existing binary. This will work in two steps:
- The injection of an object file (containing the user-defined routines) into the binary. This is a mandatory step and can not be worked around by alternatives such as injection of a shared object instead.
- Performing static analysis on the new binary and using this to statically detour routines from the original code to the newly added code.
I have, for the most part, already completed the work necessary for step 2, but I am having trouble with the injection of the object file. The problem is definitely solvable given that other tools use the same method of object injection (e.g. EEL).
.so
, is that injection tricks such asLD_PRELOAD
can be subverted by the application. Not only this, it requires the distribution of an additional library which forms the new environment. Static detouring has various other advantages (particularly for the purposes of this project), but as I've already said both in the question and comments to answers, this is not a design decision I can change :) – Ovida