Tuesday, January 19, 2016

Scripting A Windows Key Logger

I recently seized the opportunity to contribute to a project, PowerSploit, that I've often used for reference and gleaned a wealth of knowledge from. An issue was opened for the project's key-logger the day after Christmas 2015, and as I hastily skimmed through my emails before deleting them I stopped for a moment to read it. Coldalfred writes, "When i execute as default or -PollingInterval 100 or 10000 or 40 that is the default make the Powershell process consume a lot of CPU that is normal?" I had some free-time to kill, so I decided to investigate the issue to determine if it might be fixable.

I was able to verify the issue Coldalfred reported. As it turns out, the PollingInterval parameter was not successfully being passed into the initialization routine. This parameter sets a sleep statement designed to throttle the key-checking loop. PowerShell's Start-Sleep cmdlet throws a non-terminating error when null values are supplied as input, but since this particular instance was executed as a background job it wasn't readily apparent the error was occurring. In addition to masking this error, the use of jobs was causing excessive memory consumption. My initial intent was to repair the PollingInterval parameter and replace the background job with a runspace. Below is a truncated code-snippet to highlight the situation.

By this time, the project's creator had closed Coldalfred's already known issue commenting, "...SetWindowsHookEx would make for a much better keylogger but that would require placing a DLL on disk." The benefit of using SetWindowsHookEx is that you can hook all processes in a desktop simultaneously and guarantee delivery of their key messages as they happen, rather than exhaustively checking the state of every key via GetAsyncKeystate and missing at least a few. I did some research into this idea and came across an interesting piece by Hans Passant. Hans explains that there are actually two hook types that don't require a DLL, and one of them is for low-level keyboard messages. The key to this type of hook is the use of a loop that checks for messages in the queue, after setting the hook. The PeekMessage function is used below to check the queue with a filter specifying only keyboard messages (0x100,0x109) be retrieved for processing.

Even though PowerShell and C# both run atop the .NET framework and have interoperability with the Windows API, getting PowerShell to do things that seem trivial in C# can sometimes require a bit of ingenuity. This happened to be one of those times. The use of SetWindowsHookEx relies on an application-defined LowLevelKeyboardProc callback function to process the keyboard messages it retrieves. This means I have to convince an unmanaged API function to execute managed .NET scripting as a callback function. Thankfully, I'd read about working with unmanaged callback functions in PowerShell during previous internet wanderings and was able to successfully implement it, as demonstrated below.

All that's left to do is wrap everything up, drop it into a separate runspace, and execute.

The entire, non-truncated, source can be found here.


  1. Replies
    1. Thanks, liked your write-up on the traceless threat as well ;)

  2. After installing this program I have an error - missed DLL file. Thanks to my friend, that advised to me a brilliant resource, where I download missed DLL file - http://fix4dll.com/msvcp100_dll.

  3. Geofencing feature of the FlexiSpy became very popular nowadays, and this app has it available too, have a look at keyloggers for iphone here.

  4. Very informative article, I liked the concept of the script impressed by demonstration
    Richard Brown data room providers

  5. Oh yeah! You had a lot of work. I'm saving my computer from strangers. This https://www.refog.com/ helps me. That's because I hate when some workers are installing the application without my knowledge on computer.

  6. I like what you've done, I might not entirely understand it, but I like it. My question is, why does this script not work when converted into an .exe (I used https://ps2exe.codeplex.com/). My guess is that the Runspace is different and messes the script up.

  7. Oh, you did a good job! I’m not good in coding and your article helped me. Do you know about a service https://www.hoverwatch.com? Remaining undetectable you can track a phone there, namely view SMS, read the messages sent using WhatsApp , Viber and Facebook mobile apps, determine and view location of the target device user, track all web activity. It’s a good chance to know more about people whom you trust and love.

  8. WhatsApp remoto hacking sin acceder a un teléfono de destino. Puede guardar un archivo de archivos de usuario, que contiene lo siguiente: mensajes entrantes y salientes hackear whatsapp