2186855f4b59b08be5b16aaf91243cf34d8b9d3b7fe91c4746097e6034d0e70fconnectwise: 2186855f — May 2025 ClickOnce bootstrapper twin, same compile-second as 050e5825
Executive Summary
Signed ConnectWise ClickOnce bootstrapper (PE32 GUI, MSVC 14.40) compiled May 20 2025 19:01:23 UTC — identical second to sibling 050e5825. Extracts its own Authenticode signature, installs the publisher certificate into TrustedPublisher, then invokes dfshim!ShOpenVerbApplicationW to silently deploy a remote .application manifest. The C2 URL lives in the certificate's SPC_SP_OPUS_INFO (OID 1.3.6.1.4.1.311.4.1.1) attribute, not in PE strings. Post-deployment certificate cleanup via CertDeleteCertificateFromStore. Static-only (CAPE skipped — no Windows guest).
What It Is
| Field | Value |
|---|---|
| SHA-256 | 2186855f4b59b08be5b16aaf91243cf34d8b9d3b7fe91c4746097e6034d0e70f |
| File type | PE32 executable (GUI) Intel 80386, 5 sections ^[file.txt] |
| Size | 312,608 bytes (305 KB) |
| Compile timestamp | Tue May 20 19:01:23 2025 UTC (0x682CD183) ^[exiftool.json] |
| Linker | MSVC 14.40 (VS 2022) ^[exiftool.json] |
| PDB | C:\builds\cc\cwcontrol\Product\ClickOnceRunner\Release\ClickOnceRunner.pdb ^[rabin2-info.txt] |
| Signing | Valid Authenticode by ConnectWise, LLC, DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1 chain ^[strings.txt:701], DigiCert Timestamp 2024 counter-signature ^[strings.txt:719] |
| Certificate signing time | 2025-05-20 19:14:19Z ^[strings.txt:713] — ~14 minutes after compile, confirming automated CI/CD signing pipeline |
| Anti-analysis | None observed (no packing, no obfuscation, no debug checks, no VM detection) |
| Dynamic analysis | Skipped — no CAPE Windows guest available ^[dynamic-analysis.md] |
This is a ClickOnce bootstrapper Variant B per the connectwise entity page: native C/C++ (no .NET runtime), minimal import surface, no embedded MSI or assemblies. The evasion is entirely the valid signature and legitimate tool chain.
How It Works
The entry point (0x401532) is standard MSVC CRT initialization. main() at 0x401000 performs the certificate-trust bootstrap in four phases:
- Open certificate store —
CertOpenSystemStoreA("TrustedPublisher")^[r2:main] - Extract self-signature —
CryptQueryObjecton the module's own file path (GetModuleFileNameW), thenCryptMsgGetParamto pull embedded certificates from the PKCS#7 signature ^[r2:main] - Trust bootstrap —
CertCreateCertificateContext→CertAddCertificateContextToStoreintoTrustedPublisher, installing the ConnectWise publisher cert so the subsequent ClickOnce deployment is trusted ^[r2:main] - Silent ClickOnce launch —
LoadLibraryA("dfshim")→GetProcAddress("ShOpenVerbApplicationW"), then invoke with the remote.applicationURL extracted from the certificate'sSPC_SP_OPUS_INFOattribute (OID1.3.6.1.4.1.311.4.1.1) ^[r2:main]
Post-launch, the binary iterates the certificate array and calls CertDeleteCertificateFromStore on each context — a touch-and-go cleanup that removes the evidence from the store ^[r2:main].
The C2 / ClickOnce manifest URL is not present in PE strings; it is embedded inside the Authenticode signature's 1.3.6.1.4.1.311.4.1.1 attribute. Static extraction would require parsing the PKCS#7/CMS structure from the IMAGE_DIRECTORY_ENTRY_SECURITY blob (raw offset 0x49808, size 0x2D20) ^[binwalk.txt].
Decompiled Behavior
Ghidra decompilation of main() (0x401000) confirms the exact flow described above. Notable API call sites:
CryptQueryObject(1, module_path, 0x400, 2, ...)— queries the PE file itself for embedded signature objects ^[r2:main]CryptMsgGetParam(hCryptMsg, CMSG_CERT_PARAM(12), 0, ...)— extracts signer certificates ^[r2:main]CryptMsgGetParam(hCryptMsg, CMSG_INNER_CONTENT_TYPE_PARAM(10), ...)— gets inner content type ^[r2:main]CertFindAttribute("1.3.6.1.4.1.311.4.1.1", ...)— locates SPC_SP_OPUS_INFO attribute ^[r2:main]LoadLibraryA("dfshim")+GetProcAddress("ShOpenVerbApplicationW")— resolves ClickOnce launcher ^[r2:main]CertDeleteCertificateFromStore(...)in a loop — certificate cleanup ^[r2:main]
No network APIs (WinInet, WinHTTP, WS2_32) are imported. All HTTP is delegated to dfshim.dll (the Windows ClickOnce runtime) after the trust bootstrap.
C2 Infrastructure
No hardcoded IP/domain in PE strings. The ClickOnce .application manifest URL is embedded in the Authenticode SPC_SP_OPUS_INFO attribute at offset 0x49808 (PKCS#7 blob). Cross-variant IP reuse pattern from the connectwise cluster:
050e5825(May 2025 twin, same compile second) → C2 IP84.54.33.84viahttps://604e1cc7(Apr 2025 twin) → reused IP45.83.31.225from Nov 2022 MSI-bundle variant8c8e60af
This sample likely targets a different IP/URL in the same infrastructure pool. The certificate signing time (~14 min post-compile) suggests the builder compiles, then signs with the ConnectWise certificate in an automated pipeline that stamps the C2-specific manifest URL into the signature attribute.
Interesting Tidbits
- Identical compile-second twin:
050e5825shares the exact same compile timestamp to the second (May 20 19:01:23 2025 UTC) and the same PDB path. The only deltas are SHA256 and (presumably) the C2 URL in the Authenticode attribute. This confirms a CI pipeline that stamps per-sample C2 URLs during signing while keeping the compiled binary identical. ^[rabin2-info.txt] ^[entities/connectwise.md] - No network imports: The binary never opens a socket itself. All C2 communication is delegated to the legitimate Windows ClickOnce runtime (
dfshim.dll), which fetches the.applicationmanifest and subsequent.deployfiles over HTTP(S). This is a deliberate design to minimize malicious API footprint. ^[pefile.txt] - Cleanup import added:
CertDeleteCertificateFromStoreappears in the import table alongside the add/open/query functions. Earlier Nov 2022 MSI-bundle variants (7145e8) lacked this cleanup step. The Apr/May 2025 bootstrapper twins (604e1cc7,050e5825,2186855f) all include it. ^[pefile.txt] - Manifest resource only contains UAC elevation: The
.rsrcsection holds a singleRT_MANIFEST(ID 0x18) withasInvokerexecution level — no embedded ClickOnce manifest, no config, no icon. All deployment metadata is in the Authenticode signature. ^[pefile.txt] - Tiny binary for a signed PE: 305 KB with only KERNEL32 + CRYPT32 imports. The bulk of the file (~11 KB from
0x47260) is XML manifest + PKCS#7 signature blob. The actual code is compact. ^[file.txt]
How To Mess With It (Homelab Replication)
Toolchain: Visual Studio 2022 (MSVC 14.40), Windows SDK, cl.exe /O2 /DYNAMICBASE /NXCOMPAT
Source skeleton (simplified, for educational replication):
#include <windows.h>
#include <wincrypt.h>
#pragma comment(lib, "crypt32.lib")
int main() {
WCHAR path[MAX_PATH];
GetModuleFileNameW(NULL, path, MAX_PATH);
HCERTSTORE store = CertOpenSystemStoreA(0, "TrustedPublisher");
DWORD dwEncoding, dwContentType, dwFormatType;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
CryptQueryObject(CERT_QUERY_OBJECT_FILE, path,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_ALL, 0, &dwEncoding, &dwContentType,
&dwFormatType, &hStore, &hMsg, NULL);
// Extract certs, add to TrustedPublisher, then invoke dfshim
// Requires an Authenticode-signed PE with SPC_SP_OPUS_INFO attribute
return 0;
}
Verification: A successful reproducer should have only KERNEL32.dll and CRYPT32.dll imports, a valid Authenticode signature with OID 1.3.6.1.4.1.311.4.1.1, and invoke ShOpenVerbApplicationW after trust bootstrap.
Deployable Signatures
YARA rule
rule ConnectWise_ClickOnce_Bootstrapper {
meta:
author = "PacketPursuit"
description = "ConnectWise ScreenConnect ClickOnce bootstrapper — certificate trust bootstrap variant"
reference = "raw/analyses/2186855f4b59b08be5b16aaf91243cf34d8b9d3b7fe91c4746097e6034d0e70f"
date = "2025-05-20"
strings:
$pdb = "C:\\builds\\cc\\cwcontrol\\Product\\ClickOnceRunner\\Release\\ClickOnceRunner.pdb" ascii wide
$tp = "TrustedPublisher" ascii wide
$dfshim = "dfshim" ascii wide
$shopen = "ShOpenVerbApplicationW" ascii wide
$oid = "1.3.6.1.4.1.311.4.1.1" ascii wide
$cw = "Connectwise, LLC" ascii wide
condition:
uint16(0) == 0x5A4D and
pe.number_of_sections == 5 and
pe.imports("KERNEL32.dll") and
pe.imports("CRYPT32.dll") and
pe.imports("CRYPT32.dll", "CertOpenSystemStoreA") and
pe.imports("CRYPT32.dll", "CertAddCertificateContextToStore") and
pe.imports("CRYPT32.dll", "CertDeleteCertificateFromStore") and
3 of ($pdb, $tp, $dfshim, $shopen, $oid, $cw)
}
Behavioral hunt query (EQL)
sequence by process.entity_id
[library where dll.name == "crypt32.dll" and
process.name : "*.exe" and
process.hash.sha256 : "2186855f*"]
[library where dll.name == "dfshim.dll"]
IOC list
| Type | Value | Notes |
|---|---|---|
| SHA-256 | 2186855f4b59b08be5b16aaf91243cf34d8b9d3b7fe91c4746097e6034d0e70f |
This sample |
| Compile timestamp | 2025-05-20 19:01:23 UTC |
Shared with twin 050e5825 |
| PDB path | C:\builds\cc\cwcontrol\Product\ClickOnceRunner\Release\ClickOnceRunner.pdb |
All Variant B siblings |
| Certificate CN | ConnectWise, LLC |
DigiCert G4 Code Signing chain |
| Certificate signing time | 2025-05-20 19:14:19Z |
~14 min post-compile |
| OID | 1.3.6.1.4.1.311.4.1.1 |
SPC_SP_OPUS_INFO in Authenticode attribute |
| DLL | dfshim.dll |
ClickOnce runtime loaded at execution |
| API | ShOpenVerbApplicationW |
ClickOnce silent launch |
Behavioral fingerprint
This binary is a minimal 305 KB signed PE with only KERNEL32 and CRYPT32 imports. On execution, it reads its own Authenticode signature via CryptQueryObject, extracts the signer certificates, adds them to the TrustedPublisher store via CertAddCertificateContextToStore, loads dfshim.dll, resolves ShOpenVerbApplicationW, and invokes it with the remote ClickOnce manifest URL encoded in the certificate's SPC_SP_OPUS_INFO attribute. After invocation, it deletes the certificates from the store via CertDeleteCertificateFromStore. No direct network APIs are used; all HTTP traffic is generated by the legitimate Windows ClickOnce runtime.
Detection Signatures
| ATT&CK Technique | Evidence | Static Confidence |
|---|---|---|
| T1553.004 — Install Root Certificate | CertOpenSystemStoreA("TrustedPublisher") + CertAddCertificateContextToStore |
High |
| T1219 — Remote Access Software | ClickOnce deployment of ScreenConnect client via dfshim!ShOpenVerbApplicationW |
High (family inference) |
| T1071.001 — Application Layer Protocol: Web Protocols | HTTP(S) delegated to ClickOnce runtime for .application manifest fetch |
Medium (delegated, no direct evidence) |
| T1204.002 — Malicious File | Signed PE executing certificate trust bootstrap | High |
| T1078 — Valid Accounts | Abuse of legitimate ConnectWise Authenticode certificate | High |
References
- connectwise — Entity page for the cluster
- clickonce-certificate-trust-bootstrap — Technique page for the certificate → ClickOnce chain
- legitimate-remote-access-tool-abuse — Cross-family concept
Provenance
- Static analysis:
file,exiftool,pefile,strings,radare2(decompilation),binwalk - File:
<sample 2186855f4b59.bin> - All tool outputs preserved in
raw/analyses/2186855f4b59b08be5b16aaf91243cf34d8b9d3b7fe91c4746097e6034d0e70f/ - No dynamic execution (CAPE skipped — no Windows guest)