Patching code/symbols into a dynamic-linked ELF binary
Asked Answered
S

3

9

Suppose I have an ELF binary that's dynamic linked, and I want to override/redirect certain library calls. I know I can do this with LD_PRELOAD, but I want a solution that's permanent in the binary, independent of the environment, and that works for setuid/setgid binaries, none of which LD_PRELOAD can achieve.

What I'd like to do is add code from additional object files (possibly in new sections, if necessary) and add the symbols from these object files to the binary's symbol table so that the newly added version of the code gets used in place of the shared library code. I believe this should be possible without actually performing any relocations in the existing code; even though they're in the same file, these should be able to be resolved at runtime in the usual PLT way (for what it's worth I only care about functions, not data).

Please don't give me answers along the line of "You don't want to do this!" or "That's not portable!" What I'm working on is a way of interfacing binaries with slightly-ABI-incompatible alternate shared-library implementations. The platform in question is i386-linux (i.e. 32-bit) if it matters. Unless I'm mistaken about what's possible, I could write some tools to parse the ELF files and perform my hacks, but I suspect there's a fancy way to use the GNU linker and other tools to accomplish this without writing new code.

Satiety answered 27/10, 2010 at 4:19 Comment(2)
I don't know if this is work anything for you but check out the 'nm' system command (your probably already know about it). Gives quite a bit of info about a so.Koslo
Wow, the LD_PRELOAD trick looks fun! I too am looking for a way to do it in the binary though. My issue is my binary has a symbol that my BeagleBone's linker can't resolve.Valetudinary
F
6

I suggest the elfsh et al. tools from the ERESI (alternate) project, if you want to instrument the ELF files themselves. Compatibility with i386-linux is not a problem, as I've used it myself for the same purpose.

The relevant how-tos are here.

Fantasist answered 27/10, 2010 at 6:36 Comment(5)
Looks like it'll take some reading, but I think this is the tool I was looking for. Thanks!Satiety
Is there any documentation for ERESI? I can't find any "getting started", examples, etc.Satiety
The examples in the repo work, sort of, but there seems to be absolutely no documentation of how they work or how to learn from them. I'm accepting your answer as-is since it seems to be the best available without writing new documentation, but if you ever run across any please sent it my way.Satiety
I found this tutorial very enlightening: phrack.org/issues.html?issue=66&id=14&mode=txtChaff
In case anyone is seeking the previous link (now broken): phrack.org/issues/66/14.html#articleForb
J
1

You could handle some of the dynamic linking in your program itself. Read the man page for dlsym(3) in particular, and dlopen(3), dlerror(3), and dlclose(3) for the rest of the dynamic linking interface.

A simple example -- say I want to override dup2(2) from libc. I could use the following code (let's call it "dltest.c"):

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>

int (*prev_dup2)(int oldfd, int newfd);

int dup2(int oldfd, int newfd) {
    printf("DUP2: %d --> %d\n", oldfd, newfd);
    return prev_dup2(oldfd, newfd);
}

int main(void) {
    int i;

    prev_dup2 = dlsym(RTLD_NEXT, "dup2");
    if (!prev_dup2) {
        printf("dlsym failed to find 'dup2' function!\n");
        return 1;
    }
    if (prev_dup2 == dup2) {
        printf("dlsym found our own 'dup2' function!\n");
        return 1;
    }

    i = dup2(1,3);
    if (i == -1) {
        perror("dup2() failed");
    }

    return 0;
}

Compile with:

gcc -o dltest dltest.c -ldl

The statically linked dup2() function overrides the dup2() from the library. This works even if the function is in another .c file (and is compiled as a separate .o).

If your overriding functions are themselves dynamically linked, you may want to use dlopen() rather than trusting the linker to get the libraries in the correct order.

EDIT: I suspect that if a different function within the overridden library calls an overridden function, the original function gets called rather than the override. I don't know what will happen if one dynamic library calls another.

Jacie answered 27/10, 2010 at 5:37 Comment(1)
I'm trying to modify binaries, not source.Satiety
N
1

I don't seem to be able to just add comment to this question, so posting it as an "answer". Sorry about it, doing that just to hopefully help other folks who search an answer.

So, I seem to have similar usecase, but I explicitly find any modification to existing binaries unacceptable (for me), so I'm looking for standalone proxy approach: Proxy shared library (sharedlib, shlib, so) for ELF?

Nahama answered 20/1, 2012 at 2:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.