Code injection - Solaris & Linux
Question
I have an executable module created by third party. I would like to "inject" my code (kind of watchdog running in separate thread) into this process.
So far there are two possible ways - one is to run my code as executable and dynamically load a proess on top of it (seems to be very hard and tricky) or to make my code a shared object, load it via LD_PRELOAD and initialize from some static variable constructor.
Are there more convenient ways to do this ? My OS are Linux x86 and Solaris-SPARC.
Update: If possible, I'd like not to patch the process, but load my code dynamicaly.
Solution
Sounds like you're looking for InjectSo. There's a Powerpoint presentation that explains how it works. I haven't gotten around to trying it out yet.
OTHER TIPS
Hotpatch should do this for you. It is more capable than injectso.
Rob Kennedy told you about InjectSo - that's probably what you need.
Beware that the introduction of a thread into a non-threaded process would be fraught with synchronization issues. The problems are less serious if the application is already threaded, but even so, the application may object to a thread that it doesn't know about.
I have not used the mentioned InjectSo but it is a noteworthy information. If you are looking for alternatives here is a simple way to inject your code:
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
int main()
{
struct passwd* pswd = getpwuid(1000);
if(pswd)
printf("%s\n", pswd->pw_name);
return 0;
}
gcc test.c -o test
#define _GNU_SOURCE
#include <dlfcn.h>
#include <sys/types.h>
#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
static char* hocus = "hocus pocus";
struct passwd *getpwuid(uid_t uid)
{
static struct passwd *(*orig_getpwuid)(uid_t uid);
if(!orig_getpwuid) {
orig_getpwuid = (struct passwd* (*)(uid_t))dlsym(RTLD_NEXT, "getpwuid");
}
struct passwd* original_passwd = (*orig_getpwuid)(uid);
if(original_passwd) {
original_passwd->pw_name = hocus;
}
// your code here
return original_passwd;
}
gcc inject.c -shared -o libinject.so
run with LD_LIBRARY_PATH=. LD_PRELOAD=libinject.so ./test
Should say hocus pocus
. You can override arbitrary libc
functions, like printf
, snprintf
- just find what is that module using.
In the "your code here" you can start arbitrary threads, watchdogs etc.