Skip to content

oscarmuya/keylogger.rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Low-Level Linux Keylogger - Pure Rust Implementation (No External Crates)

Prerequisites

  • Linux operating system
  • Rust toolchain installed
  • Root/sudo access (required to read /dev/input devices)

How It Works

In linux events are stored in files available at /dev/input/eventN. Keyboard events are recorded in one of these file. To make a keylogger we'll need to know which file is responsible for keyboard events.

Finding the Keyboard Event File

In order to know which file is responsible for keyboard events we will first get the contents of /proc/bus/input/devices and look for the event file mapped to the keyboard.

This information is not directly readable - we need to parse the contents to identify the correct eventN file. The file contains input device data separated by \n\n in a format like below:

I: Bus=0011 Vendor=0001 Product=0001 Version=ab83
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/devices/platform/i8042/serio0/input/input3
U: Uniq=
H: Handlers=sysrq kbd leds event3
B: PROP=0
B: EV=120013
B: KEY=6000000000000020 0 0 110500f02100007 ff803078f900d401 feffffdfffcfffff fffffffffffffffe
B: MSC=10
B: LED=7

So we'll need to separate each input block and find out which belongs to the keyboard. We'll be able to know this after parsing and understanding the key mapping:

B: KEY=6000000000000020 0 0 110500f02100007 ff803078f900d401 feffffdfffcfffff fffffffffffffffe

This data contains the keys that are mapped to this input device stored as hexes. So we'll convert each hex chunk to binary and see which input block will have the most keys mapped to it which will be our keyboard.

Steps to Parse the Keyboard

  1. We will split on the whitespaces to get each hex chunk.
let chunks: Vec<&str> = hex.split_whitespace().collect();
  1. Convert each hex chunk to u64 integer.
let num = u64::from_str_radix(chunk,16);
  1. Count the number of activated keycodes by counting the number of one bits.
num.count_ones();

Now with this we'll get the file responsible for keyboard events.

Reading contents of the eventN file.

When a keyboard event is recorded its written into the eventN file. Each event is 24 bytes. The 24 bytes are arranged as:

  • Bytes 0-15 (Timestamp): struct timeval — 8 bytes for seconds, 8 bytes for microseconds
  • Bytes 16-17 (Type): Event type (u16) — value of 1 indicates EV_KEY (keyboard event)
  • Bytes 18-19 (Code): Key code (u16) — identifies which key
  • Bytes 20-23 (Value): Event value (i32) — 1 for key press, 0 for key release, 2 for key repeat

We create a function that opens the eventN file and continuously reads 24-byte chunks in a loop. We filter for events where:

  • Type == 1 (EV_KEY, keyboard events)
  • Value == 1 (key press only, ignoring key release)

To improve performance and avoid blocking the main thread, the keylogger uses a multi-threaded approach. A dedicated thread is spawned to read from the event file. This thread sends the keycodes to the main thread through a channel (mpsc).

Mapping Keycodes to Keys

Linux keycodes are standardized numbers (e.g., 30 = 'a', 57 = space, 28 = Enter). We use a match statement for a fast and efficient keycode-to-character mapping. This is more performant than a HashMap for this use case.

We then save the key presses to a file keylog.txt.

For maximum performance, we:

  • Use a dedicated thread for reading keyboard events.
  • Use BufWriter with a large buffer (64KB) to minimize disk I/O
  • Accumulate keypresses in memory
  • Flush to keylog.txt periodically rather than on every keystroke

Usage

  1. Build the project:
cargo build --release
  1. Run with sudo (required for /dev/input access):
sudo ./target/release/keylogger
  1. View captured keystrokes:
cat keylog.txt

About

Low-Level Linux Keylogger Implementation in Rust with no external crates.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages