At CYFIRMA, we are dedicated to delivering timely insights into emerging threats and malicious tactics that pose risks to both organizations and individuals. This report offers an analysis of a newly identified keylogger that operates via a PowerShell script.
In cybersecurity, keyloggers are among the most dangerous types of malware, as every keystroke on an infected system is monitored, capturing sensitive information like passwords and credit card details with remarkable stealth and accuracy.
A keylogger is a form of spyware that infiltrates a system, allowing attackers to capture every keystroke to gather sensitive information from victims, such as online banking credentials and personal conversations. The most common method of keylogger infection typically starts with a phishing email or a malicious link. Keylogging functionality is also frequently embedded within remote access trojans as part of a broader toolkit of malicious capabilities. In our investigation, we identified the Keylogger hash from Malware Bazaar, which was uploaded by the user “JAMESWT.”
File Name | 37-143-129-165.ps1 |
File Size | 10.18 KB |
Signed | Not Signed |
MD5 Hash | b5e19d28e81e69edb9b2fbee7c4d57ad |
SHA-256 Hash | 181fe99c16fa6cc87a3161bc08a9e2dbd17531c7d713b09d8567c1b3debe121f |
Command and Scripting Interpreter
PowerShell
File and Directory Discovery
System Information Discovery
C2- Command and Control
Non-Standard Port
The first part of the script defines parameters for establishing an anonymous network connection through a proxy to a server on the Tor network. It sets up the server’s .onion address and port, along with the proxy’s IP address and port, typically used for routing traffic through Tor’s SOCKS proxy. This setup is intended for securely and anonymously connecting to a hidden service on the Tor network.
The below script defines a SocksProxy class in C# to establish a connection to a remote server via a SOCKS5 proxy, creating a socket to connect to the proxy server which performs a SOCKS5 handshake to authenticate, sending a connection request to the destination host. The proxy server’s response is validated to ensure the connection was successful.
If any step fails, an exception is thrown. If successful, the connected socket is returned, enabling further communication with the destination host through the proxy, often used for anonymizing traffic or routing through specific network paths.
Attackers use static methods of customized .NET class that handle the connection to the remote server(c2) via the proxy.
The Cap-Sc function captures the entire screen, saves the screenshot as a PNG file in the temporary directory, and returns the file path. It uses System.Windows.Forms to get screen dimensions and System.Drawing to handle image creation and manipulation.
It also creates a unique file path for the screenshot, combining the system’s temporary directory path with a randomly generated file name (appending the .png extension).
This function can be useful for tasks that require capturing and processing screenshots programmatically.
To securely transmit or store data in a format compatible with text-based protocols – ensuring the integrity of the data during transport – the developer Involves two functions, Encode-Data and Decode-Data in the script, to handle the conversion between plain text and Base64-encoded text. Encode-Data converts a string into a Base64-encoded format using Unicode encoding, making it safe for transmission or storage. Decode-Data reverses this process by decoding a Base64 string back into its original text form.
The Execute-CommandInMemory function in PowerShell takes an encoded command string, decodes it using the Decode-Data function, and executes the command using Invoke-Expression. This separation of decoding and execution allows for flexibility in handling commands that are received at runtime.
The functions are used to send the command in an encoded format which is sent from a remote server and must be executed locally at the Victim environment, (with the output being captured and returned for further use).
The Get-SystemInfo function gathers system details, including the OS version, hostname, username, and the first non-local IPv4 address. This information is stored in a hash table and then converted to a compressed JSON string for easy transmission or storage.
It also sets up two global variables related to keylogging i.e. $global:keylogger_active which indicates whether a keylogger is currently active, initializing to false and $global:captured_keys which holds captured keystrokes (initialized as an empty string).
This Start-Keylogger function initializes by setting global variables to indicate its active state and resetting the captured keystrokes.
It uses embedded C# code to interface with the Windows API through User32.dll, defining functions to monitor and capture keyboard input.
These API functions (GetAsyncKeyState, GetKeyboardState, MapVirtualKey, ToUnicode) are essential for detecting keypresses, converting them to characters, and ultimately logging the captured input: this setup is the foundation for continuous recording of keystrokes.
The Stop-Keylogger function halts a keylogging job by setting a global flag to indicate the keylogger is inactive. It then stops the job using Stop-Job and removes it from the job queue with Remove-Job, ensuring proper cleanup and deactivation.
The Get-KeylogData function is designed to read and return the contents of a keylogging file stored in the system’s temporary directory. If the file exists, the function reads its contents, deletes the file to clear the log, and returns the captured data.
If the file does not exist, the function returns a message indicating that data is not available.
This function periodically dumps its captured keystrokes to a file, and the script needs to retrieve and process this data for transmission.
The Establish-Connection function sets up a network connection through a specified proxy, taking parameters for the destination IP, port, proxy IP, and proxy port.
Variable $keylogger_job is set to $null where it enters an infinite loop to establish a network connection through a SOCKS proxy. It creates a socket connection, sets up network streaming for reading and writing, and sends system information to the connected client using the Get-SystemInfo function. This process is part of the script that maintains a continuous connection and facilitates communication.
The while ($true) loop processes commands received from a Command-and-Control server.
Command Handling:
The loop continues indefinitely, handling various commands to manage system functions and interactions.
In the catch block, if a connection error occurs, the script logs the error, stops the keylogger (if active), and waits 30 seconds before retrying the connection. The final block ensures that open resources – such as the reader, writer, and socket – are closed properly to avoid resource leaks and to maintain system stability. This structure ensures graceful error handling and resource management during the connection process.
While this loop continuously attempts to establish a connection using the specified parameters for the server and proxy, if an error occurs during the connection attempt, it logs the error and waits for 60 seconds before retrying, ensuring persistent connection attempts while handling errors and allowing time for recovery.
The Start-Keylogger function sets up the keylogger to run in the background. It first defines a C# class to access Windows API functions for capturing keyboard input, then it creates a PowerShell job that runs continuously, checking for key presses every 40 milliseconds. If a key is pressed, it retrieves the keystroke and appends it to a file in the temporary directory. The job also ensures that when it stops, it logs a message indicating that it has been stopped. Finally, the function returns the job object for further management. This approach allows for continuous and asynchronous keylogging while managing the data capture and cleanup process.
The script contains comments in French, such as “# Envoyer les informations système” (Send system information); “# Implémentez la logique de persistance ici si nécessaire” (Implement persistence logic here if needed); “# Attendre avant de tenter une reconnexion” (Wait before attempting reconnection) and “# Attendre avant de redémarrer complètement” (Wait before restarting completely) These tags imply that the developer is likely a French speaker.
We identified that the attacker is utilizing a cloud server as a proxy “37[.]143[.]129[.]165,” which is hosted by Oneprovider[.]com and located in Helsinki, Finland. This server acts as an intermediary in the attack chain, helping to obscure the attacker’s true location. Additionally, the attacker is employing an Onion server, “opioem3zmp3bgx3qjqkh6vimkdoerrwh3uhawklm5ndv5e7k3t4edbqd[.]onion,” to facilitate data exfiltration and command-and-control (C2) communications, leveraging the anonymity provided by the Tor network to avoid detection and traceability.
This report provides the detailed identification and analysis of a new keylogger that operates via a PowerShell script, posing significant risks due to its capability to stealthily capture sensitive information. The keylogger employs advanced techniques such as system information discovery, file and directory discovery, and data exfiltration through non-standard ports, utilizing a proxy server and an Onion server for anonymized command-and-control (C2) communications. The attacker is likely a French speaker, as suggested by comments in the script. This report highlights the need for vigilant monitoring and robust security measures to counter such sophisticated threats.
Strategic Recommendations:
Management Recommendations:
Tactical Recommendations:
MITRE Mapping
MITRE Attack Framework | ||
Tactics | ID | Techniques/Sub-Techniques |
Execution | T1059 | Command and Scripting Interpreter |
Execution | T1059.001 | Command and Scripting Interpreter: PowerShell |
Discovery | T1083 | File and Directory Discovery |
Discovery | T1082 | System Information Discovery |
Command and Control | T1571 | Non-Standard Port |
No | Indicator (SHA-256) | Remarks |
1 | 181fe99c16fa6cc87a3161bc08a9e2dbd17531c7d713b09d8567c1b3debe121f | 37-143-129-165.ps1 |
2 | 37[.]143[.]129[.]165 | Proxy Server IP |
3 | opioem3zmp3bgx3qjqkh6vimkdoerrwh3uhawklm5ndv5e7k3t4edbqd[.]onion | Server Address/C2 |