




















V1.exe, V2.exe, etc.) were discovered on VirusTotal, some using free dynamic DNS infrastructure, indicating iterative developmentDuring a recent investigation, Elastic Security Labs identified malware deployed on a South Asian financial institution’s infrastructure. The victim environment had only SIEM-level visibility enabled, which limited post-exploitation telemetry. The intrusion involved two custom binaries: a backdoor named paint.exe and a keylogger masquerading as libcurl.dll.
BRUSHWORM functions as the primary implant, responsible for installation, persistence, command-and-control communication, downloading additional modular payloads, spreading via removable media, and stealing files with targeted extensions. BRUSHLOGGER supplements this by capturing system-wide keystrokes via a simple Windows keyboard hook and logging the active window context for each keystroke session.
Neither binary employs meaningful code obfuscation, packing, or advanced anti-analysis techniques. The overall quality of the code is low — for example, the backdoor writes its decrypted configuration to disk in cleartext before encrypting and saving a second copy, then deletes the cleartext file. Given the absence of a kill switch, the use of free dynamic DNS servers in testing versions, and some coding mistakes, we assess with moderate confidence that the author is relatively inexperienced and may have leveraged AI code-generation tools during development without fully reviewing the output.
Through VirusTotal pivoting, we identified what appear to be earlier development and testing versions of the backdoor uploaded under filenames such as V1.exe, V2.exe, and V4.exe, with varying configurations.
The backdoor is the primary implant responsible for establishing persistence, communicating with the C2 server, downloading modular payloads, spreading to removable media, and exfiltrating files.
The malware begins execution with a series of environment checks designed to detect analysis environments, though the techniques are straightforward and lack sophistication.
Screen resolution check: If the display resolution is less than 1024×768 pixels, execution terminates immediately. This is a common sandbox detection technique.
Username and computer name check: The malware checks whether the machine's username or the computer name is “sandbox”. If either condition matches, it terminates. These checks target the default name commonly used in analysis sandboxes.
Hypervisor detection: Using the CPUID instruction, the malware queries the hypervisor vendor string and compares it against the following known virtualization platforms:
| Hypervisor Vendor String | Platform |
|---|---|
VMWAREVMWARE | VMware |
KVMKVMKVM | KVM |
XENVMMXENVMM | Xen |
PRL HYPERV | Parallels |
TCGTCGTCGTCG | QEMU (TCG) |
ACRNACRNACRN | ACRN |
MICROSOFT HV | Hyper-V |
If a hypervisor is detected, the malware does not terminate — it merely sleeps for one second before continuing execution.
Mouse activity check: After the initial setup, the malware monitors mouse movement for 5 minutes. If the cursor does not move during this period, execution terminates. This acts as an additional sandbox evasion measure.
On first execution, the malware creates multiple hidden directories with hardcoded paths. These directories serve distinct roles throughout the malware's lifecycle:
| Directory | Purpose |
|---|---|
C:\ProgramData\Photoes\Pics\ | Main installation folder for the backdoor binary |
C:\Users\Public\Libraries\ | Storage for downloaded modules from the C2 server (e.g., Recorder.dll) |
C:\Users\Public\AppData\Roaming\Microsoft\Vault\ | Storage of the encrypted configuration file (keyE.dat) |
C:\Users\Public\Systeminfo\ | Staging directory for stolen files |
C:\Users\Public\AppData\Roaming\NuGet\ | Tracks exfiltrated file paths with their SHA-256 hashes (hashconfig) |
The misspelling "Photoes" (instead of "Photos") is consistent across both the backdoor and keylogger components and appears to be an authentic mistake by the author to blend with the other user’s media directories.
The backdoor's configuration is stored as a JSON structure with field values encrypted using AES-CBC. The AES key is hardcoded in the binary, while the initialization vector (IV) is prepended to each encrypted field's data blob.
The decrypted configuration follows this structure:
{
"internetCheckDomain": "<...>",
"downloadDomain": "<...>",
"retryCount": 0
}
This configuration is not referenced anywhere in the malware's operational logic. The C2 server address that the backdoor actually communicates with is a separate C++ global string variable stored in cleartext(resources.dawnnewsisl[.]com/updtdll), which is passed directly to the function responsible for C2 communication and payload downloads.
The decrypted configuration fields (internetCheckDomain, downloadDomain, retryCount) go entirely unused in this build. This configuration is likely intended for a future version, a separate payload component, or was simply disabled in the deployed build, reinforcing the impression of a codebase under active, disorganized development.
The malware establishes persistence by creating a Windows scheduled task named MSGraphics through the COM Task Scheduler interface. The task is configured to execute the malware binary each time a user logs in, ensuring the backdoor survives system reboots.
The backdoor uses the WinHTTP library to issue a GET request to the C2 server at the URI /updtdll to download a DLL payload. The downloaded binary is written to C:\Users\Public\Libraries\ as Recorder.dll.
We were unable to recover the downloaded payload during our investigation, but the naming convention and execution method suggest it is a modular plugin — likely providing additional post-exploitation capabilities such as screen recording or data exfiltration.
The downloaded DLL is executed by creating a second scheduled task named MSRecorder that uses rundll32.exe to load and run it. This mirrors the same COM-based scheduled task creation method used for persistence.
The C2 server's SSL certificate is issued by Let's Encrypt.
Once BRUSHWORM detects that the host is already infected (by checking for the presence of the installation directory), its behavior diverges based on internet connectivity. The malware performs a connectivity check by attempting to reach www.google.com.
The malware spawns two threads targeting external storage devices:
Salary Slips.exeNotes.exeDocuments.exeImportant.exeDont Delete.exePresentation.exeEmails.exeAttachments.exe| Category | Extensions |
|---|---|
| Documents & Word Processing | .doc, .docx, .dot, .dotx, .wps, .wpd, .wp, .rtf, .txt, .odt, .ott, .pages |
| Spreadsheets | .xls, .xlsx, .xlsm, .xlt, .xltx, .xlw, .ods, .ots, .csv, .tsv, .dbf, .wk1, .wk3, .wk4, .123 |
| Presentations | .ppt, .pptx, .pot, .potx, .pps, .ppsx, .odp, .otp, .key, .sxi |
| Portable & Layout | .pdf, .xps, .epub, .mobi, .ps, .prn, .tex, .latex, .pub, .p65, .fm |
| Archives & Disk Images | .zip, .rar, .7z, .tar, .gz, .bz2, .xz, .iso, .cab, .arj, .lzh, .lha, .tgz, .tbz, .txz |
| Email & Notes | .pst, .ost, .msg, .eml, .emlx, .mbox, .mbx, .maildir, .one |
| Code & Data | .py, .md, .xml, .json |
Stolen files are staged in the C:\Users\Public\Systeminfo\ directory. The malware also maintains a tracking file (hashconfig) at C:\Users\Public\AppData\Roaming\NuGet\ that records each exfiltrated file's path alongside its SHA-256 hash, likely to avoid re-exfiltrating the same files on subsequent runs.
If the internet connectivity check fails, the malware still infects removable drives with the same lure-named copies. However, in this scenario, it additionally copies stolen files and files from the user's profile directory (matching the same extension list) to the removable drives. This behavior serves as a data exfiltration bridge for environments with restricted or air-gapped network access — using USB drives to physically carry stolen data off the network.
The second component is a 32-bit Windows DLL (4f1ea5ed6035e7c951e688bd9c2ec47a1e184a81e9ae783d4a0979501a1985cf) designed for DLL side-loading. It masquerades as libcurl.dll by exporting seven standard curl_easy_* API functions, all of which are empty stubs pointing to a single RET instruction. The malicious functionality executes entirely from the DllMain entry point on DLL_PROCESS_ATTACH.
At startup, the keylogger decodes a mutex name from a Base64-encoded string: “Windows-Updates-KB852654856”. The mutex name mimics a Windows Update knowledge base identifier. If CreateMutexA returns ERROR_ALREADY_EXISTS, the process terminates immediately to enforce single-instance execution.
BRUSHLOGGER retrieves the current Windows username via GetUserNameA, computes its MD5 hash using the Windows CryptoAPI, and constructs the final log file path:
C:\programdata\Photoes\<username>_<MD5(username)>.trn
The log file is initially created with CreateFileA using CREATE_NEW, then reopened with FILE_APPEND_DATA access for append-mode writing throughout the session.
After file setup, the keylogger installs a low-level keyboard hook:
SetWindowsHookExA(WH_KEYBOARD_LL, keyboard_hook_callback, NULL, 0);
The WH_KEYBOARD_LL hook type captures keyboard input system-wide across all threads and processes. The hook procedure runs in the context of the installing thread, requiring a standard Windows message pump (GetMessageA / TranslateMessage / DispatchMessageA) to keep the hook alive.
The core capture logic resides in the hook callback, which processes every keyboard event in the system.
For each keystroke event, the callback:
GetForegroundWindowVirtualAlloc for the window titleGetLocalTime, formatted as DD-MM-YYYY HH:MMGetWindowTextAWhen the foreground window changes, a context marker is appended to the keystroke buffer:
\n<timestamp> <window title>\n
Keystroke encoding: The callback processes WM_KEYDOWN, WM_SYSKEYDOWN, WM_KEYUP, and WM_SYSKEYUP messages. Each keystroke is logged as a two-digit hexadecimal virtual key.
The flush routine copies the keystroke buffer to a local stack buffer, XOR-encrypts each byte with a hardcoded single-byte key 0x43, and writes the result to the log file via WriteFile. After a successful write, the global buffer is cleared.
The XOR key 0x43 is trivially reversible — the encryption serves only as basic obfuscation rather than meaningful cryptographic protection.
Despite their low sophistication and multiple implementation flaws, these two binaries deliver a functional collection platform that combines modular payload loading, USB worm propagation, broad file theft with air-gap bridging, and persistent keystroke capture via DLL side-loading. The iterative testing versions and active C2 infrastructure suggest an actor still refining their toolset. Elastic Security Labs will continue monitoring this activity cluster.
Elastic uses the MITRE ATT&CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
Techniques represent how an adversary achieves a tactical goal by performing an action.
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the BRUSHWORM and BRUSHLOGGER:
rule Windows_Trojan_BrushLogger_304ee146 {
meta:
author = "Elastic Security"
os = "Windows"
arch = "x86"
category_type = "Trojan"
family = "BrushLogger"
threat_name = "Windows.Trojan.BrushLogger"
reference_sample = "4f1ea5ed6035e7c951e688bd9c2ec47a1e184a81e9ae783d4a0979501a1985cf"
strings:
$a = "%02d-%02d-%d %02d:%02d " fullword
$b = { 81 ?? ?? A1 00 00 00 74 09 81 ?? ?? A0 00 00 00 75 09 6A 00 6A 10 E8 }
condition:
all of them
}
rule Windows_Trojan_BrushWorm_7c2098ef {
meta:
author = "Elastic Security"
os = "Windows"
arch = "x86"
category_type = "Trojan"
family = "BrushWorm"
threat_name = "Windows.Trojan.BrushWorm"
reference_sample = "89891aa3867c1a57512d77e8e248d4a35dd32e99dcda0344a633be402df4a9a7"
strings:
$a = "internetCheckDomain" wide fullword
$b = { B8 00 00 00 40 33 C9 0F A2 48 8D ?? ?? ?? 89 07 89 5F 04 89 4F 08 89 57 0C 45 33 C0 }
condition:
all of them
}
The following observables were discussed in this research.
| Observable | Type | Name | Reference |
|---|---|---|---|
89891aa3867c1a57512d77e8e248d4a35dd32e99dcda0344a633be402df4a9a7 | SHA-256 | paint.exe | BRUSHWORM |
4f1ea5ed6035e7c951e688bd9c2ec47a1e184a81e9ae783d4a0979501a1985cf | SHA-256 | libcurl.dll | BRUSHLOGGER |
resources.dawnnewsisl[.]com/updtdll | domain-name | C2 server |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。