Keylogger at home. We write a keylogger in C # that is not fired by antiviruses.

Father

Professional
Messages
2,601
Reputation
4
Reaction score
643
Points
113
Combat keyloggers with tons of features and anti-detection protection can cost tens, if not hundreds of dollars. But a keylogger is not such a complicated thing, and if you wish, you can make your own and even avoid being detected by antiviruses. In this article, I will show you how to do this, and at the same time we will practice developing programs in C #.

We set the task
We will not be wise and restrict ourselves to the necessary minimum. Suppose we want to get the victim's password from FB and we can briefly gain physical access to the computer. Wherein:
  • we do not bother the victim with unnecessary windows, icons in the taskbar, error messages and the like;
  • we have access to the target computer only once and for a very short time;
  • we will be able to collect logs from the same local network;
  • the antivirus must be silent;
  • we do not take into account the firewall and assume that we will give it permission manually when the keylogger is planted;
  • we will not try to hide the process and will only give it an inconspicuous name.
The victim can also use the password manager, then in the log we will only get Ctrl-C and Ctrl-V. In this case, we will also monitor the contents of the clipboard.

We will write in C # in Visual Studio. Looking ahead, I will say that as a result I got two versions of the program - one works through the interception of WinAPI, the other I call myself a "crutch". But this less beautiful version gives different results when scanned by antiviruses, so I'll tell you about it as well.

Theory
When you press a button, the operating system sends notifications to those programs that want to know about it. Therefore, the easiest way to intercept keyboard input is to receive keystroke messages. If we cannot do this (for example, the SetWindowsHookEx function is prohibited by antivirus or something else), we can pull raw input without it. There is such a function - GetAsyncKeyState, which takes a key number and allows you to find out whether it is pressed or released at the time of the call. Actually, the algorithm of actions will be as follows: every N ms we interrogate all the buttons and find out their state by entering the pressed ones into a special list. Then we process the list, taking into account the state of the Caps Lock, Num Lock, Shift, Ctrl and so on. We will write the received data to a file.

Writing the code
First, let's open Visual Studio and create a new Windows Forms (.NET Framework) project. Why Windows Forms? If we choose a regular console application, then an ugly black window will be created every time it starts, and we agreed not to bother the user. Also, until we have created the form (and we will not create it), no icons will appear in the taskbar - an important part of the hidden work. Now delete the automatically generated Form1.cs file with all the giblets and open Program.cs.

start-class.png

Main plug

A program template is already waiting for us here, but it will not work just like that. The first step is to remove lines 10-12 and 16-18. Now we change the method declaration from static void Main() to static void Main(String[] args). We need this so that we can define our arguments on restart.

Now let's add using System.IO; for working with files, System.Runtime.InteropServices for working with WinAPI and System.Threading for pausing a stream. If you do not want to write a crutch version, it is better to skip this section and go straight to the next one.

Import GetAsyncKeyState from user32.dll:
Code:
[DllImport ("user32.dll")]

And we add the actual logging of clicks, collecting ten of them, so as not to do too many disk operations:
Code:
while (true)

terrible-log.png

It will be inconvenient to decrypt such a log

It doesn't look very nice, but you can forget about readability. First, our code pulls input not only from the keyboard, but also from the mouse (all sorts of LButton and RButton). So let's not record the keystroke if it's not a symbolic key. Let's replace the content if in the loop with this:
Code:
// Improved validation of entered characters //

After such editing, the log became much cleaner (see figure).

cleaned-log.png

Looks neater already

This is much better! Now we need to add handling for the Shift and Caps Lock buttons. Let's add the following code at the beginning of the loop:
Code:
// An even more advanced check //

We now have a variable that indicates whether we need to keep the letter capitalized. We check it and add the characters to the buffer.

my-variant.png


The the Next Problem of The of of The - of of IT of messages like <Oemcomma>, <ShiftKey>, <Capital> and the like. They make it much more difficult to read the log, so you will have to fix it. For example, <Oemcomma> is a common human comma, and <Capital> is nothing more than a Caps Lock. Having tested the logger a bit on my computer, I gathered enough material to put the log in order. For example, some characters can be replaced immediately.
Code:
// Check for space and Enter //

