3

My Linux application (A) links against a Third Party shared Library (B) which I don't have source code to. This library makes use of another third party shared library that I don't have source code to (C). I believe that (B) uses dlopen to access (C) instead of directly linking. My reasoning for this is that 'ldd' on (B) does not show (C) and objdump -X (B) shows references to dlopen/dlclose/dlsym.

My requirement is that I need to in my code for (A) get a function pointer to a function foo() located in (C). Normally I'd use dlsym for this, but I need to pass it the handle returned from dlopen which I don't have since (B) does not expose this.

-

For the larger context: I need to modify the function in (C) such that everytime it calls its helper function bar() (also located in (C)), it also calls a function with the same signature located in (A) with the same parameters (Basically inject my code into the codepath of (C) foo()->bar(). I believe I've found a way to accomplish this using gdb, but in order to port my gdb command list, but I'm stuck on the step of getting the function pointer. I'm also open to alternatives to accomplish the same task rather than the exact problem as stated above

Edit: After writing this I realized I can probably just do another dlopen on the file in my code and the symbols returned via dlsym on that handle should be the same as received via the original dlopen, If I'm reading the dlopen man page correctly. However I'm still interested in advice or assistance with the my larger context, If theres a better way to go about this

2 Answers 2

2

If you know the prototype for function foo and bar, you can LD_PRELOAD (a library created by you) in your app environment and call the next available function (either foo or bar after doing your required task.

/* * gcc -shared -fPIC my_lib.c -ldl -Wl,-init,init_lib -o lib_my_name.so * * LD_PRELOAD this library in the environment of the target executable * */ #include <stdio.h> #include <dlfcn.h> #include <stdlib.h> #ifndef RTLD_NEXT #define RTLD_NEXT ((void *)-1) #endif int init_lib(void) { return 0; } void *foo (params here...) { /* your required task here */ return ((void* (*)(size_t))(dlsym(RTLD_NEXT, "foo")))(params here); } 

(I am assuming that you are doing this for some debugging purpose as you have used gdb to accomplish this, else this is not a good way for modifying some functionality at client's machine)

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. LD_PRELOAD was my original idea, but since (B) is doing dlopen/dlsym directly on (C) rather than just dynamic linking, this doesn't seem to be an option.
1

You can easily get hold of a handle for (C); just dlopen the right file. Either you already know which file to dlopen (since you want symbol "foo"), or you run strace -e open,mmap,mmap2 on (A) and see what shared libraries it happens to open.

When (C) was created, any references to "bar" (such as from a jmp instruction in "foo") are generally partial-resolved at creation time already, since (C) does have a "bar" itself. Thus, the call to bar will not go through the PLT, in other words, overriding bar through easy hacks is void, and asm-level punning, like gdb does, is required.

All that sounds so overly work intensive that it begs the question whether it is worth the work, or whether throwing out the closed-source components may be better.

1 Comment

Thanks, this is pretty much what I ended up doing and it worked fine. I used dlopen/dlsym to get the function and a dissassembly of the function to find a call instruction and change the operand to point to my code, which then calls the original function via the dlsym function pointer

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.