Execute code in kernel mode.

Hi everyone. I would like to hook a system function (gettimeofday) to modify it. I guess I'll need kernel mode to do that. By the way, how could I do it (c++ or c)?

I want to modify that function for one process which I know the PID. So I need to return my own value for that PID and real value for any other PID.

Thank you for read.

You may be able to do this without resorting to hacking and recompiling your kernel, but it depends on your system, what is it?

libkeepalive for instance overloads the socket() call without modifying the kernel, by intercepting function calls in libc. It needs the LD_PRELOAD option though, which AFAIK is linux-specific.

1 Like

I'm using ubuntu:

$ uname -a
Linux ********* 2.6.35-27-generic #48-Ubuntu SMP Tue Feb 22 20:25:46 UTC 2011 x86_64 GNU/Linux

I would like to do a kind of "speed hack" like Cheat Engine does for Windows. So I need to modify that function to return fake values, so apps think the time between tick and tick was twice or thrice of the real.

I don't care about the method if it can be applied to any application, and it doesn't do any kind of lag because the code. So all you give me will be accepted.

LD_PRELOAD will work for you then. Take a look at the code used in libkeepalive, it overrides socket(), you should be able to override gettimeofday() the same way. Force your fake library to be overloaded first with LD_PRELOAD="/path/to/my/fake/library.so" and it will call timeofday from it instead if it finds it there.

Do not export LD_PRELOAD="..." for the whole system, just when running that application. You could mess up your system pretty severely if it got preloaded in places you didn't intend.

1 Like

