One of my side projects over the past few months has been to teach myself the C programming language. It has been going pretty well, but it’s easy to get bored with the typical practice problems.To combat this I gave myself a slightly more real-world practice problem. I decided to write a Key Logger in native C using only the Win32 API. There are a few good examples online of the mechanics of how to do this, but what I quickly found after getting a working prototype up and running was that Windows Defender is actually pretty good in some cases at detecting/tagging key loggers as Trojans. I tried different example code from online, and in each case Windows Defender instantly caught it upon execution.
So the next challenge was how to write a Key logger in native C with the Win32 API which Windows Defender could not detect.
After a few modifications I thought I had it figured out, but what I came to realize is that Defender is built such that it can tell if you are repeatedly trying to vet code past it and it will temporarily stop intercepting it so you can’t tell if your modifications are working.
It is actually a fairly interesting problem in that Defender has to be able to recognize certain patterns common to Key Loggers, but at the same time it has to be able ignore programs that function like Notepad/Word/Games which have a completely legitimate reason for listening and responding instantly to keystrokes. This balance is where the room for vulnerability lies. It would be easy to alert anytime a new program was listening for keystrokes via the Win32 API’s, but you would have so many non-actionable events it would be pointless. So it becomes a game of whack-a-mole where the patterns for detecting key loggers need to be permissive enough not to piss off users trying to run non-malicious code, but restrictive enough to hopefully catch/deter a less than determined adversary.
I have no insider knowledge into how Defender works (nor would I share any if I did), but after figuring out how to force Defender to try to quarantine my program every time it ran, I could slowly comment out aspects of my Key Logger code until I zeroed in on the characteristics it was using to make its diagnosis. Once I had that, the problem was solved.
It took a few hours, but I now have a basic functional Key Logger that doesn’t need to run as administrator and is completely invisible to Windows Defender. I also learned more about C and the Win32 API in the past few hours than from three weeks worth of reading. As much as possible I am going to try to add in programming assignments like this one that have a bit more real-world application as they are able to maintain my interest better than writing Celsius to Fahrenheit temperature converters and the other example problems that are universal to almost every learn programming language X book.
I had debated not publishing the code, but a routine Bing/Google search will reveal plenty of similar alternate examples, and with C source code for programs like mimikatz readily available this would fall into the tamer categories of code available for aspiring white hats who want to learn more about programming and security.
The code is provided without warranty of any kind and is for educational purposes only, and in this case I am only including screenshots without the details of the work to vet the code against an antivirus application. If you want to create a working copy you have to type it out yourself which is in the end the best way to learn.
To start off launch Visual Studio. (For my example I am using Visual Studio 2013)
File New Project (Ctrl — Shift — N)
Select Visual C++ (Win32 Console Application) -Even though the code we are writing is almost entirely C the C++ compiler is backwards compatible with any of our C code.
Select Empty project
Right-Click Source File — Add — New Item (Ctrl-Shift-A)
Give you .cpp files a name click Add
The code itself is pretty simple. The ShowWindow() function controls the visibility of the command prompt window.
While loop continues indefinitely until the End Key is pressed or the Console Window/associated process is closed/stopped. For loop cycles between keys 8-255.
GetAsyncKeyState() function let’s us know if the key we are cycling through in the for loop is down. http://www.cplusplus.com/forum/general/141404/ (Nice explanation of why to use & 0x0001)
Use if statements to determine what keys get written directly to file. Shift letters A-Z by 32 making all letters lowercase via ASCII character set. http://www.asciitable.com/
To map other keys you need to use win32 API Virtual-Key Codes:
If you have any suggestions on good C Programming resources let me know. I have exhausted K&R and K.N.King’s C Programming a Modern approach and am currently working my way through Robert Sedgewick’s Algorithms in C, but I am always happy to get new reading suggestions.