Challenge 5: Keylogger¶
Ever wondered what your keyboard is whispering to your OS? With eBPF, you can sneakily listen in—without crashing the system or setting off alarm bells!
For this challenge, you will create a stealthy eBPF-based keylogger that monitors specific keystrokes entered by the user and displays the captured input as a message.
This challenge will require you to efficiently manage input events, use eBPF maps and perf buffers, and ensure smooth real-time logging.
Description¶
For this challenge, the files to download are simply the template for your code:
$ wget --no-check-certificate https://people.montefiore.uliege.be/~gain/courses/info0940/asset/keylogger.tar.gz
$ tar -xzvf keylogger.tar.gz
Your task is to develop a keylogger that tracks and stores specific keystrokes
entered by the user, then displays all the saved keys when the user presses the
ENTER
key. All the keys must be shown by the eBPF program using a perf
buffer.
What you need to do¶
Your task is to write an eBPF program that captures and processes specific keystrokes entered by the user. The program must efficiently track keystrokes and store them in a data structure, ultimately constructing a buffered message of fixed size : 32 characters (without considering the null terminator).
The keystrokes to handle are:
Alphabetic characters: both uppercase (
A-Z
) and lowercase (a-z
)Numeric characters:
0-9
Special symbols:
,.-=
and spaceENTER (
↵
): Displays the buffered message via the perf bufferTAB (
↹
): Clears the entire buffered messageBACKSPACE (
⌫
): Removes the last recorded keystrokeSHIFT/CAPSLOCK (
⇪
): Toggles the character case
Your program should maintain a buffered message, updating it
dynamically based on user input. When the TAB
key is pressed, the
buffer should be completely cleared, and when BACKSPACE
is
pressed, only the last saved character should be removed—simulating a
real-time text editor effect. Note that it has no effect if the
buffered message size is 0. Pressing ENTER
should display the
message on stdout. The program must also correctly handle both
uppercase and lowercase characters (via SHIFT
and CAPSLOCK
).
Any other keystrokes must be ignored.
When the buffered message reaches its maximum size (32 characters), the oldest characters should be replaced, implementing a circular buffer behavior.
Important
Consider that by default,
CAPSLOCK
is never enabled.Handling repeated keystrokes (when a key is held down during several seconds) is not required.
For testing, you need to enter the keys directly in the virtual machine rather than in the SSH client on your terminal.
Verify that your keyboard layout is the same on both your SSH client and the virtual machine. To ensure consistency, use
sudo loadkeys be
orsudo loadkeys us
in both environments.To handle numbers, do what’s easiest for you among those three options (no need to handle all of them, just one is enough):
Use the numpad;
Use the keys above the letters (for example on an AZERTY keyboard:
&é"'(§è!çà
);Use shift with the keys above the letters (for example on a AZERTY keyboard: SHIFT +
&é"'(§è!çà
).
As example, the figure below illustrates the behavior of the keylogger.

Regarding the small notes:
*1: “HelLo” was initially typed. Then, the
BACKSPACE
key was used to remove the ‘L’, and ‘l’ was typed instead. As a result, the final output displayed is “Hello”, where ‘L’ has been deleted and replaced by ‘l’.*2: The message “It is a circular buffer” was deleted using several backspaces.
*3: After pressing
ENTER
, two solutions can be considered: (1) either truncating the message until the end (e.g., the ‘E’ is also deleted) or (2) tracking the deletion to keep the last character(s). Both approaches are valid, and choosing one over the other will not affect your mark.