Keyloggers remain a staple in many red team operations and threat actor campaigns, offering deep insight into user behavior, passwords, and command history. I wanted to write one in Rust, aiming for a binary that was memory-safe, efficient, and integrated directly with Linux’s input subsystem.
Instead of intercepting keystrokes through high-level APIs or the X server, I went straight to the evdev interface — the Linux kernel’s raw input event device system.
This gives us direct, low-noise access to keystroke events from /dev/input/event* without any display server dependencies.
How It Works
Here’s the full source code:

Lets break it down line by line.
Imports

Here we are importing a number of important crates:
- evdev
- For interacting with the evdev interface, to capture keystrokes from the kernel’s raw input event device stream.
- File
- To create files on the filesystem (our file which will contain captured keystrokes).
Main Function

Here we open a handle to /dev/input/event9, which corresponds to a keyboard device on this system. This gives us raw access to keystroke events.
Your device may vary, and you will have to enumerate which file corresponds to the hardware device you are wanting raw input from.

We then create a benign looking file in the /tmp directory, to store our captured keystrokes. You can name this file in any way you wish, to better blend into your target environment.

We then enter our main loop, which will continuously:
-
- Pull new input events from the kernel using
device.fetch_events() - Filter the events to only the keyboard
- Input using if let
InputEventKind::Key(key) - Ensure
ev.value()is equal to 1 , that way we only log key press events (ignoring key release events) - Write the captured event to our log file stored in
/tmp, usingwriteln!
- Pull new input events from the kernel using
I hope you’ve enjoyed this post, and are inspired to pick up rust and get creative!
MITRE ATT&CK Techniques:
T1056.001 — Input Capture: Keylogging
T1036 — Masquerading


