2021-01-23 04:20:24 +00:00
|
|
|
# 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
|
2021-01-23 04:52:09 +00:00
|
|
|
glibc and musl it is). This then gets overwritten *at runtime by* `ld.so` due
|
2021-01-23 04:20:24 +00:00
|
|
|
to a relocation of type `R_X86_64_PC32` targetting the `pcrel32` operand of
|
|
|
|
that instruction --- all without touching any code of the executable.
|
|
|
|
|
2021-01-23 04:52:09 +00:00
|
|
|
The result:
|
|
|
|
|
|
|
|
```c
|
|
|
|
int main(int argc, char** argv[]){
|
|
|
|
printf("hello, world\n");
|
|
|
|
return 42;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern int main2(int argc, char** argv[]);
|
|
|
|
int main2(int argc, char** argv[]) {
|
|
|
|
printf("be gay do crimes\n");
|
|
|
|
return 69;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
```
|
|
|
|
$ ./hello.glibc
|
|
|
|
hello, world
|
2021-01-23 04:54:02 +00:00
|
|
|
$ ./manip-exe ./hello.glibc{,.manip} main2
|
2021-01-23 04:52:09 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
```asm
|
|
|
|
$ objdump -d hello.glibc.manip
|
|
|
|
|
|
|
|
0000000000001050 <_start>:
|
|
|
|
1050: 31 ed xor %ebp,%ebp
|
|
|
|
1052: 49 89 d1 mov %rdx,%r9
|
|
|
|
1055: 5e pop %rsi
|
|
|
|
1056: 48 89 e2 mov %rsp,%rdx
|
|
|
|
1059: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
|
|
|
|
105d: 50 push %rax
|
|
|
|
105e: 54 push %rsp
|
|
|
|
105f: 4c 8d 05 6a 01 00 00 lea 0x16a(%rip),%r8 # 11d0 <__libc_csu_fini>
|
|
|
|
1066: 48 8d 0d 03 01 00 00 lea 0x103(%rip),%rcx # 1170 <__libc_csu_init>
|
|
|
|
106d: 48 8d 3d c1 00 00 00 lea 0xc1(%rip),%rdi # 1135 <main>
|
|
|
|
1074: ff 15 66 2f 00 00 callq *0x2f66(%rip) # 3fe0 <__libc_start_main@GLIBC_2.2.5>
|
|
|
|
```
|
|
|
|
|
|
|
|
```
|
|
|
|
$ ./hello.glibc.manip
|
|
|
|
be gay do crimes
|
|
|
|
```
|
|
|
|
|
2021-01-23 04:20:24 +00:00
|
|
|
## Usage
|
|
|
|
|
|
|
|
```sh
|
|
|
|
# build only the tool
|
|
|
|
make manip-exe
|
|
|
|
# usage: ./manip-exe <input> <output> <symbol>
|
|
|
|
|
|
|
|
# also show some example stuff
|
|
|
|
make all
|
|
|
|
```
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
2021-01-23 04:28:40 +00:00
|
|
|
```
|
|
|
|
be gay, do crimes, death to america
|
|
|
|
```
|
2021-01-23 04:20:24 +00:00
|
|
|
|