But things seem to be more difficult to overcome. The shift, by the way, has two different options - right and left. We remove all this, because we have already received the state of the capital letters.
Code:
if (((Keys) i) .ToString (). Contains ("Shift") || ((Keys) i) == Keys.Capital) {continue; }

After running the logger for a while, we find other buttons that need to be processed in a special way:
  • Num Lock;
  • function keys;
  • Print Screen;
  • Page Up and Page Down;
  • Scroll Lock;
  • Shift + number key combination;
  • Tab;
  • Home and End;
  • Start;
  • Alt;
  • arrow keys.
We add more checks and replacements, and the log becomes readable. In general, it is already quite good! Among the shortcomings: there is no support for the Russian layout, which, however, is not so important if our goal is to get passwords.

Let's see what the antivirus will say ...

avast-1.png


Antivirus response when forced scanning
avast-2.png

Reaction at startup (later says that everything is ok)

Uploading the sample to VirusTotal to check the rest. Result: only 8 out of 70 antiviruses suspect something.

image.jpg


Beautiful option
Now let's try to do it more correctly and we will intercept messages about keystrokes on the keyboard. The first steps are the same: we create a Windows Forms project and come up with an inconspicuous name (for example, WindowsPrintService). In the stub that Visual Studio created for us, change void Main() to void Main(String[] args). Now let's do a simple argument check:
Code:
if (((Keys) i) == Keys.Space) {buf + = ""; continue; }

There is quite a lot of code below, I will not give it all. There are flags Caps Lock, Shift, and more, and clicks are determined by the giant Switch. But I want to show not this, but the installation of the hook on the keyboard.

sethook.png

Installing the hook on the keyboard

First, we put a reference to our function in a variable callback, then we get the handle of our program, then we set the hook. And then we always process the received messages every 5 ms ( PeekMessageA). An important point is the declaration of the callback function, which must exactly match the WinAPI, as well as the transfer of control to the underlying handlers (see below).
Code:
private static IntPtr CallbackFunction (Int32 code, IntPtr wParam, IntPtr lParam)

And here we transfer control further along the chain of hooks:
Code:
return CallNextHookEx (IntPtr.Zero, code, wParam, lParam)

callback-listing.png

Callback function listing

This screenshot shows the code of our callback function with some abbreviations (the parsing of keystrokes did not fit). Pay attention to the call mentioned above CallNextHookEx, which is needed so that not only we receive messages about keystrokes.

switch.png

Switch that parses Shift + number key

This screenshot shows the processing of numeric keystrokes with the key held down, and the next one shows the situation with Caps Lock and Shift.

caps-and-shift-handler.png

Determine the case of the entered character

Clipper
Clipper is a program designed to steal data from the clipboard (name - from the word clipboard). This can be useful, for example, in case the victim uses a password manager and copies passwords from there.

Let's create a new Windows Form, delete the files <FormName> .Designer.cs and <FormName> .resx. Now let's go into edit mode by pressing F7 and start writing the code. Add using System.Runtime.InteropServices and import WinAPI (in the screenshot - in a separate class).

native-methods.jpg

Class that imports WinAPI methods

Insert the following code into the form constructor:
Code:
NativeMethods.SetParent (Handle, NativeMethods.HWND_MESSAGE);

The first call will make our window capable of receiving system messages, and the second will assign a handler for incoming messages.

Now let's declare a variable of type String and name it lastWindow. We will now override the default message handling function ( void WndProc(ref Message m)):
Code:
protected override void WndProc (ref Message m)

For this code to work, I took a ready-made class that you can simply add to the project and not bother with creating wrappers around WinAPI. You can get it on Pastebin.