I'm forcing that function to print twice as the time that happened but nothing happens. To test, I added print("LOOOLAZO") but it doesn't print :(. Here is the code I'm using:

speed hack library:

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <dlfcn.h>
#include <stdio.h>

static timeval * timezero = 0;

typedef int (*go)(timeval *tv, timezone *tz);

int gettimeofday(timeval *tv, timezone *tz)
{
    // Testing purposes:
    printf("LOOOLAZO");
    go gettimeofday_orig;
    int val;
    gettimeofday_orig=(go)dlsym(RTLD_NEXT,"gettimeofday");
    if (!timezero)
    {
        timezero = new timeval;
        timezone tmp;
        val = gettimeofday_orig(timezero,&tmp);
        (*tv) = (*timezero);
        (*tz) = tmp;
        return val;
    }
    // Double speed:
    timezone tmpz;
    timeval tmpv;
    val = gettimeofday_orig(&tmpv,&tmpz);
    tmpv.tv_sec = 2*tmpv.tv_sec - timezero->tv_sec;
    tmpv.tv_usec = 2*tmpv.tv_usec - timezero->tv_usec;
    while(tmpv.tv_usec >= 1000000)
    {
        tmpv.tv_usec -= 1000000;
        tmpv.tv_sec += 1;
    }
    return val;
}

executable main.cpp:

#include <stdio.h>
#include <sys/time.h>

using namespace std;

int main(int argc, char ** argv)
{
    struct timezone tmpz;
    timeval tmpv;
    while (true)
    {
        gettimeofday(&tmpv,&tmpz);
        printf("S: %i MS: %i\n",tmpv.tv_sec, tmpv.tv_usec);
    }

    return 0;
}

Line export:

export LD_PRELOAD="/home/******/proyectos/cheat engine/bin/speedhacklib/speedhack.so" 

Output:

S: 1300139092 MS: 722327
S: 1300139092 MS: 722330
S: 1300139092 MS: 722333
S: 1300139092 MS: 722336
S: 1300139092 MS: 722340
S: 1300139092 MS: 722343
S: 1300139092 MS: 722346
S: 1300139092 MS: 722349
S: 1300139092 MS: 722352
S: 1300139092 MS: 722355
S: 1300139092 MS: 722358
S: 1300139092 MS: 722361
S: 1300139092 MS: 722365

No LOOOLAZO anywhere. Any idea?

Thank you for reading.

I don't see any LOOOOOL in your speedhack code, either.

Be sure to use write(), not a stdio function like printf(). Also be sure to write to stderr(FD 2), not stdout, since that might buffer.

write(2, "LOOOL", 5);

Sorry, it is not LOOOOOL, it is LOOOLAZO at the start of the gettimeofday from speed hack. A no sense mistake, sorry.

---------- Post updated at 04:55 PM ---------- Previous update was at 04:49 PM ----------

New code:

#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <dlfcn.h>

static timeval * timezero = 0;

typedef int (*go)(struct timeval *tv,struct timezone *tz);

int gettimeofday(struct timeval *tv, struct timezone *tz)
{
    write(2, "LOOOL", 5);
    go gettimeofday_orig;
    int val;
    gettimeofday_orig=(go)dlsym(RTLD_NEXT,"gettimeofday");
    if (!timezero)
    {
        timezero = new timeval;
        struct timezone tmp;
        val = gettimeofday_orig(timezero,&tmp);
        (*tv) = (*timezero);
        (*tz) = tmp;
        return val;
    }
    // Doblar la velocidad:
    struct timezone tmpz;
    struct timeval tmpv;
    val = gettimeofday_orig(&tmpv,&tmpz);
    tmpv.tv_sec = 2*tmpv.tv_sec - timezero->tv_sec;
    tmpv.tv_usec = 2*tmpv.tv_usec - timezero->tv_usec;
    while(tmpv.tv_usec >= 1000000)
    {
        tmpv.tv_usec -= 1000000;
        tmpv.tv_sec += 1;
    }
    return val;
}

I don't know why when I add <iostream> I'm forced to write c code instead c++. I needed to write struct at each declaration of structure... Any idea?

PD: It seems not to get executed. Just that.

You're not writing this in C++, are you? Your gettimeofday function will be named some crazy operator-overloaded C++ hashed name.

[edit] Add this exact code to libkeepalive.c:

// below #include <netinet/tcp.h>
#include <sys/time.h>

int gettimeofday(struct timeval *tv, struct timezone *tz)
{
        write(2, "LOOOL", 5);
        return(-1);
}

Then run make in the appropriate directory:

$ ls
AUTHORS    FEEDBACK  Makefile  VERSION  test
ChangeLog  LICENSE   README    src      wtf.cpp
$ make
 make
make -C src/
make[1]: Entering directory `/home/tyler/code/c/1shot/speedhack/libkeepalive-0.2/src'
gcc -fPIC   -c -o libkeepalive.o libkeepalive.c
gcc -shared -Wl,-soname,libkeepalive.so -o libkeepalive.so libkeepalive.o -ldl
rm libkeepalive.o
make[1]: Leaving directory `/home/tyler/code/c/1shot/speedhack/libkeepalive-0.2/src'
make -C test/
make[1]: Entering directory `/home/tyler/code/c/1shot/speedhack/libkeepalive-0.2/test'
gcc     test.c   -o test
make[1]: Leaving directory `/home/tyler/code/c/1shot/speedhack/libkeepalive-0.2/test'
cp src/libkeepalive.so libkeepalive.so
strip -s libkeepalive.so
$ g++ -o wtf wtf.cpp
$

...then use it like so:

$ export LD_PRELOAD="./libkeepalive.so"
$ ./wtf
LOOOLS: -1216950284 MS: -1076618008
LOOOLS: -1216950284 MS: -1076618008
LOOOLS: -1216950284 MS: -1076618008
LOOOLS: -1216950284 MS: -1076618008
LOOOLS: -1216950284 MS: -1076618008
LOOOLS: -1216950284 MS: -1076618008
LOOOLS: -1216950284 MS: -1076618008
LOOOLS: -1216950284 MS: -1076618008
LOOOLS: -1216950284 MS: -1076618008
....

And be sure to export LD_PRELOAD="" before doing anything else because you will continue to see LOOOL's popping up in bizzare places :smiley:

I suspect the difference is in the makefile. Some rather bizzare options are required to prevent gcc from complaining about your symbols conflicting with libc's when you build stuff like this.

1 Like

You need a newline:

printf("LOOOLAZO\n");

And we try to run a G rated forum here... please try to avoid the foul language.

1 Like

Personally I would try to avoid using any stdio functions inside a libc-level system library...

1 Like

Good point I guess. But personally, I would not try to modify a system call. :wink:

Can anyone test it for me? Or give me a tip? I can't imagine where to continue if the library is not executed (that seems to be the problem).

Thank you for read.

EDIT: Sorry, I didn't notice the 2nd page. I'm shamed.

I won't use foul language again, I promise haha.

So is the problem that I write it in C++? Could I use something like extend "C"?

I gave you working, step-by-step instructions in my post at the top of this page, and demonstrated that gettimeofday call was intercepted, and pointed out potential problems in your own code (i.e. C++ functions get named bizzare names, you need to make it a C function).

If my instructions don't work for you or are missing needed details, please describe where you got stuck.

---------- Post updated at 09:19 AM ---------- Previous update was at 09:03 AM ----------

Boy it's a good thing there's a way to do this in userspace, since you'd have no hope at all of running C++ in the kernel :smiley:

extern "C" gettimeofday(...) might work, but remember, you're writing C library code, not a normal userspace program. You should try to limit the high-level calls you make as much as possible. I'd avoid using C stdio, let alone iostream and the like. What if, in your gettimeofday() function, something deep in STL decides to call gettimeofday()? You'll get recursion until crash or swapdeath.

What, precisely, do you need C++ for? There may be lower-level alternatives.

I understand your looping through STL functions. I don't need them for nothing but test purposes. That is, when I finish the library I'll erase the "LOOOL" line.

I don't need C++. Is just the language I always use. I don't know ASM and I didn't go deeper on C, so I prefer C++.

Thank you for replies. The bug seemed to be that the library must be in the same folder, thing that I didn't know.

No, don't write your gettimeofday() in assembly, that'd be just silly. :smiley: As is comparing C to assembly. :stuck_out_tongue:

C isn't hard if you already know C++. All you'd be learning is the names of a few system calls.

Nah. The run-time linker for OpenBSD, NetBSD, FreeBSD, and SunOS/Solaris all support the LD_PRELOAD environment variable. If I'm not mistaken, AIX supports the functionality but the variable's name may be slightly different (LDR_PRELOAD perhaps?). Perhaps other systems as well.

Regards,
Alister

Well. Now it is implemented and working well. The next part is to try to modify that function while Run-Time. Is it possible? I mean, not to launch the application with modified library, but change it while is running.

Thank you for replies. I did this part in the half time I thought it would cost me.

No. But you could have your function check for things to decide whether it should act normally or not.

You could even have it call libc's own gettimeofday() by loading the symbol from libc with dlopen/dlsym and calling it with a function pointer... Again, libkeepalive's source tells you how to do that.

1 Like

Well. For an unknown reason (unknown for me) LD_PRELOAD is not working for some programs, just half of them:

For instance:

quake4
ERROR: ld.so: object 'speedhack.so' from LD_PRELOAD cannot be preloaded: ignored.

or:

tileracer
ERROR: ld.so: object 'speedhack.so' from LD_PRELOAD cannot be preloaded: ignored.

Any idea of what is happening? The library is placed on /usr/lib/ so I guess LD_PRELOAD can find it, because it works with my own test program for testing speedhack.

What exactly have you set LD_PRELOAD to?