Script host resolving a web service used for two-way C2
Matches a Sysmon DNS query where a scripting engine or signed-binary proxy — never a browser or a mail client — resolves a web service whose API supports both fetching an instruction and posting a result, which is AN0100's "suspicious process contacting common web service domains" leg. dns_query is chosen over the network-connection source the same analytic offers because every one of these services is fronted by shared CDN address space, so the destination IP identifies nothing, and because Sysmon EventID 22 attributes the query to the process that called the resolver while EventID 3 would only name whichever process owns the socket. The domain list is MITRE's DomainPattern knob populated here with bidirectional APIs only: read-only dead-drop endpoints such as pastebin and raw.githubusercontent are left out because a channel with no return path is a different sub-technique, and graph.microsoft.com is left out because the Graph PowerShell module makes it ordinary traffic for the very processes selected here. Two limits worth stating — the rule sees a name and nothing else, so it cannot tell a C2 poll from a legitimate API call, and it goes blind entirely against direct-to-IP callbacks, DNS-over-HTTPS, or a name already in the host resolver cache; Sysmon EventID 22 also needs DNS query logging switched on in the running configuration, which the common community configs filter hard. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0035, not hand-written and not tested by its author. Any lab result is on this rule's own page.Full descriptionShow less
The detection
The 3 SIEM queries below are previews produced by Siemphony’s own translator, not pySigma, and none has been executed against a real backend — review before you deploy.
detection.yml
title: Script host resolving a web service used for two-way C2id: 8f7d2596-cddf-4d66-855c-b4e87be57890status: experimentaldescription: | Matches a Sysmon DNS query where a scripting engine or signed-binary proxy — never a browser or a mail client — resolves a web service whose API supports both fetching an instruction and posting a result, which is AN0100's "suspicious process contacting common web service domains" leg. dns_query is chosen over the network-connection source the same analytic offers because every one of these services is fronted by shared CDN address space, so the destination IP identifies nothing, and because Sysmon EventID 22 attributes the query to the process that called the resolver while EventID 3 would only name whichever process owns the socket. The domain list is MITRE's DomainPattern knob populated here with bidirectional APIs only: read-only dead-drop endpoints such as pastebin and raw.githubusercontent are left out because a channel with no return path is a different sub-technique, and graph.microsoft.com is left out because the Graph PowerShell module makes it ordinary traffic for the very processes selected here. Two limits worth stating — the rule sees a name and nothing else, so it cannot tell a C2 poll from a legitimate API call, and it goes blind entirely against direct-to-IP callbacks, DNS-over-HTTPS, or a name already in the host resolver cache; Sysmon EventID 22 also needs DNS query logging switched on in the running configuration, which the common community configs filter hard. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0035, not hand-written and not tested by its author. Any lab result is on this rule's own page.references: - https://attack.mitre.org/techniques/T1102/002 - https://attack.mitre.org/detectionstrategies/DET0035author: Siemphony pipeline (machine-derived from MITRE ATT&CK v19.2)date: 2026-08-16tags: - attack.command-and-control - attack.t1102.002logsource: category: dns_query product: windowsdetection: selection_process: Image|endswith: - '\powershell.exe' - '\pwsh.exe' - '\wscript.exe' - '\cscript.exe' - '\mshta.exe' - '\rundll32.exe' - '\regsvr32.exe' - '\certutil.exe' - '\curl.exe' - '\python.exe' selection_webservice: QueryName|endswith: - 'api.telegram.org' - 'discord.com' - 'discordapp.com' - 'api.github.com' - 'gist.github.com' - 'slack.com' - 'api.trello.com' - 'api.dropboxapi.com' - 'content.dropboxapi.com' - 'api.notion.com' - 'api.imgur.com' - 'firebaseio.com' - 'api.twitter.com' condition: selection_process and selection_webservicefalsepositives: - "Developer and administrator PowerShell reaching api.github.com — module installs, release-asset downloads, gist reads and writes, and anything wrapping the GitHub REST API. On engineering estates this is the single largest source of hits and it is why the level is not higher; the practical suppression is the account and the host role, not the domain, since removing GitHub takes out one of the most-used bidirectional channels there is." - "Chat and ticketing notifications sent from scheduled scripts. A backup job posting its result to a Slack or Discord incoming webhook, or a monitoring script messaging a Telegram bot, produces a script host resolving exactly these names on a fixed schedule." - "Python-based line-of-business tooling and vendor agents that bundle their own interpreter and synchronise with Dropbox, Trello or Notion through the same public APIs, appearing as python.exe against a small set of servers." - "curl.exe is shipped in Windows and is the default way a build or provisioning script talks to any REST API, so a CI step publishing an artefact to a GitHub release or a Dropbox folder matches without anything unusual happening."level: mediumSplunk · SPL
Run this as a search.
index=* ((Image="*\\powershell.exe" OR Image="*\\pwsh.exe" OR Image="*\\wscript.exe" OR Image="*\\cscript.exe" OR Image="*\\mshta.exe" OR Image="*\\rundll32.exe" OR Image="*\\regsvr32.exe" OR Image="*\\certutil.exe" OR Image="*\\curl.exe" OR Image="*\\python.exe") AND (QueryName="*api.telegram.org" OR QueryName="*discord.com" OR QueryName="*discordapp.com" OR QueryName="*api.github.com" OR QueryName="*gist.github.com" OR QueryName="*slack.com" OR QueryName="*api.trello.com" OR QueryName="*api.dropboxapi.com" OR QueryName="*content.dropboxapi.com" OR QueryName="*api.notion.com" OR QueryName="*api.imgur.com" OR QueryName="*firebaseio.com" OR QueryName="*api.twitter.com"))Elastic · ES|QL
Run this as a search.
FROM logs-*| WHERE ((TO_LOWER(process.executable) LIKE "*\\\\powershell.exe" OR TO_LOWER(process.executable) LIKE "*\\\\pwsh.exe" OR TO_LOWER(process.executable) LIKE "*\\\\wscript.exe" OR TO_LOWER(process.executable) LIKE "*\\\\cscript.exe" OR TO_LOWER(process.executable) LIKE "*\\\\mshta.exe" OR TO_LOWER(process.executable) LIKE "*\\\\rundll32.exe" OR TO_LOWER(process.executable) LIKE "*\\\\regsvr32.exe" OR TO_LOWER(process.executable) LIKE "*\\\\certutil.exe" OR TO_LOWER(process.executable) LIKE "*\\\\curl.exe" OR TO_LOWER(process.executable) LIKE "*\\\\python.exe") AND (TO_LOWER(dns.question.name) LIKE "*api.telegram.org" OR TO_LOWER(dns.question.name) LIKE "*discord.com" OR TO_LOWER(dns.question.name) LIKE "*discordapp.com" OR TO_LOWER(dns.question.name) LIKE "*api.github.com" OR TO_LOWER(dns.question.name) LIKE "*gist.github.com" OR TO_LOWER(dns.question.name) LIKE "*slack.com" OR TO_LOWER(dns.question.name) LIKE "*api.trello.com" OR TO_LOWER(dns.question.name) LIKE "*api.dropboxapi.com" OR TO_LOWER(dns.question.name) LIKE "*content.dropboxapi.com" OR TO_LOWER(dns.question.name) LIKE "*api.notion.com" OR TO_LOWER(dns.question.name) LIKE "*api.imgur.com" OR TO_LOWER(dns.question.name) LIKE "*firebaseio.com" OR TO_LOWER(dns.question.name) LIKE "*api.twitter.com"))
Wazuh · XML rule
Deploy to your manager — this is a rule, not a search.
<group name="sigma,windows,dns_query,"> <!-- Rule ids must be unique on your manager; 100000+ is the user range. --> <rule id="100000" level="7"> <!-- Set <if_sid> to the decoder/base rule for windows so this only evaluates relevant events. --> <field name="Image" type="pcre2">(?i)(\\powershell\.exe$|\\pwsh\.exe$|\\wscript\.exe$|\\cscript\.exe$|\\mshta\.exe$|\\rundll32\.exe$|\\regsvr32\.exe$|\\certutil\.exe$|\\curl\.exe$|\\python\.exe$)</field> <field name="QueryName" type="pcre2">(?i)(api\.telegram\.org$|discord\.com$|discordapp\.com$|api\.github\.com$|gist\.github\.com$|slack\.com$|api\.trello\.com$|api\.dropboxapi\.com$|content\.dropboxapi\.com$|api\.notion\.com$|api\.imgur\.com$|firebaseio\.com$|api\.twitter\.com$)</field> <description>Script host resolving a web service used for two-way C2</description> <mitre> <id>T1102.002</id> </mitre> </rule></group>
Sentinel · KQL
Run this as a search.
Sentinel cannot express this construct. No Sentinel table is modelled for this logsource ({"category":"dns_query","product":"windows"}), so there is nothing honest to query. Pick a logsource this translator maps, or write the KQL by hand. The Sigma source is on the first tab, unchanged.
Verdicts · reactions · comments
Community
Verdicts from engineers who actually deployed it, and the conversation around it.
Nobody has run this in a real environment and said what happened.
Verdicts from engineers who deployed it
0 castNo verdicts reported yet. The first one is worth more than the tenth — say what you ran it against.
Log in to report a verdict.
Log in to join the discussion.
No comments yet. Someone who deploys this will have something to say about it.