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.
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.
$ 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.
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:
And be sure to export LD_PRELOAD="" before doing anything else because you will continue to see LOOOL's popping up in bizzare places
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.
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
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.
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.
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.
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.