2

I don't know very much about keyloggers; but I thought I'd be able to detect the presence of one by writing a program to simulate keystrokes (in Windows) and recording the throughput, then repeating the test with an active keylogger.

The idea being that a keylogger would also have to listen to the keystroke messages and perform some action; and that I'd be able to detect a decrease in performance. Thus far, my approach has failed miserably.

I'm trying this in Windows 7 using WIN32APIs to send messages. I really thought this would work, even if it's not very practical. Can anyone with more knowledge/experience flat out tell me if there is an obvious reason why this approach is doomed to fail? Several of the commercial keyloggers claim to 'not slow down the machine' but I figured it was just marketing. Yet, I can see no measurable performance difference.

Is it possible to detect keyloggers by monitoring the system for performance loss?

1
  • Maybe not, keyloggers designed today do not show on task manager, you can't tell what is the CPU utilization. Several of the commercial keyloggers like aobo keylogger claims to 'not slow down the machine' it wasn't just marketing.
    – user49855
    Jun 24, 2014 at 8:52

1 Answer 1

5

I'm not sure how your keyboard hooking code works in the background, but first up, Mr Chen blogged about the problem of using PostMessage for this type of thing. As he says, if you want to send input that gets stuck into the keyboard queue, use SendInput.

For example, one way to capture keypresses is to use SetWindowsHookEx and write an event handler as part of a DLL loaded in via LoadLibrary. This will then receive all the keyboard input you feed the system, and is one way for example to implement global hotkeys (as in, for the whole system).

The problem with this mechanism is that if the hook takes too long to process that input, Windows boots it out and never passes any more messages to it. Charming. It turns out there's actually a Windows 7 bug where the OS chucks hooks out for no good reason, too.

Anyway, OK, back on to task. It is possible, as one explanation, that your keylogger isn't showing any measurable performance difference because it's not actually installed. This is worth verifying.

Secondly, however you hook, you're going to incur a performance penalty, whatever the marketing speak says. There's extra instructions being executed whichever way you cut it, since if you're using a driver, Windows is clattering through an extra device in the driver stack and if you're using SetWindowsHook, Windows is enumerating and calling an extra hook.

What might be going wrong is the measurement process. This is pretty hard to do, especially when you account for confounding factors like context switches, IO delay etc. Depending on how you attempt to measure input time, you might just be missing the difference.

It gets more technical than that too - for example, rtdsc doesn't work all that well with multi-core systems these days, so if you're using that, it might not work. You need the appropriate API function to get a decent resolution timer.

Another point to note is the presence of a debugger. If you've ever debugged an application under say Visual Studio, you'll be well aware as DLLs load, debugging symbols get loaded too, introducing massive delays. I'm sure you've realised this, but worth repeating.

Here's how I'd approach this:

  • Write a Windows application. Log WM_KEYPRESS messages - time and keypress.
  • Have a thread.
  • Have a button that triggers the thread to begin sending SendInput messages.
  • Run this process for a while - you need to get enough data to negate any confounding factors.
  • Stop.
  • Repeat with keylogger loaded in.

Needless to say, I'd load this on a physical, not virtual machine, with as little running as possible.

Will you see anything? Honestly, I don't know. It looks like some have tried using this and other metrics, but I'm not sufficiently privileged to be allowed to read papers that are the advancement of human knowledge and that my taxes might have contributed to. If you can, do let me know if it's any good!

Added detail a context switch may occur whenever you make an API call, but does not necessarily occur. For example, if you call an IO-related function and the API must block, your process will then be suspended and the scheduling algorithm run to determine if any waiting processes are either starved of time, or have IO messages they need to handle. Depending on this, you, or another process, might well be woken up and run. The process then repeats.

If a switch between processes is merited, this is comparatively expensive (on the minute scale that we'd be measuring here) then the current register state is saved, your process is mapped out and another is mapped in. This is clearly more expensive than jumping back to user land.

Another potential gotcha are interrupts. On Linux (not sure about Windows), interrupts preempt everything when allowed to run, so a call may take more time simply because during that time, the kernel handled more interrupts than the previous time.

Interrupts don't always (in fact, probably shouldn't need) to switch process context, but there may be more or less of them at any given point, depending on what the hardware is doing. More of them means more CPU cycles between call and completion of that call.

2
  • Thank you for your post. One thing I can say is that I'm doing this all in a VM - I think I'll do a full backup/clean install and try it on my physical machine.
    – Rob P.
    Oct 19, 2012 at 20:28
  • @RobP I would - there shouldn't be an effect, really, but if you are in essence sharing the CPU with other operating systems and basing your measurements from a clock (as opposed to ticks), you're going to see delays for that too.
    – user2213
    Oct 19, 2012 at 20:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .