May 31, 2026
I Built a Keylogger Detector in C++ at 19 — Here’s How It Actually Works
This is the story of one of my recent projects — a keylogger detector built from scratch in C++ using low-level Windows API internals. Not…
By Muhammad Adnan | Penetration Tester
4 min read
This is the story of one of my recent projects — a keylogger detector built from scratch in C++ using low-level Windows API internals. Not because someone assigned it to me. Because I wanted to understand how keyloggers actually work at the lowest level — and then build something that could catch them.
Why Keyloggers Are Still a Serious Threat
Keyloggers are one of the oldest and most effective attack tools in existence. They silently record every keystroke you type — passwords, credit card numbers, private messages — and send that data to an attacker without you ever knowing.
Modern keyloggers don't work the way most people imagine. They don't need to physically access your keyboard. Instead, they operate entirely inside Windows itself, hooking into the operating system's own keyboard event pipeline.
And that's exactly where I decided to fight them.
Understanding the Attack Before Building the Defense
Before writing a single line of detection code, I needed to understand how keyloggers actually operate at the Windows API level.
Windows processes keyboard input through a system called the hook chain. When you press a key, Windows passes that event through a chain of registered callbacks before it reaches your application. Legitimate software uses this for things like accessibility features and input method editors.
Keyloggers abuse this exact mechanism. They register a low-level keyboard hook using SetWindowsHookEx() with the WH_KEYBOARD_LL flag, inserting themselves into that callback chain. Every keystroke passes through them before reaching its destination.
This gives me a detection surface. A keylogger sitting in that hook chain has to do work — capture the keystroke, log it, maybe encrypt it, then pass it along. That work takes time. Measurable, detectable time.
Detection Technique 1: Hook Chain Timing Analysis
The first detection method I implemented exploits exactly this timing side-channel.
Here's the core idea:
void DetectHookChainingDelay() {
// Install a test hook
// Simulate synthetic keystrokes
// Measure the time each callback takes
// Flag anomalies above threshold
}void DetectHookChainingDelay() {
// Install a test hook
// Simulate synthetic keystrokes
// Measure the time each callback takes
// Flag anomalies above threshold
}A clean system with no keylogger processes keyboard hook callbacks in microseconds — consistently. When a keylogger is present, that timing spikes. The keylogger needs processing time to do its dirty work.
My tool sets its own hook, fires synthetic keystrokes using SendInput(), and measures the round-trip time using high-resolution timestamps from QueryPerformanceCounter(). If the maximum callback delay exceeds a threshold, it raises a warning.
When I ran this on my own machine, the output was revealing:
[*] Running Timing-Based Hook Detection...
[*] Hook set. Simulating keystrokes to measure hook chain delay...
[+] Maximum hook callback delay: 7437 microseconds.
[!] WARNING: High hook chain delay detected!
A keylogger might be present and intercepting keystrokes.[*] Running Timing-Based Hook Detection...
[*] Hook set. Simulating keystrokes to measure hook chain delay...
[+] Maximum hook callback delay: 7437 microseconds.
[!] WARNING: High hook chain delay detected!
A keylogger might be present and intercepting keystrokes.7437 microseconds. That's a real signal — not noise. Something in my hook chain was adding latency.
Detection Technique 2: Heuristic Process Scanning
Timing analysis alone isn't enough. Some sophisticated keyloggers are optimized to minimize their processing delay specifically to evade timing-based detection. So I built a second layer: behavioral heuristic process scanning.
The scanner uses CreateToolhelp32Snapshot() and Process32Next() to enumerate every running process on the system, then evaluates each one against a set of behavioral indicators that keyloggers commonly exhibit:
Indicator 1 — No visible window Legitimate applications almost always have a visible window or system tray presence. A process running silently with no UI is suspicious.
Indicator 2 — Running from AppData or Temp Windows system processes run from C:\Windows\System32. User applications run from Program Files. A process running from AppData\Local, AppData\Roaming, or Temp directories is a significant red flag — these are writable locations that malware uses to persist without administrator privileges.
Indicator 3 — Suspicious process name patterns Known keylogger families have characteristic naming conventions. The scanner checks against these patterns.
The output on my test machine caught something interesting:
[!] Suspicious Process Found: OneDrive.Sync.Service.exe (PID: 11968)
Reason: No visible window, running from suspicious path:
C:\Users\Username\AppData\Local\Microsoft\OneDrive\...\OneDrive.Sync.Service.exe
[!] Suspicious Process Found: <Application name>.exe (PID: 15840)
Reason: No visible window, running from suspicious path:
C:\Users\Username\AppData\Local\Programs\<Application NAme>.exe[!] Suspicious Process Found: OneDrive.Sync.Service.exe (PID: 11968)
Reason: No visible window, running from suspicious path:
C:\Users\Username\AppData\Local\Microsoft\OneDrive\...\OneDrive.Sync.Service.exe
[!] Suspicious Process Found: <Application name>.exe (PID: 15840)
Reason: No visible window, running from suspicious path:
C:\Users\Username\AppData\Local\Programs\<Application NAme>.exeBoth are legitimate applications on my machine — but they perfectly match the behavioral profile of a keylogger. This is exactly why malware analysts can't rely on automated tools alone. Context matters. A heuristic scanner gives you leads, not verdicts.
This is one of the most important lessons in malware analysis: the goal is not to replace human judgment, but to surface the right processes for a human analyst to examine.
What I Learned Building This
1. Offensive knowledge makes you a better defender. You cannot detect what you don't understand. Before writing a single line of detection code, I had to deeply understand how keyloggers install hooks, what APIs they use, and how they persist. That offensive mindset — thinking like an attacker — is what makes the detection logic effective.
2. False positives are not failures — they're data. OneDrive triggering my heuristic scanner isn't a bug. It's proof that Microsoft's own software uses the same behavioral patterns as malware. That's a legitimate security finding, not an error.
3. Timing side-channels are everywhere. The hook chain timing technique I used here is a simplified version of the same class of attacks used in side-channel cryptographic attacks. The principle — that computation takes measurable time, and that measurement reveals hidden information — applies at every level of the stack.
4. Low-level C++ is irreplaceable for security work. Python is great for scripting and automation. But when you need to call SetWindowsHookEx(), enumerate process memory, and measure nanosecond-level timing, you need C++. There's no abstraction layer to hide behind.
What's Coming Next
This is version 1.0. The detection engine works, but there's much more to build:
- Registry persistence scanning — Keyloggers persist through registry run keys. The next version will enumerate these automatically.
- DLL injection detection — Advanced keyloggers inject into legitimate processes rather than running standalone. Detecting anomalous DLLs loaded into trusted processes is the next frontier.
- JSON report export — For use in incident response workflows and integration with SIEM systems.
- YARA rule integration — Matching running processes against known malware signatures.
- Linux port — Detecting
LD_PRELOADhook-based keyloggers on Linux systems.
The Code
The full source code is available on GitHub:
github.com/adnancyber-he/KeyloggerFinder
Build it yourself, test it, break it, improve it. That's the point.
If you work in security and want to connect:
- Portfolio: muhammadadnant.vercel.app
- LinkedIn: linkedin.com/in/muhammad-adnan-3b2aab287
- GitHub: github.com/adnancyber-he
This tool is intended strictly for educational purposes, authorized security testing, and malware research in controlled environments. Always obtain proper written authorization before testing on systems you do not own.