relocmain/README.md

50 lines
1.9 KiB
Markdown

# relocmain
Swap out an ELF executable's `main` function with another function from its
symbol table, without touching its code at all.
## How it works
The typical ELF entrypoint isn't `main` directly, but rather `_start`, an
assembly stub that first does some runtime initialization before calling
`main`. But instead of directly calling the latter function, it is often
passed as a parameter to `__libc_start_main` (which in turn calls `main` after
doing *more* initialization stuff).
'Relocations' are instructions for an ELF linker or loader on how to patch a
binary when moving it around in memory or when resolving functions. Some
examples are "this value here is an absolute address, so when you move me
around, please keep it updated" (`R_<arch>_RELATIVE`), or "I'm using this
external function, and I'm accessing it through a PLT, so when you resolve
the symbol, please put it in the PLT" (`R_<arch>_JUMP_SLOT`).
This programs adds another relocation entry that replaces the code that loads
the address `main` (to pass it to `__libc_start_main`) with the address of a
different symbol. Due to how relocations work, it is restricted to replacing
it with another symbol that is either imported from another library, or
exported by the executable itself.
Currently, only x86_64 is supported (but it's not too hard to add support for
other instruction sets, 32-bit ELF support is a bit harder). The code looks for
a `lea rdi, [rel <pcrel32>]` instruction near `_start`, this is often the
instruction that loads `main` to pass it to `__libc_start_main` (at least on
glibc and musl it is). This then gets overwritten *at runtime by *`ld.so` due
to a relocation of type `R_X86_64_PC32` targetting the `pcrel32` operand of
that instruction --- all without touching any code of the executable.
## Usage
```sh
# build only the tool
make manip-exe
# usage: ./manip-exe <input> <output> <symbol>
# also show some example stuff
make all
```
## License
See [LICENSE](/LICENSE).