You have several options here, but I like this one.
Since the code is already inside the executable, so you have to patch the entrypoint to jump to a new function.
To do so, I suggest to use a shared object (.so). In this module you will both: the new function and a 'patcher function'. The latter function must be defined with
__attribute__((constructor)), this attribute will force the ELF loader to call this function before the
main function from your original executable is called.
The patcher function will set write access at the entrypoint of the old function with
mprotect (2), encode the jump instruction, and it's probably better to remove the write access you needed for the patch.
Once you have your shared object, you can inject it using the
Edit with an example, since you didn't mentioned the architecture, I assumed this is for x86-64:
First this is a target, we want to change the function my_rand to return 0xdeadbeef.
return rand() + rand() ^ rand();
printf("random value: %08x\n", my_rand());
To find the RVA, we can use
nm because we have the symbol. You might have to find it manually.
nm target|grep my_rand
0000000000001169 T my_rand
Finally, the code of the patcher:
static int new_random(void)
static void emit_jump_to_address(uint64_t address, uint64_t jump_destination)
long page_size = sysconf(_SC_PAGESIZE);
void* aligned_address = (void*)(address & ~(page_size - 1));
if (mprotect(aligned_address, page_size, PROT_READ|PROT_WRITE|PROT_EXEC) < 0)
*(uint16_t*)(address + 0x0) = 0xb848; // mov rax, Iv
*(uint64_t*)(address + 0x2) = jump_destination; // mov rax, jump_destination
*(uint16_t*)(address + 0xa) = 0xe0ff; // jmp rax
if (mprotect(aligned_address, page_size, PROT_READ|PROT_EXEC) < 0)
// ref: https://stackoverflow.com/questions/19451791/get-loaded-address-of-a-elf-binary-dlopen-is-not-working-as-expected
struct link_map* lm = dlopen(NULL, RTLD_NOW);
__attribute__((constructor)) void patcher(void)
target = get_image_base();
target += 0x1169; // RVA
printf("[!] targeted function is at %p\n", (void const*)target);
printf("[!] new function is at %p\n", (void const*)&new_random);
This source code was compiled with clang and injected using
$ clang patcher.c -o patcher.so -shared -ldl
$ env LD_PRELOAD=./patcher.so ./target
[!] targeted function is at 0x7fe05f907169
[!] new function is at 0x7fe05f8c11f0
random value: deadbeef
Note, I'm using fish, so the
env is required.