Register for your free account! | Forgot your password?

You last visited: Today at 12:33

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



C# Keyhook (WinAPI)

Discussion on C# Keyhook (WinAPI) within the Coding Snippets forum part of the Coding Releases category.

Reply
 
Old   #1


 
elite*gold: 1091
Join Date: Jun 2007
Posts: 19,836
Received Thanks: 7,180
C# Keyhook (WinAPI)

Code:
using WPARAM = System.IntPtr;
using LPARAM = System.IntPtr;


public struct KeyHookEventArgs
{
    public Keys PressedKey { get; set; }
    public string TranslatedCharacters { get; set; }
}

public class KeyHook : IDisposable
{
    public enum HookType
    {
        WH_KEYBOARD_LL = 13,
        WH_GETMESSAGE = 3
    }

    public enum WindowsMessage : uint
    {
        KEYDOWN = 0x100,
        SYSKEYDOWN = 0x0104,
        KEYUP = 0x0101,
        SYSKEYUP = 0x0105
    }

    public enum MapVirtualKeyMapType : uint
    {
        VK_TO_VSC = 0x00,
        VSC_TO_VK = 0x01,
        VK_TO_CHAR = 0x02,
        VSC_TO_VK_EX = 0x03,
        VK_TO_VSC_EX = 0x04
    }

    public enum VirtualKey
    {
        SHIFT = 0x10,
        LSHIFT = 0xA0,
        CONTROL = 0x11
    }

    private IntPtr _HookID = IntPtr.Zero;
    private bool _shiftPressed = false;

    public Func<KeyHookEventArgs, bool> OnKeyPressed = (KeyHookEventArgs eventArgs) => false;

    public KeyHook(Func<KeyHookEventArgs, bool> onKeyPressed)
    {
        OnKeyPressed = onKeyPressed;
    }

    public void Install()
    {
        _HookID = SetWindowsHookEx((int)HookType.WH_KEYBOARD_LL, HookCallback, IntPtr.Zero, 0);
    }

    public void Uninstall()
    {
        UnhookWindowsHookEx(_HookID);
    }

    private delegate IntPtr LowLevelKeyboardProc(
        int nCode, WPARAM wParam, LPARAM lParam);

    private IntPtr HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
    {
        uint processID;
        var windowThreadID = GetWindowThreadProcessId(GetForegroundWindow(), out processID);
        var threadID = GetCurrentThreadId();

        /* Kann zum filtern benutzt werden
        using (var process = Process.GetCurrentProcess())
        {
            if (process.Id != processID)
                return CallNextHookEx(_HookID, nCode, wParam, lParam);
        }*/

        if (nCode >= 0)
        {
            var virtualKey = (uint)Marshal.ReadInt32(lParam);

            if ((int) wParam == (int) WindowsMessage.KEYDOWN || (int) wParam == (int) WindowsMessage.SYSKEYDOWN)
            {
                AttachThreadInput(threadID, windowThreadID, true);
                
                var keyboardState = new byte[256];
                GetKeyboardState(keyboardState);

                if (_shiftPressed)
                    keyboardState[(int) VirtualKey.SHIFT] |= 0x80;
                else
                    keyboardState[(int) VirtualKey.SHIFT] |= 0x00;

                if (virtualKey == (int) VirtualKey.LSHIFT)
                    _shiftPressed = true;

                var charBuffer = new char[16];
                var translatedCharacterCount = ToUnicode(virtualKey,
                    MapVirtualKey(virtualKey, (uint) MapVirtualKeyMapType.VK_TO_VSC),
                    keyboardState, charBuffer, charBuffer.Length, 0);

                AttachThreadInput(threadID, windowThreadID, false);

                var forwardEvent = OnKeyPressed(new KeyHookEventArgs()
                {
                    PressedKey = (Keys) virtualKey,
                    TranslatedCharacters = new string(charBuffer, 0, translatedCharacterCount)
                });

                if (forwardEvent)
                    return lParam;
            }
            else if ((int) wParam == (int) WindowsMessage.KEYUP)
            {
                if (virtualKey == (int)VirtualKey.LSHIFT)
                    _shiftPressed = false;
            }
        }

        return CallNextHookEx(_HookID, nCode, wParam, lParam);
    }


    public void Dispose()
    {
        Uninstall();
    }

    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
    public static extern int ToUnicode(uint virtualKey, uint scanCode, byte[] keyStates, [MarshalAs(UnmanagedType.LPArray)] [Out] char[] chars, int charMaxCount, uint flags);

    [DllImport("user32.dll")]
    static extern uint MapVirtualKey(uint uCode, uint uMapType);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook,
        LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("User32.dll")]
    private static extern IntPtr GetForegroundWindow();

    [DllImport("User32.dll")]
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    [DllImport("user32.dll")]
    private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

    [DllImport("kernel32.dll")]
    private static extern uint GetCurrentThreadId();
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
        WPARAM wParam, LPARAM lParam);

    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetKeyboardState(byte[] lpKeyState);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);
}
Voraussetzung: Aktive Message loop. Bei WinForms Anwendungen läuft die ohnehin schon, ansonsten muss diese halt manuell implementiert werden.

Ihr braucht euch nicht im Zielprozess befinden, da der Hook global ist und jede Anwendung die auf dem selben Desktop läuft, gehooked wird.

Nutzung:

Code:
using (var keyHook = new KeyHook((KeyHookEventArgs eventArgs) =>
                {
                    // return false wenn der Key an die Applikation selbst weitergeleitet werden soll,
                    // return true wenn der Key nicht weitergeleitet werden soll
                }))
                {
                    keyHook.Install();

                    tagMSG msg;
                    bool res = true;
  
                    while (res)
                    {
                        res = Convert.ToBoolean(GetMessage(out msg, IntPtr.Zero, 0, 0));
                        TranslateMessage(ref msg);
                        DispatchMessage(ref msg);
                    }
                }
Der Rückgabewert im Callback (sofern ein Key gedrückt wird) ist sehr wichtig. Wenn ihr nämlich true (statt false) zurückgebt, bekommt die originale Anwendung die ihr gehooked habt die Information nicht, dass der Key gedrückt wurde. Ist relativ handlich um alternativen Input zu ermöglichen, von dem die Anwendung nichts mitbekommen soll.
Mostey is offline  
Thanks
3 Users
Old 07/28/2015, 19:55   #2
 
saixo's Avatar
 
elite*gold: 0
Join Date: Oct 2014
Posts: 606
Received Thanks: 371
nicht dass ich es vor hätte aber könnte man mit der methode einen keylogger schreiben? ^^
saixo is offline  
Old 07/29/2015, 09:01   #3
 
elite*gold: 67
Join Date: Aug 2014
Posts: 1,323
Received Thanks: 928
Natürlich. Du jedoch nicht, da du das fragen musst.
Xio. is offline  
Reply




All times are GMT +2. The time now is 12:33.


Powered by vBulletin®
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2026 elitepvpers All Rights Reserved.