[CLUG-tech] Re: hooking on linux?

Jonathan Hitchcock vhata-clug at rucus.ru.ac.za
Mon Feb 6 09:40:53 SAST 2006


Hi,

Chavoux Luyt wrote:
> I would like to know how easy/difficult it is to hook the linux
> versions of .dll's (.so files?).

Of course, being Open Source, it's very easy.  If it wasn't, some 
disgruntled hacker in Armenia would have rewritten it.

However, as has been pointed out, there are better ways to do it in your 
case, PAM being the most obvious.

> Any tutorials or man pages that will explain how to go about this?

For this thread's completeness's sake, here is how to create .so files, 
and how to dynamically load and run functions from them  ;-)

(Stefanor: wanna wiki this?)

Step #1
=======
Create a C file with your functions in it:


int inc(int x) {
    return(x+1);
}


That's nice and simple.  I called it test.c.


Step #2
=======
Compile your C file to object code:

$ gcc -c  -fPIC test.c

Now we have test.o.
Link this object code into a .so file:

$ ld -o test.so -shared  test.o

Now we have test.so.


Step #3
=======

Create a C program to load and run the method in the file:

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

int main(int argc, char *argv[]) {
    int i;
    void *handle;     // void pointer to dll
    int (*inc)(int);  // typed pointer to function
    char *error;      // error string

// Note that, above, inc is a pointer to a function that takes
// an int, and returns an int. Modify for your own purposes.


// Get a handle to the dynamically opened library:
    handle=dlopen("./test.so",RTLD_LAZY);
    if ((error = dlerror()) != NULL) {
       printf (stderr, "%s", error);
    }

// Get a handle to a function in the dll:
    inc=dlsym(handle,"inc");
    if ((error = dlerror()) != NULL) {
       printf (stderr, "%s", error);
    }

// Run this function:
    i = 0;
    printf("%d\n",i);
    i = (*inc)(i);
    printf("%d\n",i);

// Close the handle to the dll
    if(handle!=NULL) dlclose(handle);
}

I called this run.c.


Step #4
=======

Compile run.c to a binary executable, linking in the DL library:

$ gcc -o run run.c -ldl


Step #5
=======

Run it.

$ ./run
0
1

That is exactly what we expected it to do - i was 0, we inc'd it, and it 
became 1.

Now the fun part...

Step #6
=======

Alter the .so file.

int inc(int x) {
    return(x+5);
}

Now it adds 5 instead of 1.
Recompile it:

$ gcc -c  -fPIC test.c
$ ld -o test.so -shared  test.o


Step #7
=======

Without recompiling it, run the binary:
$ ./run
0
5

It uses the new code from the .so, and thus has different behaviour, 
without recompiling it.

Hurrah!
Everybody go have a beer and take the rest of the day off.


More information about the Clug-tech mailing list