This post is a tutorial on how to develop a keylogger for Windows using Python. A keylogger is an application used to capture keystrokes from an unsuspecting user. I'll walk you through the steps of building your own keylogger (with ability to store a file locally or upload it to Dropbox) and explain the steps along the way so you too can start experimenting with Python. In addition, I'll just post the script because I know that's what some of you want.
The following will be broken down into three parts:
- Setting up your Python environment
- Developing the Python script
- Script execution
introduction
Let's start this tutorial off by defining our project. We'll begin by listing the following project details: application type, application functionality, development language, and application requirements. The application type is the high level description of what our application will actually do, or what the application's purpose will be. The application functionality is process of defining the application type, listing out the processes that the application will perform to succeed, trying to map out what kind of work the application will perform. The development language is the programming language that the application will be created in, such as Python or C# or whatever you like. Finally, the application requirements list out necessities for our application to function (nothing stopping you from removing/adding functionality which will remove/add requirements). Let's take a look at the details for our Windows keylogger.
Project: Simple Windows Keylogger
Application Type
- Keylogger: The application will record all user keystrokes in a local text file.
- Collect all user keystrokes
- Save keystrokes to local file
- Upload file to DropBox
- Create Windows registry runkey to automatically start keylogger on user logon
- Prevents multiple instances of keylogger from executing at once
- Allow user to define: keylogger function (write only locally, or upload to DropBox), keylogger write location, and if they want to create a Windows registry runkey
- Python 2.7
- Windows Operating System (Mutex and Registry functionality)
- Python dependencies (see Setting Up Your Python Environment)
- DropBox API key (see Setting Up Your Python Environment)
- Network connection (upload log to DropBox)
Now that we understand what our application will do and what we need to make that happen, we can start the process by setting up our environment, collecting and installing the functional requirements and making sure we have what we need to successfully develop our project: ThreatFix Windows Keylogger
setting up your environment
Let's go ahead and make sure our environment is set up to develop our application. In this section, we'll detail how to install Python 2.7, any application specific dependencies, and the Dropbox API. All of these steps are required to create our application, so only skip a section if you're absolutely sure you're good to go, alright?
Python 2.7
The first step in setting up your environment is through the installation and setup of the Python 2.7 framework. If you already have Python 2.7 installed and set up correct, you can skip to the next section: Python Dependencies. Start off by grabbing Python 2.7 here. Once you do that, go ahead and install it to your environment. After installing, let's make it easier on ourselves and set the file path for Python as an entry in our "Environment Variables". What this will do will allow us to call "Python.exe" generically, without having to specify a path, as the path is already defined for the system. One of the easiest ways to do this (through the Windows GUI) is to head to the "Start" menu, type in "System Variables", click on "Edit the system environment variables", and select "Environment Variables". When the Environment Variables window comes up, scroll down in the "System variables" section until you see "Path". Click "Edit" and in the "Variable value" field, append the path to "Python.exe" to the string. For instance, the following are my System Variable paths before and after the addition of Python.
System Variable "Path" - Before
Value: %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32
\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\
\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\
System Variable "Path" - After
Value: %SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32
\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;%SystemRoot%\Python27\
\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;%SystemRoot%\Python27\
Easy enough, right? Again, this allows us to call "Python.exe" without having to specify the direct path to Python every time. The following are what you'd see in the command line for "Python.exe" before and after adding it to your system path.
Note above how after modifying the system variable, I am able to execute Python easily, without having to list the direct path every time.
With that out of the way, we've successfully set up Python 2.7. Easy enough, right? Now, let's move onto the dependencies.
With that out of the way, we've successfully set up Python 2.7. Easy enough, right? Now, let's move onto the dependencies.
Python Dependencies
In this section, we will be discussing Python libraries not included by default that are needed to successfully use our keylogging application. Let's start by look at, and downloading, our libraries.
Library |
Description |
Download |
pyHook |
This library is a wrapper for global input hooks in Windows, providing the functions needed to detect and cause mouse and keyboard events. This will be used to track the user's input. |
|
pywin32 |
This library is used to perform additional Python functionality in Windows. This will be used to create and monitor our environment to prevent duplicate processes from executing. |
While there are both 32 and 64 bit versions of pywin32 available, I had trouble finding a 64-bit version of pyHook. Then I found it. To save you some time, I've uploaded a 64-bit bit version of pyHook. You can find a 64-bit version of pyHook below.
PyHook 64-Bit Download
pyhook-1.5.1.win-amd64-py2.7.zip |
Installing these libraries is quite easy. Simply follow the instructions and you're good to go. Just make sure you have the correct version downloaded prior to installation (32-Bit or 64-Bit)
Dropbox SDK
To enable Dropbox functionality in our application, we need to perform two actions: installing the Dropbox SDK on our system and generating a Dropbox access token.
Dropbox SDK Installation
Dropbox for Python allows a user to leverage the Dropbox API to establish communication between Dropbox and your host. To install Dropbox for Python, follow these instructions:
- Go to the Dropbox for Python github website.
- Click "Download ZIP" on the right side of the page.
- Extract the Dropbox zip file
- Using command line, install the Python package. You can do this by traversing to the unzipped folder and typing in the following command: "python setup.py install"
DropBox Access Token
The Dropbox generated access token will be used to link the application with our Dropbox, enabling us to upload our log. To get the access token, follow these instructions:
- Go to to Dropbox Application Developer website.
- Select "Create App" in the top right corner.
- Select "Dropbox API"
- Select "App folder"
- Name your App (Ex: Babby's First Keylogger)
- On your Application page, select "Generated Access Token" in the "OAuth 2" section.
- A long string of characters will appear, this will be the token you use to connect your application to your Dropbox. Save this string somewhere, we'll need it for our script.
If all of the above steps were followed and successful, then that means we have everything we need to develop our application. If you have any issues installing any libraries or getting Dropbox installed, drop a comment below and I'll try to help out.
developing the keylogger Application
This section will walk you through the creation of your keylogging application, coding the application functionality while attempting to perform error handling at the same time. We'll start by listing out the libraries we need to import, what modules we'll need, writing those modules, and writing error handling checks so our application doesn't crash.
Functions
Let's start off by defining our functions. These functions perform specific actions that can be executed at specific times or when a trigger occurs. For example, one function will be "runKey" whose only purpose is to create a Windows registry runkey. This function will be called when it's triggered in the code. All of these small functions make up the larger application. While most of these functions can be "combined" and don't necessarily need to be their own function - it's up to you how you want to write your code.
Function Name |
Functionality |
main |
Think of this function like a parent of other functions. It's purpose isn't to perform any "specific" action, but to instead start other functions at a specific time. |
argChecks |
This function is in charge of verifying that the user has input the correct command arguments, such as program function (local or dropbox), log path, and whether a runkey will be created. |
pathCheck |
This function's purpose is to verify whether or not the path the user put in is valid and can be written to. |
introMessage |
This function's only purpose is to display an application usage message to the user, usually when an error occurs. |
local |
This function is in charge of storing keystrokes to the local file. |
dbox |
This function uploads the local file to dropbox. |
runKey |
The runKey function creates a Windows user runkey to start this application on logon. |
onKeyboardEvent |
This function handles the collection of user keystrokes and determines additional functional execution. |
Imports
Imports are libraries used by the Python application to perform the actions you request. Without these imports, you would not be able to perform specific actions. For example, without the _winreg import, your application would be unable to perform actions on the Windows registry.
Import Name |
Functinality |
os |
This library provides miscellaneous operating system interface options. For example, if you want to read or write a file, this import can be used. |
sys |
This library provides system-specific parameters and functions. In our application, we will be using this library to collect and manipulate user arguments. |
threading |
This library allows multiple functions to execute at once. |
_winreg |
The _winreg import provides functionality to communicate with the Windows registry. |
dropbox |
The dropbox library allows us to communicate with Dropbox and upload our log file. |
pythoncom |
Works in conjuction with pyHook. Allows the application to receive notifications (keystroke events). |
pyHook |
This library allows the user to manipulate mouse and keyboard actions |
win32event |
Provides an interface to the Windows API, will be used in our application to manipulate mutex. |
win32api |
Provides an interface to the Windows API, will be used in our application to manipulate mutex. |
winerror |
Allows the application to monitor the error messages from Windows. |
Writing The Code
Let's jump into writing the code. I'll be working function by function until we complete the entire application. Along the way, I will explain the function's functionality (heh) along with any additional comments or error handling procedures that I thought would be beneficial. I will refrain from going line by line, but if you would like me to elaborate, just leave a comment.
Imports
Let's start with placing our imports in the script. These are all of the imports listed above, but with the addition of a "try, except" command. What this means is it attempts to import the libraries nested in the try command, but if it fails it will print a failure message and exit the application. This is to provide the user with some feedback instead of giving it a traceback message which may be confusing to some.
Imports
Dropbox API Key
Remember in the "Setting Up Your Environment" section when you generated your Dropbox API key? We're going to use it now. Place it after your imports in a variable. This variable is going to called by the Dropbox function and used to upload your log to your account. Easy enough.
Dropbox API Key
Creating the Message Function
This function is quite simple as it doesn't really "do" anything complex. This function simply prints a message to the user, typically when an error occurs.
Message Function
Creating the Local Function
This function, while small, is extremely important. This function creates a text file (in this case, ThreatFix_Keylogger_Log.txt) in the path that the user specified. The keys that are entered are placed in the log and the file is closed. This will happen every time the function is called, which is every time a keystroke occurs.
Local Function
Creating the Dropbox Function
This function will be used to upload the local file (from the above function) to Dropbox. The Dropbox API key you generated will be called (dropBoxKey) and the local file will be uploaded to the account. The variable "threadCount" will be used later to reset a timer, but for now - let's just implement this code block.
Dropbox Function
Adding the Windows Runkey
This function takes the current path and file name for the keylogger and places it in the Windows Registry under the User hive.
Windows Runkey Function
Checking the File Path
The Path Check function provides input validation for the user path. If the path cannot be found or the user does not have write privileges to that path, the application will exit and the user will receive a message to try a different path.
Path Check Function
Checking the User Arguments
While the Argument Check function is slightly longer, it's mainly because it is checking to ensure that all of the necessary arguments are used by the user. If not, the application will exit and the user will receive a specific message telling them what's wrong.
Argument Check Function
Creating the main Function
This is a hybrid of two functions, but I decided to combine it. In the first part, several variables are intialized and then the argChecks and pathCheck functions are called. These are all called in order, from top to bottom.
The second part is "actually" where the application execution begins. In this instance, this is also where the application will check to see if the file is already running. If it is, it will exit. If it is not already running, the main function (above it) is called and the application begins. Sloppy, sure. Works? Yep.
The second part is "actually" where the application execution begins. In this instance, this is also where the application will check to see if the file is already running. If it is, it will exit. If it is not already running, the main function (above it) is called and the application begins. Sloppy, sure. Works? Yep.
main Function
The Keyboard Monitor Function
The final function, onKeyboardEvent, is responsible for storing the keystrokes in variable "key". Once the key is stored, the application runs the local, dropbox, and/or runkey function as specified by the user.
Keyboard Event Function
Finalized Code
That's it! Not much code. It can certainly be more efficient and trimmed down, but you now have a fully functional Windows keylogger written in Python.
ThreatFix Simple Keylogger
Application Testing
Now that we have our code in place, we can go ahead and test it out! Assuming you copied the code, or correctly modified your own, everything should be good to go. Let's take a look at the functionality.
Local Log
You can test (and later user) the Python script using Command Line. By entering the command seen in the image below, a file will be created in the %Appdata% directory. This file will be your logger file and will update with every keystroke.
Dropbox Upload
By just modifying the command "Local" in the above image to "Dropbox", you can upload the log straight to Dropbox in 60 second increments (timer countdowns after a keystroke and resets after upload. This method still keeps a log in the %Appdata% directory. Feel free to modify this to put keystrokes in memory or remove the file upon upload.
Conclusion
Well there you have it, a quick tutorial on how to create a simple Windows Keylogger. I'll probably expand on some of these sections in the next few days, but for now take a stab at making your own. Make some new modules, change my code up - tell me what you do and how you did it.
-Paul
-Paul