- Even if we pretend downloading/installing CW (via xxx.top, xxx.help and so on) does not work, a scammer might use another remote tool and then they will still try to install CW while watching our screen.
- I wrote a python script that you can run in the background when you fire up your VM to block the execution of the CW installers. Bare with me, it’s the first time I wrote a script like that.
Script Summary: ConnectWise Detection and Blocking Script
This script is designed to monitor the user’s Downloads folder for executable files (.exe) and automatically verify their digital signatures using the signtool. If it detects a file issued by ConnectWise, LLC (I tried a couple of support.client.exe files and they all have it, independent of the file name), the script will block its execution by modifying file permissions.
Key Features:
- Continuously scans the Downloads folder every 10 seconds (you can change the folder if you want or the interval if it slows down your VM).
- Verifies executable files for the ConnectWise, LLC signature using signtool.
- Blocks execution of identified malicious files.
- Logs activities for review and troubleshooting.
Required Libraries:
This script relies on the following libraries (pip install them if they give you errors, I had all of them installed):
os
: Standard library for operating system interactions.logging
: Standard library for logging events.subprocess
: Standard library to run external commands.
You will need to install signtool separately for the script to work. It is included with the Windows SDK. To install it:
- Download the Windows SDK from the official Microsoft website.
- During installation, make sure to select the option to install the Windows App Certification Kit, which includes signtool. (the installation is pretty big, maybe you don’t need all I just installed all of them)
Starting / stopping the script:
- Make sure to start the script with admin rights.
- When you start the script it will disappear from your screen (but still run in the background).
- If you want to stop the script hit ESC (you can see if it stopped in the log file. The log file has the same name as your script).
File Permissions:
Files detected as ConnectWise-related will have their execution blocked [and you + the scammer will see a warning which you can’t bypass!], but this may lead to complications when attempting to delete these files. To delete blocked files, follow this workaround (or reset your VM to an older Snapshot):
- Right-click the blocked file and select Properties.
- Navigate to the Security tab.
- Click Advanced.
- Select Everyone and click Edit.
- Check the Allow box next to Full control and apply the changes.
After adjusting the permissions, you should be able to delete the files as needed.
Notes:
- I only tested it in my VMware Win10 machine with a couple of support.client.exe CW installation files you get from the .top/.help sites. If you find any other files and they are not detected/blocked please let me know.
- Review the log file created by the script for details on detected files and actions taken.
If you have any ideas on how to change/improve it, please let me know.
Here’s the current version of the script:
import os
import logging
import subprocess
import time
import ctypes
import threading
# Setup logging
script_name = os.path.splitext(os.path.basename(__file__))[0]
log_filename = f'{script_name}.log'
logging.basicConfig(filename=log_filename, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Define the target directory to scan
TARGET_DIRECTORY = os.path.expanduser(r"~\Downloads") # Use Downloads folder
# Variable to control the scanning loop
running = True
def extract_signature_info(filepath):
"""Extract and log specific issuer information from the given executable file using signtool."""
try:
logging.info(f"Verifying file: {filepath}") # Log the file being verified
# Call signtool to verify the digital signature
result = subprocess.run(
['signtool', 'verify', '/pa', '/v', filepath],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
if result.returncode == 0:
# Signtool succeeded, parse the output to find the issuer name
output_lines = result.stdout.splitlines()
issuer_name = None
for i, line in enumerate(output_lines):
if 'Issued to:' in line:
if 'Connectwise, LLC' in line:
issuer_name = line.split(':', 1)[1].strip()
logging.info(f"Relevant issuer found - File: {filepath} - Issuer: {issuer_name}")
block_execution(filepath)
break
if 'Issued to:' in line and "Connectwise, LLC" in output_lines[i + 3]:
issuer_name = output_lines[i + 3].strip()
logging.info(f"Relevant issuer found - File: {filepath} - Issuer: {issuer_name}")
block_execution(filepath)
break
if issuer_name is None:
logging.info(f"File: {filepath} - No relevant issuer information found.")
else:
logging.error(f"File: {filepath} - Signature verification failed. Error: {result.stderr.strip()}")
except Exception as e:
logging.error(f"Failed to extract information for {filepath}: {e}")
def block_execution(filepath):
"""Block execution of the file by changing permissions to deny read and execute."""
try:
result = subprocess.run(
['icacls', filepath, '/deny', 'Everyone:RX'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
if result.returncode == 0:
logging.info(f"Execution successfully blocked for {filepath}")
else:
logging.warning(f"Failed to block execution for {filepath}. Error: {result.stderr.strip()}")
except Exception as e:
logging.error(f"Failed to block execution for {filepath}: {e}")
def scan_directory():
"""Scan the specified directory for executable files and extract digital signature information."""
scanned_files = set() # Keep track of already scanned files
while running:
for root, _, files in os.walk(TARGET_DIRECTORY):
for file in files:
if file.lower().endswith(".exe"): # Check for any .exe file
filepath = os.path.join(root, file)
if filepath not in scanned_files: # Check if the file has already been scanned
scanned_files.add(filepath)
extract_signature_info(filepath)
logging.info(f"New file detected: {filepath}") # Log if a new file is found
time.sleep(10) # Wait for 10 seconds before scanning again
def hide_console():
"""Hide the console window."""
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 0)
def on_exit():
"""Stop the script gracefully."""
global running
running = False
logging.info("Stopping the script...")
if __name__ == "__main__":
# Hide the console window
hide_console()
# Start the scanning thread
scanning_thread = threading.Thread(target=scan_directory, daemon=True)
scanning_thread.start()
# Allow the user to stop the script using the ESC key
print("Press ESC to stop the script.")
while running:
if ctypes.windll.user32.GetAsyncKeyState(0x1B): # ESC key
on_exit()
break
scanning_thread.join() # Wait for the scanning thread to finish
logging.info("Script terminated.") # Log termination