It's easy to start the clipper: add a link to the assembly System.Windows.Forms.dll, add using for System.Windows.Forms and System.Threading and add the following lines to the logger start method:
Code:
Thread clipboardT = new Thread (new ThreadStart (

Simply? That's it. You only need to add this call after assigning a handler for Trace, otherwise all the output will fly away to unknown distances.

Collecting logs
The next thing we need is to collect the log remotely. Since we are not going to engage in industrial espionage, but only want to see what some of our relatives or acquaintances are doing, we can first restrict ourselves to access from the local network. To do this, it will be enough to build a minimalistic HTTP server into our project. Here is the correct source, and here is the version I modified.

The use is also very primitive: it is enough to create an object of our server and it automatically takes the address localhost:34000 and <InternalIP>:34000 under the HTTP and at the same address port 34001. The server will return a list of files and folders as a list, or the contents of the file, if the file is requested.

In the constructor, you need to pass the path to the folder where the logs are written (or any other that may be needed). By default, logs are written to the current folder, which means that we pass it to the constructor Environment.CurrentDirectory.

Autostart
There are many ways to get into autorun: here is the "Startup" folder, and a bunch of places in the registry, and installing your own driver, and creating a service. However, the registry and drivers are monitored by any decent antivirus, and creating a service is too crooked option that can break in any moment, although in extreme cases it's not bad.

We will simply create a task in the task scheduler and ask it to launch our logger with the necessary parameters every time a user logs on to the system. To work with the task scheduler, we take the Microsoft.Win32.TaskScheduler package from NuGet. I posted the code for working with it on Pastebin. Don't forget to correct the path referenced by the planner entry.

I showed the algorithm of actions of the logger at startup in the picture.

algo.png

Algorithm of actions

Antivirus response
Checking the prettier version on VirusTotal shows that it is detected by a greater number of antiviruses than before - 15 out of 70. However, among the rest there are almost all our popular home antiviruses. In general, the main thing is not to run into Avira or NOD32.

image2.jpg


Checking the window title
If our alleged victim immediately after logging in to the systems went to log in to VK, then consider himself lucky. But what if instead she sat down to play CS: GO? Have of will of the Password of The of to pull out tons of of The The characters W, A, S, D and spaces, and with the "spike" option is more Complicated. Therefore, let's pump our logger: we will record keyboard signals only when the browser window with the login form is active. To do this, let's go back to WinAPI, and specifically to the function GetForegroundWindow.

winapi-import.png

Importing WinAPI

The seen another imports folder of The folder of of The folder with with with In That <br> <br> <br> we feature the the Up the Up Up Need: GetWindowText. It is needed to get its title from the window handle. The algorithm of actions here is also very clear: first, we get the title of the active window, then we check whether it is necessary to turn on the logger, and turn it on (or off). Implementation of this scheme:
  1. Let's create a function IsForegroundWindowsInteresting. Its code will be like this:
    Code:
    bool IsForegroundWindowInteresting (String s)
  2. At the very beginning of our function, CallbackFunction insert
    Code:
    if (IsForegroundWindowInteresting ("Welcome! | FB") ||

As you noticed, I am checking two options, since I do not know what language the victim is using. If we did not find an interesting window, then we simply go to the next handler and do not load the computer with unnecessary disk operations.

Searching by log
Now let's assume that the log has grown to an alarming size anyway, and we need to extract, for example, a phone number from it in order to know where to look for a password. Regular expressions are best suited for this, in C # they are provided by the class Regex.

For obvious reasons, we will analyze the logs on our machine, so we will create a separate program. To use regular lines, let's add using System.Text.RegularExpressions and create a method that accepts the path to the log file as input, and displays all the phone numbers found on the console.
Code:
public void FindTelephoneNmbers (String path)

The password will follow the phone number.

Outcomes
So, we made sure that creating a keylogger is not a problem. Moreover, our self-written spyware, with all its limitations, has an important advantage: antiviruses do not know in advance about its existence, and not all of them determine its functions. Of course, a lot can be further improved. For example, add the ability to access via the Internet, teach a keylogger to work with different keyboard layouts, add screenshots and other features. My goal in this article was to show how easy it is to make such a program, and to inspire you for future exploits. Hope I did it!

xakep.ru
 
Top