Prologue
This post leans a bit more into my CTI discipline and I'm definitely putting my CTI hat on to write this. While it still carries cyber threat urgency, non-malware.. and it focuses more on emerged attack tooling that I felt was important to share soon.
I am now releasing custom ARTEX detection signatures pack to the public under TLP:CLEAR because active, autonomous threat campaigns leveraging this framework are currently escalating out of control, compressing traditional intrusion timelines from weeks into mere hours, and its intrusion can affect our lifeline.
The purpose is, to help defenders (from xCERT/xSIRT) to help or give idea how to counter these machine-speed identity compromises, API sweeps, and cloud persistence operations. The links for the rules can be found in following table and I have included the analytical playbook detailing the behavioral logic behind this ruleset.
All associated detection tools and signatures are open-sourced and available in the official MalwareMustDie GitHub repository and shared under TLP:CLEAR. In the signature folder there are also several python scripts I made for testing on those signatures. Read and check the following playbook before you decide to use or modify, and I hope this helps!
- Additionally, the tested OpenIOC can be found here => (here),
- The tools I build for testing offline can be seen here => (here),
- The test results conducted can be seen here => (here).
The details of the released detection pack can be found in the repository README.md here => (here).
Again, please read, assess and perform tests beforehand. You can decide what to do afterward, it's you to decide. Hope helps!
FYI, I have updated ARTEX detection signature pack into v1.1.0 after recent new dataset traffic tests, read here => (here), and minor updates v1.1.1 with more detection to indicators from recent incidents per Nov, 14 2026, here => (here).
I have also added an activity chronology of public ARTEX reporting (Oct–Nov 2026), compiled at a reviewing CERT's suggestion, as Appendix F, read here => (here).
PS1: I have also included an approach for detecting the released signatures in upper-layer network flows using Zeek, which you can find at the bottom of this post under the "Appendix D: (Additional) An idea on using Zeek to detect using releaaed signatures in upper layers networking data-set" part here => (here). This section demonstrates how to automate signature detection from network flows and combine it with behavioral detection across the upper network layers (L3/4). (Thanks to Aaron Kaplan for raising this question.)".
PS2: Readers reading this post might miss the main point. Because Artex is LLM-powered, the post suggests you to use LLMs to stop these behaviors in the future with playbooks built from IOC patterns.
- Many read my ARTEX signature release as "an IOC list". It isn't. The IOCs expire within a year by design. The real release is the workflow: how to turn the next ARTEX-style attack into detections as fast as the attacker moves.
- ARTEX is an LLM harness. Swap the model, prompts or infra and every IOC changes. What changes much less is how an agent behaves: machine-speed recon chains, ~1/s Password Sprays with rotating UAs, self-correcting API retries, systematic record enumeration.
- So the pack is behavior-first. Those patterns live in Sigma correlations, Sentinel KQL and Zeek SumStats on the upper network layers, not in packet filters. IPs are clearly labelled T3/T4 context for retro-hunting what already happened.
- "The Playbook" is the core of this sharing: to verify the source, classify how specific an indicator really is, assign a tier, route it to the right format, expire it. We applied it to four campaigns with an LLM assisting and humans gating every verification step. Next trail, same loop.
- That's the big picture: attackers use LLMs to compress weeks into hours. Defenders can use LLMs to compress "new report → tested detection" into hours too, as long as humans keep the verification gates. We must defend atacker's powered LLM/#AI with AI.
- The Zeek section shows how to carry the same behavioral logic into network sensors you already run. Playbook, rules and tests: [link]. Break them, send FP/TP reports. That's how this grows.
For any constructuve discussion I welcome you to do so here => (here).
Signatures Download Table
| Format | Takes |
|---|---|
| Sigma | Web/WAF strings and paths, identity events, Linux process/file events, Class F sequences (correlation rules) |
| Sentinel KQL | Entra/M365/Azure/AWS behaviors, app IDs, IP watchlists, retry-timing logic, SOAR hooks |
| Suricata 7 | HTTP headers/UA/URI/body markers, DNS for callback domains, JA3/JA4, IP reputation, console fingerprints (title, port) |
| Snort 3 | Same content markers and IP lists as Suricata; no JA4 dependency |
| osquery | Files, accounts, containers/images, listening ports (8787/8790/8890/5435), runner names on servers |
| YARA | Webshell and dropped-file content markers; backdoored image layers once a hash is V1 |
| STIX 2.1 | Every published indicator plus Tool, Intrusion-Set, Campaign and relationship objects; embedded Sigma/Suricata/YARA patterns |
ARTEX Signature Detection Playbook, project definition
Project: MalwareMustDie.org public detection pack against misuse of the ARTEX AI pentest framework
Version: Final 0.4 — 13 November 2026.
Audience: Rule authors and reviewers; downstream users, CERTs and CSIRTs
Distribution: TLP:CLEAR — public release.
Covered formats: Sigma (incl. 5 behavioral correlation rules), Microsoft Sentinel KQL, Suricata 7, Snort 3, osquery, YARA, STIX 2.1 bundle – Lifetime: 1 year for IOCs; behavioral rules do not expire.
Signature development playbook v0.4 (final)
1. Purpose and Principles
This playbook decides, for each indicator collected about ARTEX misuse, whether it enters the signature set, at which confidence tier, in which formats, with what alert wording, and for how long. It exists so that every rule in the public pack can be traced back to a source, a decision, and a reviewer.
Five principles govern every decision:
- Detection, not prevention. Only inline Suricata/Snort and Sentinel automation can block. All other output is an alert for a human or SOAR to act on.
- Evidence before inclusion. No indicator is published at a confidence higher than its best available source supports.
- Confirmed outranks generic. Indicators unique to ARTEX or its operators alert at high priority; generic tool strings never alert alone and always carry a warning.
- Behavior outlives IOCs. Many ARTEX “indicators” on victims are generated by the LLM or by the tools it calls, not hard-coded in the framework. Sequences are preferred over single strings.
- Do no harm by publishing. Nothing that helps an attacker (backdoor trigger values, exploitation detail) and nothing that identifies a private person goes into the public pack.
2. Source Document Review (Input Baseline)
Six inputs were compared by stages until 13 November 2026. The comparison sets the baseline for the decision record in Appendix A.
| Document | Role | Assessment |
|---|---|---|
| ARTEX CTI Report v1.0 (18 Oct 2026, Internal) | Primary internal analysis; 47 reference URLs | Authoritative for campaign context, ConnectWise app IDs, Korean/JPCERT/Zscaler/Wiz IPs. Two attributions could not be confirmed against the cited vendor page (see 2.2). |
| MMD_artex_iocs.docx (original sheet) | Format template; Eye Security + CTI report | Accurate extraction. Git author emails cannot be re-verified (masked by Cloudflare on the live page). |
| MMD_ARTEX_IOCs_v2.docx (10 Nov, review) | Superset of the original + referenced vendor reports | Adds Microsoft Storm-3358 and exposed-secrets IPs, full Wiz UA and probe-path set, Zscaler operator artifacts, backdoored Docker images. Carries verification caveats per item. |
| ConnectWise / Storm-0940 case summary (colleague, 11 Nov) | Timeline and kill chain of the Oct 2026 ConnectWise Cloud Backup compromise | Consistent with Microsoft and Huntress reporting. Re-checked against Huntress’s original analysis, which adds two details that change rule logic (see Section 3A). Note: the incident was a vendor (ConnectWise) app-credential compromise; Microsoft stated its own systems were not compromised. |
| Korea finance & Japan breach-wave summary (staff, 12 Nov) | Timelines, mechanics and IOCs of the first two ARTEX-linked campaigns | Consistent with CrowdStrike, GMO and JPCERT/CC coverage. Re-checked against Japanese reporting of the JPCERT/CC advisory, which adds attack-technique detail used in B1/B2 (see Sections 3B, 3C). Victim counts differ by measure (records vs individuals); not detection-relevant. |
| MMD_ARTEX_IOCs _v3.docx (colleagues checks, 13 Nov) | Merge of v1/v2 + Strand, cross-checked with andpalmier, Censys/SOCRadar, Google/Mandiant, Sophos | Most valuable addition: console fingerprints and the source-confirmed vs model-generated split. Several new items have no public source found yet (see 2.3). Some v2 detail needed by the behavioral rules was dropped (see 2.4). |
2.1 Items verified during review
- Console default port 8787, with 8790 and 443 common: confirmed in Censys coverage (5 Nov 2026). Zscaler’s 8890 is an operator customization, not a contradiction. Both are kept.
- Censys matches consoles by page title plus Next.js static assets: confirmed; supports using the title as a durable console fingerprint.
- Google/Mandiant artifacts: artex-probe-* files and webhook.site callbacks confirmed via secondary coverage of the 30 Oct 2026 GTIG post.
- 178.16.54.129 vs 178.15.54.129: no public ARTEX mention of either. 178.16.54.0/24 (OMEGATECH) carries Spamhaus SBL/DROP listings on neighboring hosts and URLhaus records of ConnectWise-themed lures (Jul 2026). 178.15.54.129 has no threat record. Decision by the project lead: include 178.16.54.129 and the abuse segment; treat 178.15.54.129 as a typo variant.
2.2 Attribution conflicts found
- ReconProbe/1.0: the CTI report attributes it to Wiz, but Wiz’s published IOC table does not list it. v3 classes it as model-generated. Decision: Tier 4.
- norma/0.4: listed by Wiz, but v3 notes the Norma SDK is shared by other agents. Decision: Tier 4, not Tier 1.
- azure-toolkit/1.0: now attributed to Microsoft by two independent internal summaries (CTI report, colleague case summary): upgraded to V2. Still a generic-looking string, so it stays Class D / Tier 4.
- JA3/JA4 hashes: still not seen in any JPCERT/CC material available to this project, including the staff summary. Hold at Tier 4 until a reviewer confirms them in the original.
- JPCERT/CC IP list (9 addresses): matched by the MMD CTI report and the summary of the JPCERT/CC Case E list: upgraded V3 → V2. JPCERT/CC itself warns that listed addresses may be in legitimate use by the time of investigation, which is reflected in the alert text.
- curl/7.88.1 and python-requests/2.34.2: also published by JPCERT/CC as example user-agents for its API-abuse case. Corroborated, but still generic: Tier 4.
2.3 v3 items with no public source located yet
Searches for Strand Intelligence (10 Nov) returned no matching publication. Until a reviewer obtains the original reports, the following v3 items enter the HOLD queue (Section 9), not the pack:
- Favicon SHA256 and mmh3 values; HTTP Basic Auth realm “ARTEX”; health JSON "service": "artex"; recorder proxy 127.0.0.1:8788
- Binary SHA256 of the backdoored build (needs VirusTotal confirmation with project-lead approval before any lookup)
- Fork user-agents: ARTEX-Nuclei-Fingerprint/1.0, ARTEX-CredHunter/2.0, artex-selfupdate, artex-enrich/1.0
- Windows host artifacts (i<intentID>_<purpose>.<ext>, C:\ProgramData\artx5v\, artx* under C:\Windows\Temp), zz<id>.aspx, ZZ<n>$ accounts
- JSP shells cl1217.jsp, f1219a.jsp, z1219.jsp; disposable mail domains (maxxspace.com, yopmail.com, fldubai.com)
2.4 v2 detail to restore in the merged baseline
The behavioral rules depend on items v3 summarized away. These must be carried into the merged IOC baseline from v2:
- Wiz account-recovery, registration, OAuth and SSO probe endpoints, the alg:none JWT test, and AWS Cognito event names (Rule B2)
- Microsoft exposed-secrets ARM retry pattern (28–80 s, corrected api-version) and Storm-3358 tooling WISP / vshell / AdaptixC2 (Rules B4, B5)
- ConnectWise guidance that legitimate Cloud Backup egress is Azure private IPv6 — kept as context only. It must NOT be used as an allow-filter: Huntress saw the Global Administrator escalation itself come from a Microsoft-internal private IPv6 address (see Section 3A).
- Per-item verification caveats (git authors unverified; date first-seen per IP)
3. Decision Workflow Overview
Every indicator passes through the same eight gates, in order. An indicator that fails a gate stops there and is recorded with the reason.
| Gate | Name | Question answered |
|---|---|---|
| G1 | Intake & normalize | Is the value clean, de-duplicated, refanged for rules, and tied to a source, date and URL? |
| G2 | Source verification | How strong is the best source we have actually read? (Section 4) |
| G3 | Uniqueness class | Is it ARTEX-specific, operator/fork-specific, model-generated, generic, infrastructure or behavioral (Section 5) |
| G4 | Exclusion check | Does it hit a legitimate service, private data, attacker-enabling detail or an unrelated namesake? (Section 9) |
| G5 | Tier assignment | Which tier, severity and alert wording follow from G2 × G3? (Section 6) |
| G6 | Format routing | Which of the seven formats can observe this indicator in real logs? (Section 7) |
| G7 | Combination design | Must it co-occur with other signals to fire? Which regex or keyword set? (Section 8) |
| G8 | Lifetime & test | What are valid from / valid until, and has it passed false-positive testing? (Sections 10–11) |
3A. Case Review — ConnectWise Cloud Backup / Storm-0940 (Oct 2026)
This is a well-documented ARTEX-assisted intrusion, so it is used to test the playbook end to end. Sources: Microsoft (21 Oct 2026), Huntress, ConnectWise advisories, and the colleague case summary. The incident was a compromise of a vendor’s multi-tenant app credential; it was not a compromise of Microsoft systems.
3A.1 Kill chain and where each phase is visible
| Phase (2026) | What happened | Visible to | Playbook effect |
|---|---|---|---|
| 10–14 Oct Password spray |
From 144.172.64.99: 327 accounts across 8 orgs, >151,000 failed logons, peak ~2,900/min on 11 Oct. No success, no tokens, no Graph activity. | Each targeted tenant (Entra sign-in logs) | Calibrates B3 thresholds. .99 role = spray source. |
| ~13–15 Oct Vendor credential theft |
Client assertion/secret of ConnectWise Cloud Backup and related Cloud Management apps obtained from ConnectWise’s own tenant. | Vendor only | Not detectable by downstream tenants. No rule; context in STIX. |
| 15 Oct from 01:58 UTC Role self-assignment |
Cloud Management service principals (Exchange Online, Teams, Graph) assigned themselves directory roles, mostly Exchange Administrator, in ~50 Huntress-monitored tenants. | Each tenant (Entra audit log, PIM alerts) | New behavioral rule B6 (proposed). |
| 15 Oct 03:44–03:49 UTC Global Admin + persistence |
Cloud Management – MS Teams (24205314-…) made itself Global Administrator, then a Python-urllib/3.12 script added client secrets (expiring 2028) to an MSP tool and to Huntress’s own app. Source was a Microsoft-internal private IPv6 address. | Each tenant (Entra audit log) | B6 core chain. Source-IP allow-filters would miss it. |
| 15 Oct 06:13–08:34 UTC Tenant sweep |
Cloud Backup app-only sign-ins from 144.172.64.128 to obtain Graph tokens, tenant after tenant in sorted GUID order, seconds apart. | Per tenant: one SP sign-in. Sorted-order pattern: vendor, Microsoft, multi-tenant MSSPs only | Per tenant: T1 on app ID + non-vendor IP. Cross-tenant pattern: guidance for MSSPs, not a public rule. |
| 15–16 Oct Follow-on |
Graph reconnaissance; activity from transient VPN IPs 187.15.88.186 / .90.217 / .89.186. | Each tenant (Graph activity logs) | VPN IPs stay T4 (shared exits). |
| 16–17 Oct Containment |
Advisory published; 7 app identities disabled, certificates revoked, services suspended. | — | App-ID rules stay active until vendor confirms rotation. |
| Late Oct Restoration |
New hardened app ‘ConnectWise Cloud Backup for M365’ requiring re-consent. | — | Do not alert on the new app ID; add it to the documented allow-list once published. |
3A.2 Lessons applied to the playbook
- Act on what the identity does, not where it comes from. The Global Administrator grant came from Microsoft-internal private IPv6, so the ConnectWise app-ID rule now fires on role self-assignment or credential addition regardless of source IP. Source IP is enrichment only.
- Persistence outlives the IOC window. Secrets planted with 2028 expiry survive disabling the original apps. Credential-addition detections have no expiry, and the published hunting window starts at 2026-10-13, which is earlier than the one-year IOC window.
- Authentication is not exfiltration. T1 alerts on app-only sign-ins must say that a successful sign-in alone does not prove data access, and must direct responders to Graph activity and audit logs.
- Disable, do not delete. Response text for app-ID alerts must say to disable the service principal; deleting it destroys consent records needed for investigation.
- Scope includes former customers. Tenants with residual consent were hit. Rule documentation must tell users to check for the app IDs even if they no longer use the product.
- Separate IP roles. 144.172.64.99 = spray (no success); 144.172.64.128 = primary app sign-in source on 15 Oct 06:13–08:34 UTC; 144.172.64.60 = related sign-in/Graph activity. Each IP’s metadata records its role and time window.
- Some detections belong to vendors and MSSPs. The sorted-GUID multi-tenant sweep is only visible across tenants. It goes into the README as guidance for MSSPs and CSIRTs, not into the per-tenant rule set.
- Do not publish Microsoft-internal addresses. The private IPv6 range seen in the escalation is Microsoft cloud infrastructure; publishing it as an IOC would generate false positives on legitimate traffic.
3B. Case Review — South Korean Financial Sector (late Sep – early Oct 2026)
First widely reported real-world ARTEX abuse. Primary source: CrowdStrike (7 Oct 2026). Victim names and counts come from Korean press and regulator notices, not from CrowdStrike. Actor: unknown, likely Chinese-speaking, financially motivated, probably a single operator (CrowdStrike, moderate confidence). Not attributed to Storm-0940 or any named group.
3B.1 Kill chain and where each phase is visible
| Phase | What happened | Visible to | Playbook effect |
|---|---|---|---|
| Operator set-up | ARTEX hosted on 38.244.50.120 (with open directory incl. CLAUDE.md); Hong Kong primary server (IP not published); DeepSeek v4.1-flash via xcai.pro; GLM-5.3 and Grok 4.6 in Claude Code sessions. | Hosting providers, internet scanners; egress logs if inside your network | 38.244.50.120 and xcai.pro stay T3. Operator workspace folders become an osquery/hunting item. |
| Target choice | Peripheral internet-facing systems: loan-progress inquiry service for brokers, employee mobile work-support app. Core banking not targeted. | Victim web/API logs | B1/B2 scope must include low-profile partner and employee portals, not only flagship apps. |
| Access | Authentication/access-control gaps exploited; valid records enumerated. | Victim web/API logs | B2 gains an authorization-enumeration branch. |
| Collection | One service: ~25,000 records exfiltrated over ~30 hours (~14 records/min). | Victim web/API, DB audit | Low-and-slow: volume thresholds would miss it. Use distinct-object counts per identity/session over long windows. |
| Proxying | Proxy IPs incl. 101.53.80.20, 205.214.59.31, 124.155.252.63, 154.201.79.246, 23.248.249.90 and others. | Victim edge logs | Proxy IPs T3 with ‘shared proxy’ note; never auto-block on these alone. |
| Monetization | Claude sessions asked about markets and Telegram groups for selling Korean breach data. | Not visible to defenders | Context only. Personal details in the sessions are excluded (Section 9). |
3B.2 Lessons applied to the playbook
- Count distinct objects, not requests. B2 adds a rule branch for one identity or session reading an unusually high number of distinct record IDs (customer, loan, application numbers) over hours, with no rate condition.
- Peripheral systems are first in line. Rule documentation tells users to deploy B1/B2 on broker, partner, employee-mobile and inquiry APIs first.
- One host, two campaigns. 38.244.50.120 appears in both the Korean campaign and the JPCERT/CC list. It remains T3 on its own, but any B-rule hit from it is raised to T1.
- Keep campaigns separate in STIX. Shared tooling and one shared IP do not establish a shared operator. The Korean activity is modeled as its own unattributed intrusion set.
3C. Case Review — Japanese Breach Wave (Sep – Oct 2026)
Sources: GMO Cybersecurity by Ierae (19 Oct 2026, confirmed ARTEX on attack infrastructure) and the JPCERT/CC advisory (first issued 8–9 Oct, updated through 23 Oct). GMO observed one infrastructure targeting ~20 Japanese companies (9 in one industry) plus six further AI-enabled attack servers by sector; it shared full IOCs with law enforcement only. JPCERT/CC describes several cases; the staff summary reports a later Case E naming ARTEX, Cairn and CyberStrikeAI. Actor(s) unknown; not linked publicly to the Korean campaign or Storm-0940.
3C.1 JPCERT/CC cases and detection relevance
| Case | Technique (per JPCERT/CC reporting) | Playbook effect |
|---|---|---|
| A | Scanning each target for many different known vulnerabilities and management misconfigurations, not one common bug. | Supports B1; no single-CVE rule. |
| B | App-to-Backend (A2B): public smartphone apps analyzed to find API endpoints and keys; internal APIs not reachable from the UI attacked to change user privileges or create accounts; responses compared while toggling headers or sending malformed tokens; blind NoSQL injection to find accounts; API keys stolen elsewhere reused. Example UAs curl/7.88.1, python-requests/2.34.2. | B1 gains an A2B branch; B2 gains header-toggle / malformed-token differential probing and NoSQL-injection probes. |
| C | Exploitation of a Metabase SQL-injection vulnerability via API (UAs python-requests/2.33.1, Metabase-GHSA-vwf4/2.0). | Part of the same wave but not ARTEX-attributed. Out of scope for the ARTEX pack; may ship as a separately labeled companion rule. |
| D | Web shells planted on application servers reachable from public web servers. | Supports B5. |
| E (staff summary) | AI pentest platforms (ARTEX, Cairn, CyberStrikeAI); attempts against internet-facing WSUS servers and downloads of configuration/backup files; IP list of nine addresses incl. 38.244.50.120. | B1 gains WSUS and config/backup download stages. IP list T3 at V2. |
3C.2 Operator tooling seen on attacker servers
- Agent configuration folders for Claude Code, OpenAI Codex CLI and Qwen
- Android/Flutter reverse engineering: jadx, Blutter
- SSRF test scripts based on HTTP 302 redirects to internal targets
- Web shells and tools for MySQL, Jenkins and mail gateways
3C.3 Lessons applied to the playbook
- Mobile apps expose the API map. B1’s A2B branch fires when internal or admin API routes, never called by the official app or web UI, are hit by a client lacking the app’s normal headers or signing, especially after many 401/403 responses.
- Differential probing is a strong signal. The same endpoint requested repeatedly with headers removed, tokens malformed or alg changed, followed by a different response class, is added to B2.
- SSRF via redirect. Requests whose URL-type parameters point to an external host that answers 302 to internal or metadata addresses (e.g. 169.254.169.254, localhost, RFC1918) are added to B1 as a late-stage probe.
- Config, backup and WSUS exposure. Downloads of backup/config artifacts (.bak, .zip, .sql, .env, config.*) and probing of internet-facing WSUS endpoints join B1. Exact paths to be taken from the JPCERT/CC original during rule writing.
- Rate limits are a control, not a rule. JPCERT/CC recommends per-function rate limits on login, password reset, SMS and search. These go into the README’s mitigation section.
- Listed IPs may already be clean. JPCERT/CC states that published addresses may be legitimately used at investigation time. T3 alert text for this list must say so.
- No novel zero-days. All cases exploited known issues and misconfigurations, which supports behavior-first detection over exploit signatures.
4. Source Verification Levels
| Level | Definition | Effect on decision |
|---|---|---|
| V1 | Confirmed: read in the primary vendor/CERT publication, or two independent primary sources agree | Eligible for any tier |
| V2 | Corroborated: one primary source read via a faithful mirror, or two independent secondary sources agree | Eligible for Tier 1–3; reviewer note required |
| V3 | Single secondary source, or primary page cited but not retrievable | Maximum Tier 4; flagged "unconfirmed" in rule metadata |
| V4 | No public source located, or internal-only | HOLD — not published until upgraded |
Hash rule: file hashes are never searched on the open web. A hash moves above V4 only after a VirusTotal lookup approved by the project lead.
5. Uniqueness Classes
| Class | Description | Examples | Default treatment |
|---|---|---|---|
| A | ARTEX-unique, hard-coded or framework-default | ### ARTX-AGENT, X-ARTX-KEY, ArtExVerify/1.0, console title, backdoored image names | Single-signal alert allowed |
| B | Operator- or fork-specific | Mozilla/5.0 (ARTEX), k=x9f3c2b7e, artex-local:perf2-20261003, sink-* runners | Single-signal alert; note fork/operator scope |
| C | LLM- or tool-generated naming patterns | artx_*, artex-probe-*, qa_probe_*, zz-notexist-*, ARTEX-PROBE-0001 | Alert only with a second signal (Section 8) |
| D | Generic tool or library strings | curl/7.88.1, python-requests/*, Boto3, browser UAs, norma/0.4 | Never alerts alone; enrichment only |
| E | Infrastructure (IP, domain, segment, port) | Campaign IPs, artex[.]lol, 178.16.54.0/24, 8787/tcp | Tier by source; time-boxed |
| F | Behavioral sequence | Recon chain, spray cadence, ARM retry, webshell foothold | Sigma correlation / KQL; no expiry |
6. Tier Assignment and Alert Wording
| Tier | Eligibility | Severity | Alert title and mandatory text |
|---|---|---|---|
| T1 | Class A or B and V1/V2 | critical / high | [ARTEX-T1 CONFIRMED] <indicator>. Text: "Indicator unique to ARTEX or a known ARTEX operator. Treat as likely compromise; start incident response." |
| T2 | Class F at V1/V2, or Class C with a second confirming signal | high | [ARTEX-T2 BEHAVIOR] <pattern>. Text: "Sequence consistent with automated ARTEX activity. Validate source and scope before containment." |
| T3 | Class E at V1/V2 (historical incident infrastructure) | medium | [ARTEX-T3 PAST-INCIDENT IOC] <value> (<source>, first seen <date>). Text: "Infrastructure from a published incident; may be reassigned. Correlate with T1/T2 before blocking." |
| T4 | Class D at any level; any class at V3; abuse segments; typo variants | low / informational | [ARTEX-T4 GENERIC – WARNING] <value>. Text: "WARNING: generic agent or unconfirmed indicator. Also produced by legitimate tools and other attackers. Do not act on this alert alone." |
Escalation rule: a T4 hit that co-occurs with a T1 or T2 hit on the same source, host or identity within the correlation window raises the combined alert to the higher tier. A T3 hit plus a T2 hit raises to T1.
Priority rule: rule metadata must sort confirmed (T1) above everything else in every format: Suricata/Snort priority 1–4 mapped to T1–T4; Sigma level critical/high/medium/low; Sentinel severity High/High/Medium/Informational.
7. Format Routing
| Format | Takes | Does not take |
|---|---|---|
| Sigma | Web/WAF strings and paths, identity events, Linux process/file events, Class F sequences (correlation rules) | Raw IP lists longer than ~20 (use STIX/KQL watchlists) |
| Sentinel KQL | Entra/M365/Azure/AWS behaviors, app IDs, IP watchlists, retry-timing logic, SOAR hooks | Packet-level content |
| Suricata 7 | HTTP headers/UA/URI/body markers, DNS for callback domains, JA3/JA4, IP reputation, console fingerprints (title, port) | Identity-provider events; TLS payloads without inspection |
| Snort 3 | Same content markers and IP lists as Suricata; no JA4 dependency | JA4 (not supported natively) |
| osquery | Files, accounts, containers/images, listening ports (8787/8790/8890/5435), runner names on servers | Network content |
| YARA | Webshell and dropped-file content markers; backdoored image layers once a hash is V1 | Infrastructure; behavior |
| STIX 2.1 | Every published indicator plus Tool, Intrusion-Set, Campaign and relationship objects; embedded Sigma/Suricata/YARA patterns | HOLD items; private or attacker-enabling data |
8. Combination and Matching Design
Regex and keyword sets are acceptable starting points, provided each Class C or D signal is paired with at least one other signal. Design rules:
- Anchor: filenames as ^artx[_-] or ^zzartx\d+\.php$, not substring artx.
- Case: list case variants explicitly (ARTX, artx) rather than /i over long patterns, to keep Snort/Suricata fast-pattern efficient.
- Co-occurrence: Class C requires a second element, e.g. artx_ file write + .php extension + ?k= parameter, or artex-probe-* + webhook.site callback.
- Windows and thresholds: every Class F rule declares its window and count (e.g. ≥60 SSO route variants in 120 s; spray median ≤1 s across ≥20 accounts).
- Allow-lists: each rule ships an empty, documented allow-list for authorized ARTEX testers and internal scanners.
8.1 Behavioral rules (Class F)
B1–B5 are the five agreed rules. B6 is proposed from the ConnectWise case review and needs the project lead’s approval before it joins the set. It is listed before B5 only for readability.
| ID | Name | Signal chain | Data sources |
|---|---|---|---|
| B1 | Recon & API-discovery chain | *.js.map or env.js/config.json → swagger/openapi → previously unseen API route, same source, short window. Branches: (a) A2B — internal/admin API routes never called by the official app, from a client lacking the app’s normal headers; (b) config/backup downloads (.bak, .zip, .sql, .env) and WSUS probing; (c) SSRF probes with URL parameters pointing to hosts that redirect (302) to internal/metadata addresses | Web server, WAF, reverse proxy, API gateway |
| B2 | Auth & authorization probing | alg:none JWT, malformed OAuth callback, SSO route-variant burst, reset/username-check burst. Branches: (a) differential probing — same endpoint with headers removed or tokens malformed, then response class changes; (b) NoSQL-injection operators in auth/search parameters; (c) low-and-slow enumeration — one identity/session reading an unusually high count of distinct record IDs over hours, no rate condition (Korea case: ~25,000 records in ~30 h) | Web, API gateway, DB audit, Okta, Entra, Cognito |
| B3 | Distributed spray | ≈1 s cadence across many accounts; UA rotates per burst; IP rotation after block. Calibration from the Storm-0940 case: 327 accounts / 8 orgs, >151,000 failures over 5 days, peaks ~2,900/min | Entra, Okta, Cognito |
| B4 | Agentic cloud retry | SP sign-in without MFA → ARM 4xx → corrected retry in 28–80 s → Key Vault/Storage read | Entra SP sign-ins, Azure Activity, Key Vault |
| B6 (proposed) | Vendor app-identity abuse & persistence | Third-party service principal adds itself to a privileged directory role (Global / Exchange / Privileged Role Administrator) → within minutes adds a client secret or certificate to a different application (often with multi-year expiry). Fires regardless of source IP. Seed list: the 7 ConnectWise app IDs; generic form covers any vendor app. | Entra audit log, PIM alerts, SP sign-in logs, Graph activity |
| B5 | Webshell foothold | ARTX-marker write → INTO OUTFILE / LOAD DATA LOCAL → qa_* or ArtexProbe account → nsenter or runner registration | Linux audit, DB logs, web, GitHub audit |
9. Exclusions and HOLD Queue
| Item | Decision |
|---|---|
| IlyassCODEX/ARTEX | Exclude: unrelated namesake project. |
| api.deepseek.com, Backblaze B2, webhook.site, *.oast.me, *.dnslog.cn | Legitimate or widely used testing services. webhook.site / oast.me / dnslog.cn enter only as T4 enrichment or as the second signal in a T2 combination. api.deepseek.com and Backblaze excluded as indicators. |
| xcai.pro | Include as T3 (LLM reseller used by operators); note that other customers may use it. |
| 127.0.0.1:5435, 127.0.0.1:8788 | Not network IOCs. osquery listening-port context only. |
| Backdoor secret marker | Never published (unknown, and would enable abuse). |
| Telegram handle YY520CN | Exclude from the public pack: identifies an individual and CrowdStrike could not tie it definitively to the operator. |
| Git authors artx@example.local / .com | V4 until re-verified; HOLD. |
| All Section 2.3 items | HOLD until a reviewer upgrades the source level. |
| 178.15.54.129 | Publish as T4 typo variant with explicit note; never as T3. |
| Microsoft-internal private IPv6 seen in the Global Admin escalation | Exclude as an indicator (Microsoft cloud infrastructure). Mention in rule notes only, to explain why source-IP filtering is not used. |
| Huntress and MSP tool app IDs that received planted secrets | Exclude: victims, not indicators. |
| New ‘ConnectWise Cloud Backup for M365’ app | Never alert on it; document it as a legitimate replacement once its ID is published. |
| Personal details in the Korean operator’s sessions (name, phone, Telegram handle) | Exclude entirely from rules, STIX and README. Not definitively tied to the operator; private-person data. |
| Victim organization names (Korean banks, Japanese companies) | Exclude from rules and STIX. Mention only as published by regulators, if at all, in the README. |
| Unpublished Hong Kong primary server; GMO’s law-enforcement-only IOCs | Nothing to include; do not infer or reconstruct. |
| GMO Internet Group Onamae.com Desktop Cloud / FX VPS incident | Distinct event. Do not merge its indicators into the ARTEX pack. |
| JPCERT/CC Case C (Metabase) indicators | Not ARTEX-attributed. Out of scope; optional companion rule with its own label. |
HOLD queue handling: HOLD items live in a private tracking file with the missing evidence stated. Review weekly; promote when the source level reaches V2 or better, otherwise drop at the next major release.
10. Lifetime and Versioning
- Infrastructure (Class E): valid_from 2026-11-13, valid_until 2027-11-13 (one year), per project decision. Each IP keeps its own first-seen date and source in metadata.
- Abuse segment 178.16.54.0/24: included at T4 for the same one-year window, alert-only (never auto-block) because the /24 is multi-origin hosting with collateral risk.
- Class A–D string indicators: one-year review, not hard expiry; downgrade when forks are shown to change them.
- Class F behavioral rules: no expiry; lifecycle status only.
- Hunting window for ConnectWise-related content: from 2026-10-13 (earliest reported activity against the apps) onward, independent of the one-year IOC window, because planted secrets can remain valid until 2028.
- ConnectWise app IDs: remain T1 until ConnectWise confirms the old identities are permanently retired; then downgrade to hunting-only rather than delete.
- Identifiers: reserve a dedicated Suricata/Snort SID block and stable Sigma UUIDs before writing; never reuse an ID after deletion.
- Releases: semantic versions (v1.0.0 = first public). GitHub tag, MISP event, OTX pulse and social posts always reference the same tag.
11. Fine-Tuning and Testing
| Stage | Requirement |
|---|---|
| experimental | Rule compiles/validates (sigma-cli check, suricata -T, snort -T, osqueryi, yara -C, STIX validator). Positive test sample exists (synthetic log line or crafted PCAP). |
| test | Run against ≥7 days of benign data per log type (web, identity, cloud, PCAP). False positives documented in the rule’s falsepositives field. T1 target: zero FP; T2: ≤1 FP/day per 10k users or 1M requests; T3/T4: no target, but volume recorded. |
| stable | Two independent confirmations from users or CSIRTs (GitHub issue, MISP sighting), or one confirmed true positive in a real incident. |
| deprecated | Source retracted, indicator reassigned, or FP rate unacceptable; kept in the repo with reason for one release, then removed. |
Feedback loop: GitHub issue templates for false positive, true positive and new indicator; triaged weekly; changes land in the next patch release with a changelog entry citing the issue.
12. Packaging and Publication Checks
- Every rule carries: tier tag, source name and URL, source level (V1–V3), first-seen date, valid_until, author, license, MITRE ATT&CK IDs.
- License chosen once for the whole pack (Detection Rule License 1.1 is the Sigma community norm).
- Indicators are refanged inside rules and STIX patterns, defanged in README, MISP/OTX descriptions and social posts.
- STIX bundle: Tool (ARTEX), Intrusion-Sets kept separate per campaign (Storm-0940, Storm-3358, unattributed KR finance operator, unattributed JP breach-wave operator(s)); shared indicators such as 38.244.50.120 linked to each campaign without merging actors; Indicators with pattern_type stix/sigma/suricata/snort/yara, confidence mapped from tier, TLP:CLEAR marking, external references to every source.
- Credits: Eye Security, Microsoft, Wiz, Zscaler, CrowdStrike, JPCERT/CC, ConnectWise, Censys, Google/Mandiant, Check Point, Badbyte; andpalmier (cross-check); plus Strand Intelligence once its report is confirmed.
- Final review against Section 9 exclusions immediately before tagging a release.
Appendix A — Decision Record for the Current IOC Set
Application of Gates G2–G6 to the merged v2 + v3 baseline. “Formats” uses: Sg = Sigma, K = Sentinel KQL, Su = Suricata 7, Sn = Snort 3, O = osquery, Y = YARA, X = STIX.
| Indicator group | Source | Class | Tier | Formats | Notes |
|---|---|---|---|---|---|
| Webshell: X-ARTX-KEY header, ### ARTX-AGENT response | V1 Eye | A | T1 | Su Sn Sg Y X | Response marker also in YARA for webroot scans |
| Shell key k=x9f3c2b7e | V1 Eye | B | T1 | Su Sn Sg X | Operator-specific; may rotate |
| UA Mozilla/5.0 (ARTEX), ArtExVerify/1.0 | V1 Eye | A/B | T1 | Su Sn Sg X | (ARTEX) noted as fork-specific in v3 |
| Probe markers ARTEX_WRITE_PROBE, ARTX_PERSIST_OK, artex_control_marker_zz9q, ARTEX-PROBE-0001 | V1 Eye | C | T2 | Sg Su Sn Y X | Fire with a second signal |
| File patterns artx_*, artx-*, zzartx0000.php, artex-probe-* | V1 Eye / V2 GTIG | C | T2 | Sg O Y X | Anchored regex + write context |
| Control-404 probes zz-notexist-*, artx-nonexistent, zzz-nonexistent-xyz123 | V1 Eye/Wiz | C | T2 | Sg Su Sn | Combine with recon chain B1 |
| Accounts qa_probe_*, qa.audit29a; runners sink-* | V1 Eye | B/C | T2 | Sg O K X | B5 component |
| DB: INTO OUTFILE /tmp/x.php5, LOAD DATA LOCAL into artx_* | V1 Eye | B | T1 | Sg O X | |
| Backdoored images tomicdd/artex, congdonglinux/artex | V2 THN/Badbyte | A | T1 | O Sg X | Defends red teams too |
| Other Docker namespaces (mianhuatang11/artex etc.) | V2 | B | T4 | O X | Not confirmed backdoored |
| Image tag artex-local:perf2-20261003; ports 8890/5435 | V1 Zscaler | B | T1/T3 | O X | Operator infra; ports as context |
| Console default ports 8787/8790 + console page title | V2 Censys | A | T3 | Su Sn O X | Port alone = T4; title+port = T3 |
| Favicon hashes, realm, health JSON | V4 | A | HOLD | — | Awaiting Strand Intelligence original |
| ConnectWise app IDs (7): role self-assignment or credential addition | V1 CW/Huntress/MS | B | T1 | K Sg X | Any source IP; text: disable, do not delete |
| ConnectWise app IDs (7): SP sign-in from 144.172.64.0/24 or other non-vendor IP | V1 | B | T1 | K Sg X | Text: sign-in ≠ data access; check Graph logs |
| ConnectWise app IDs (7): consent present only | V1 | B | T4 | K X | Hunting context; covers former customers |
| Credential added to any app by a third-party SP within minutes of a role grant (B6) | V1 Huntress | F | T2 | K Sg | Pending approval of B6 |
| 144.172.64.99 (spray source, 10–14 Oct) | V1 MS | E | T3 | K Su Sn Sg X | Role recorded in metadata |
| 144.172.64.128 (app sign-ins, 15 Oct 06:13–08:34 UTC) | V1 MS/CW/Huntress | E | T3 | K Su Sn Sg X | Combined with app ID → T1 |
| 144.172.64.60 (related sign-in / Graph) | V1 MS/CW | E | T3 | K Su Sn Sg X | |
| Transient VPN 187.15.88.186/.90.217/.89.186 (15–16 Oct) | V2 CTI/colleague | E | T4 | K Su Sn X | VPN exits; high collateral |
| 38.244.50.120 (KR ARTEX host / jump server; JPCERT/CC list) | V1 CS/Zscaler + V2 JPCERT | E | T3 | K Su Sn Sg X | Cross-campaign; any B-rule hit from it → T1 |
| Korean campaign proxy IPs (9) | V1 CS | E | T3 | K Su Sn X | Shared proxies; alert, do not auto-block |
| Zscaler work servers 23.248.226.250–254, proxies | V1 Zscaler | E | T3 | K Su Sn X | |
| Wiz nodes 104.194.150.21, 167.88.172.97 | V1 Wiz | E | T3 | K Su Sn X | |
| JPCERT/CC Case E IPs (8 besides 38.244.50.120) | V2 CTI/staff | E | T3 | K Su Sn X | Text: may now be legitimately used (per JPCERT/CC) |
| Storm-3358 IPs (WISP C2, ARTEX servers, C2) incl. 178.16.54.129 | V2 MS mirror | E | T3 | K Su Sn X | Upgrade to V1 when MS original read |
| 178.16.54.0/24 abuse segment | V2 Spamhaus/URLhaus | E | T4 | K Su Sn X | Alert-only, no block |
| 178.15.54.129 typo variant | V3 | E | T4 | K X | Explicit typo note |
| 199.19.77.84 (exposed-secrets SP sign-ins) | V2 | E | T3 | K Su Sn X | |
| Eye infra 207.5.195.93; artex[.]lol family domains | V1 Eye | E | T3 | Su Sn K X | DNS + HTTP Host |
| xcai.pro LLM gateway | V1 Zscaler/CS | E | T3 | Su Sn K X | Egress from your own network = operator inside |
| Callback *.dnslog.cn, *.oast.me, webhook.site | V1 Eye/GTIG | D | T4 | Su Sn Sg | Second signal for T2 combos |
| Neo-reGeorg UA Firefox/38.0 | V1 Eye | D | T4 | Su Sn Sg | Used by many actors |
| Generic UAs (curl, python-requests, Python-urllib, Boto3, aws-cli, Wiz browser set, norma/0.4, ReconProbe/1.0, azure-toolkit/1.0) | V1–V3 | D | T4 | Sg K Su Sn X | WARNING text mandatory |
| JA3/JA4 (JPCERT) | V3 | D | T4 | Su X | Snort 3 lacks JA4 |
| Zscaler env vars, scripts, workspace files, server accounts | V1 Zscaler | B | T2 | O Y X | For hunting your own servers / seized hosts |
| Storm-3358 tooling WISP, vshell, AdaptixC2 | V2 MS/Censys | B | T2 | X (+ link to existing rules) | Reference existing family rules |
| Git authors artx@example.local/.com | V4 | B | HOLD | — | Re-verify |
| v3 Windows/JSP/aspx artifacts, disposable mail domains, fork UAs | V4 | C | HOLD | — | Section 2.3 |
| Operator workspace folders (.claude/, .codex/, .qwen/, CLAUDE.md) on hosts also showing ARTEX ports | V2 CS/JPCERT | B | T2 | O X | Hunting on own servers; single folder alone = T4 |
| Open directory listing exposing CLAUDE.md or ARTEX config | V1 CS | B | T4 | Su X | For hosting providers / CSIRTs |
| Metabase-GHSA-vwf4/2.0, python-requests/2.33.1 (JPCERT Case C) | V2 | — | Out of scope | — | Optional companion rule |
| Behavioral B1–B5 (B1/B2 expanded in v0.3) | V1 multi | F | T2 | Sg K | Section 8.1 |
Appendix B — Reviewer Checklist (per indicator)
- Source read directly? Level V1–V4 recorded?
- Class A–F assigned with reason?
- Exclusion list checked (legitimate service, private data, attacker-enabling, namesake)?
- Tier, severity, alert title and warning text match Section 6?
- Formats limited to those that can observe the indicator?
- Class C/D paired with a second signal or marked enrichment-only?
- valid_from / valid_until and first-seen date set?
- Positive test and benign-data FP test recorded?
- Defanged in prose, refanged in rule?
- Credit and reference URL present?
Appendix C — Change Log
| Version | Changes |
|---|---|
| 0.1 | Initial draft: document review, gates G1–G8, tiers, routing, exclusions, decision record. |
| 0.2 | Added Section 3A (ConnectWise / Storm-0940 case review, re-checked against Huntress). Removed source-IP condition from the ConnectWise app-ID T1 rule. Proposed behavioral rule B6. Split Storm-0940 IPs by role and time window. Added hunting window from 2026-10-13, ‘disable, do not delete’ and ‘sign-in ≠ data access’ alert text, former-customer scope, and three new exclusions. azure-toolkit/1.0 upgraded to V2 (still T4). |
| 0.3 | Added Section 3B (Korea finance case) and 3C (Japan breach wave,
JPCERT/CC cases A–E). Expanded B1 (A2B, config/backup/WSUS,
SSRF-redirect branches) and B2 (differential probing, NoSQL injection,
low-and-slow distinct-record enumeration). JPCERT/CC IPs upgraded V3→V2 and T4→T3 with reassignment warning. 38.244.50.120 marked cross-campaign with T1 escalation on any B-rule hit. Added operator-workspace hunting item, five exclusions (personal data, victim names, unpublished IOCs, unrelated GMO VPS incident, Metabase case), and per-campaign STIX intrusion sets. |
| 0.4 | FINAL. Editorial corrections by the project lead (source document names and dates, terminology, section titles). Version labels set to 0.4, distribution set to TLP:CLEAR, US spelling applied throughout, andpalmier recorded as a cross-check source. Approved as the baseline for writing the signature set. |
Appendix D: (Additional) An idea on using Zeek to detect using releaaed signatures in upper layers networking data-set (experimental stage).
It would be good for NetSec practitioner with AI tooling to use the signature packs for wider range detection, and Zeek is a natural place to start. Suricata and Snort match packets against fixed content, and the Sentinel KQL rules watch cloud identity logs, but there is a layer in between that neither covers well: the network conversation as a whole. Zeek turns every connection, DNS query, TLS handshake and HTTP transaction into structured logs, and its scripting language can keep state and count over time. That is exactly what the behavioral rules in this pack need, and the structured, tier-tagged notices it produces are easy for AI-assisted triage tooling to sort, so the confirmed (T1) alerts surface first and the generic (T4) noise stays in the background.
The idea below splits Zeek detection into two layers. Example 1 answers "Who are you talking to?" and Example 2 answers "What are you saying, and how are you acting?". Before the details, here is what Zeek can and cannot see from this pack, so nobody expects it to do the job of the KQL or osquery parts.
| Part of the pack | Visible to Zeek? | Where else to detect it |
|---|---|---|
| Past-incident IPs and FQDNs (T3), callback services (T4) | Yes: conn.log, dns.log, http.log Host, ssl.log SNI | Suricata/Snort IP and DNS rules, KQL watchlist |
| Webshell header, ARTEX user-agents, webshell key, response marker (T1) | Yes, but only on cleartext HTTP/1.x (behind TLS termination) | Suricata/Snort content rules, Sigma webserver rules |
| Rule B1 recon chain (T2) | Yes, with SumStats over a time window | Sigma correlation, KQL k06 |
| Rule B2 auth probing (T2) | Partly (single requests); full chains are easier in KQL | Sigma, KQL k07/k08 |
| ConnectWise app abuse, password spray against Entra ID (Storm-0940) | No: this traffic goes to Microsoft's cloud, not through your network | KQL k01-k03, Sigma cloud rules |
| Host artifacts (backdoored images, accounts, dropped scripts) | No | osquery, YARA, Sigma Linux rules |
Example 1: Infrastructure & metadata layer (Layers 3, 4 and DNS/SNI)
Core concept: "Who are you talking to?" Example 1 uses Zeek's Intel Framework to check network routing details and unencrypted connection metadata (IP addresses in conn.log, DNS queries in dns.log, TLS Server Name Indication in ssl.log, HTTP Host headers and user-agents in http.log) against the pack's indicators, in memory, at line rate.
- Why it is useful: even when an operator hides commands inside HTTPS, your network still sees the destination IP, the DNS lookup for
xcai.proorartex.lol, and the server name in the TLS handshake. Matching IPs and names in memory is cheap and scales to high throughput. - Where it pays off most: inbound traffic to your own web, VPN and API endpoints, and outbound traffic to
xcai.pro, the LLM gateway used by ARTEX operators. Egress to it from inside your network suggests an operator is already inside. - Its limitation (why it is Tier 3): operators rent shared VPS and route through public proxies. An IP used by ARTEX last week may belong to an innocent company next week, and JPCERT/CC itself warns that listed addresses may already be in legitimate use. Example 1 hits are therefore T3 (correlate before blocking), and the 178.16.54.0/24 abuse segment, VPN exits and generic user-agents are T4 (logged, never alerted on alone).
- Blind spots: DNS-over-HTTPS and TLS Encrypted ClientHello hide the name; and several important IOCs (the Storm-0940 spray and ConnectWise sign-ins) never cross your perimeter at all, they only show up in Entra ID logs.
Example 2: Application & behavioral layer (Layer 7)
Core concept: "What are you saying, and how are you acting?" Example 2 uses Zeek's HTTP parser and the SumStats (summary statistics) engine to read inside web requests and track behavior over time.
- Part A, exact content signatures (Tier 1): the
X-ARTX-KEYheader, the### ARTX-AGENTresponse marker, theArtExVerify/1.0andMozilla/5.0 (ARTEX)user-agents and thek=x9f3c2b7ewebshell key. The header and the response marker are framework-level (class A); the key belongs to one operator and the(ARTEX)user-agent to one fork (class B). All of them are unique to ARTEX or a known ARTEX operator, so they stay T1, but a different operator on a fresh IP will not necessarily send the class B ones. - Part B, behavioral sequencing with SumStats (Tier 2, Rule B1): one request for a
.js.mapfile or one 404 could be a normal user or crawler. One source pulling five or more distinct source maps, config files, Swagger/OpenAPI docs, backup archives (.bak,.sql,.env) andzz-notexist-*test paths within two minutes is the automated reconnaissance pattern of an AI pentest agent. Commodity scanners such as nuclei or ZAP produce the same pattern, which is why it is T2 (validate before containment). The same chain from the cross-campaign host 38.244.50[.]120 escalates to T1. - Its limitation: Zeek must see cleartext HTTP, so the sensor belongs behind your reverse proxy, load balancer or TLS-decrypting packet broker. Zeek's built-in HTTP analyzer parses HTTP/1.x; the proxy-to-backend leg is usually HTTP/1.1, which makes it the best tap point.
First draft of the scripts (concept)
These are the first draft scripts of this idea, kept here as they were written because the review notes below explain, line by line, why parts of them would stay silent. Please deploy the corrected version further down, not this draft.
#fields indicator indicator_type meta.source meta.desc
38.244.50.120 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] KR ARTEX host / JPCERT Case E jump server (escalate to T1 on B-rule hit)
144.172.64.99 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Storm-0940 password spray source
144.172.64.128 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Storm-0940 primary app sign-in source
207.5.195.93 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Eye Security ARTEX infrastructure
178.16.54.129 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Storm-3358 ARTEX/C2 server
artex.lol Intel::DOMAIN MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] ARTEX family callback domain
xcai.pro Intel::DOMAIN MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] LLM reseller gateway used by ARTEX operators
@load base/frameworks/intel
@load frameworks/intel/seen
@load frameworks/intel/do_notice
redef Intel::read_files += {
"/opt/zeek/share/zeek/site/artex_intel.tsv"
};
# Optional: Customize notice behavior so T3 matches log to notice.log
hook Notice::policy(n: Notice::Info)
{
if ( n$note == Intel::Notice && /MMD-072-2026/ in n$msg )
{
add n$actions[Notice::ACTION_LOG];
}
}
@load base/protocols/http
@load base/frameworks/notice
@load base/frameworks/sumstats
module ARTEX;
export {
redef enum Notice::Type += {
## Tier 1: Confirmed ARTEX HTTP header, User-Agent, or webshell key
Confirmed_HTTP_Indicator,
## Tier 2: Rule B1 automated API/config reconnaissance chain
Behavioral_Recon_Chain
};
# Tier 1 patterns (Class A/B)
const t1_ua_regex = /ArtExVerify\/1\.0|Mozilla\/5\.0 \(ARTEX\)/;
const t1_uri_regex = /[\?&]k=x9f3c2b7e(&|$)/;
# Tier 2 / Rule B1 recon patterns (Class C + B1 stages)
const b1_recon_uri_regex = /(\.js\.map|\/env\.js|\/config\.json|\/swagger|\/openapi|\/zz-notexist-|\/artx-nonexistent|\.(bak|sql|env))(\?|$)/;
# Threshold for B1 recon hits from a single source within 2 minutes
const b1_threshold: double = 5.0;
const b1_window: interval = 2mins;
}
# 1. Inspect HTTP Headers for X-ARTX-KEY (Tier 1)
event http_header(c: connection, is_orig: bool, original_name: string, name: string, value: string)
{
if ( is_orig && name == "X-ARTX-KEY" )
{
NOTICE([
$note=Confirmed_HTTP_Indicator,
$conn=c,
$msg="[ARTEX-T1 CONFIRMED] Header X-ARTX-KEY detected. Indicator unique to ARTEX; treat as likely compromise.",
$sub=fmt("Header value: %s", value),
$identifier=cat(c$id$orig_h)
]);
}
}
# 2. Inspect HTTP Requests for Tier 1 UAs/URIs and feed Rule B1 SumStats
event http_request(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string)
{
local orig = c$id$orig_h;
# Check Tier 1 User-Agent
if ( c$http?$user_agent && t1_ua_regex in c$http$user_agent )
{
NOTICE([
$note=Confirmed_HTTP_Indicator,
$conn=c,
$msg=fmt("[ARTEX-T1 CONFIRMED] ARTEX User-Agent detected: %s", c$http$user_agent),
$identifier=cat(orig, c$http$user_agent)
]);
}
# Check Tier 1 Webshell Key in URI
if ( t1_uri_regex in unescaped_URI )
{
NOTICE([
$note=Confirmed_HTTP_Indicator,
$conn=c,
$msg=fmt("[ARTEX-T1 CONFIRMED] ARTEX webshell key parameter in URI: %s", unescaped_URI),
$identifier=cat(orig, unescaped_URI)
]);
}
# Feed Rule B1 Recon Chain tracker
if ( b1_recon_uri_regex in unescaped_URI )
{
SumStats::observe("artex.b1.recon", [$host=orig], [$str=unescaped_URI]);
}
}
# 3. Initialize SumStats for Rule B1 Behavioral Correlation
event zeek_init()
{
local r1 = SumStats::Reducer($stream="artex.b1.recon", $apply=set(SumStats::UNIQUE));
SumStats::create([
$name="artex-b1-recon-detection",
$epoch=b1_window,
$reducers=set(r1),
$threshold=b1_threshold,
$threshold_val(key: SumStats::Key, result: SumStats::Result) =
{
return result["artex.b1.recon"]$unique + 0.0;
},
$threshold_crossed(key: SumStats::Key, result: SumStats::Result) =
{
NOTICE([
$note=Behavioral_Recon_Chain,
$src=key$host,
$msg=fmt("[ARTEX-T2 BEHAVIOR] Rule B1 recon chain: %s requested %d distinct config/API/probe URIs in %s.",
key$host, result["artex.b1.recon"]$unique, b1_window),
$identifier=cat(key$host)
]);
}
]);
}
Review notes: what was corrected
- The Intel notice hook never fired. The Intel Framework only raises
Intel::Noticewhen the feed has ameta.do_noticecolumn set to T, and its notice text does not containmeta.source, so/MMD-072-2026/ in n$msgcould never match. The corrected loader handlesIntel::matchdirectly and raises its own notice, using the tier frommeta.desc: T1/T3 notify, T4 stays in intel.log only. - Intel DOMAIN matching is exact.
artex.loldoes not matchstaging.artex.lol. The corrected feed lists every FQDN, and the loader adds a DNS suffix check for the operator domains and forartx*.dnslog.cncallbacks. - The user-agent check could not work in
http_request. That event fires before headers are parsed, soc$http$user_agentis not set yet. It moved into thehttp_headerhandler (Zeek upper-cases header names, so"USER-AGENT"). - The B1 regex missed most real requests. The trailing
(\?|$)applied to every alternative, so/zz-notexist-8812,/swagger/,/swagger/index.html,/openapi.jsonand/zzz-nonexistent-xyz123never matched (5 of 9 test URLs). Only the file-extension alternatives are anchored now; all 9 match and the benign samples do not. - Response status was not available. The playbook counts 2xx backup downloads and 404 probes, so B1 is now fed from
HTTP::log_http, which carriesstatus_code. - Additions: the
### ARTX-AGENTresponse marker (server-side body check), T1 escalation for 38.244.50[.]120, the complete tiered feed (43 IPs, 7 FQDNs, 19 user-agents) and the 178.16.54.0/24 segment as a separate optional T4 feed.
Corrected scripts (use these)
The feed is generated from the same tiered IOC list as the pack (iocs/mmd-artex-iocs.csv), so tier, role, first-seen date and source travel with every indicator. Fields are separated by literal tab characters, which are preserved in the block below for copy and paste. The bare Mozilla/5.0 user-agent is left out on purpose: as an exact-match Intel item it would flood intel.log.
#fields indicator indicator_type meta.source meta.desc meta.url
207.5.195.93 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] VPS hosting ARTEX instances | Eye Security observed ARTEX intrusion | first seen 2026-11-12 | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
artex.lol Intel::DOMAIN MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator domain | Eye Security observed ARTEX intrusion | first seen 2026-11-12 | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
staging.artex.lol Intel::DOMAIN MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator domain | Eye Security observed ARTEX intrusion | first seen 2026-11-12 | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
artex.tokena2b.top Intel::DOMAIN MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator domain | Eye Security observed ARTEX intrusion | first seen 2026-11-12 | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
artex.ok7777.eu.cc Intel::DOMAIN MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator domain | Eye Security observed ARTEX intrusion | first seen 2026-11-12 | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
artex.noog2infra.site Intel::DOMAIN MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator domain | Eye Security observed ARTEX intrusion | first seen 2026-11-12 | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
144.172.64.99 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Password-spray source 10-14 Oct (no successful logons); later related activity | Storm-0940 ConnectWise Cloud Backup campaign | first seen 2026-10-10 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/
144.172.64.128 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Primary ConnectWise app-only sign-in source, 15 Oct 06:13-08:34 UTC; combined with ConnectWise app ID = T1 | Storm-0940 ConnectWise Cloud Backup campaign | first seen 2026-10-15 | ConnectWise / Huntress https://www.huntress.com/blog/vendor-credential-enables-unauthorized-access
144.172.64.60 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Related sign-in and Graph activity | Storm-0940 ConnectWise Cloud Backup campaign | first seen 2026-10-15 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/
187.15.88.186 Intel::ADDR MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] Transient VPN exit 15-16 Oct; shared, high collateral | Storm-0940 ConnectWise Cloud Backup campaign | first seen 2026-10-15 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/
187.15.90.217 Intel::ADDR MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] Transient VPN exit 15-16 Oct; shared, high collateral | Storm-0940 ConnectWise Cloud Backup campaign | first seen 2026-10-15 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/
187.15.89.186 Intel::ADDR MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] Transient VPN exit 15-16 Oct; shared, high collateral | Storm-0940 ConnectWise Cloud Backup campaign | first seen 2026-10-15 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/
104.194.150.21 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Wiz-observed node targeting IT/software vendors | Storm-0940 ConnectWise Cloud Backup campaign | first seen 2026-10-01 | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
167.88.172.97 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Wiz-observed node targeting IT/software vendors | Storm-0940 ConnectWise Cloud Backup campaign | first seen 2026-10-01 | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
38.244.50.120 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] ARTEX host / jump server (KR); also on JPCERT/CC Case E list. Any behavioral-rule hit from this IP escalates to T1 | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
101.53.80.20 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator proxy (shared) | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
205.214.59.31 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator proxy / upstream SOCKS :443 (shared) | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
124.155.252.63 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator proxy (shared) | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
154.201.79.246 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator proxy / proxy-pool API :443 (shared) | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
23.248.249.90 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator proxy (shared) | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
23.158.220.98 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator proxy (shared) | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
103.248.148.84 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator proxy (shared) | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
203.160.133.172 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator proxy (shared) | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
209.209.85.38 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator proxy (shared) | Korean financial-sector ARTEX campaign | first seen 2026-09-25 | CrowdStrike https://www.crowdstrike.com/en-us/blog/unknown-threat-actor-uses-artex-to-target-south-korean-finance/
23.248.226.250 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator work server | Korean financial-sector ARTEX campaign | first seen 2026-08-04 | Zscaler ThreatLabz https://www.zscaler.com/blogs/security-research/inside-global-ai-assisted-hacking-campaign
23.248.226.251 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator work server | Korean financial-sector ARTEX campaign | first seen 2026-08-04 | Zscaler ThreatLabz https://www.zscaler.com/blogs/security-research/inside-global-ai-assisted-hacking-campaign
23.248.226.252 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator work server | Korean financial-sector ARTEX campaign | first seen 2026-08-04 | Zscaler ThreatLabz https://www.zscaler.com/blogs/security-research/inside-global-ai-assisted-hacking-campaign
23.248.226.253 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator work server | Korean financial-sector ARTEX campaign | first seen 2026-08-04 | Zscaler ThreatLabz https://www.zscaler.com/blogs/security-research/inside-global-ai-assisted-hacking-campaign
23.248.226.254 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Operator work server | Korean financial-sector ARTEX campaign | first seen 2026-08-04 | Zscaler ThreatLabz https://www.zscaler.com/blogs/security-research/inside-global-ai-assisted-hacking-campaign
161.8.161.140 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Upstream SOCKS proxy (port 11005) | Korean financial-sector ARTEX campaign | first seen 2026-08-04 | Zscaler ThreatLabz https://www.zscaler.com/blogs/security-research/inside-global-ai-assisted-hacking-campaign
xcai.pro Intel::DOMAIN MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] LLM API reseller/gateway used as ARTEX model backend; egress from your own network suggests an operator inside | Korean financial-sector ARTEX campaign | first seen 2026-08-04 | Zscaler ThreatLabz https://www.zscaler.com/blogs/security-research/inside-global-ai-assisted-hacking-campaign
31.59.92.155 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Observed 4-20 Oct (JST); may now be legitimately used per JPCERT/CC | Japanese breach wave, JPCERT/CC Case E | first seen 2026-10-04 | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
31.56.206.187 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Observed 27 Sep-20 Oct (JST); may now be legitimately used per JPCERT/CC | Japanese breach wave, JPCERT/CC Case E | first seen 2026-09-27 | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
46.8.227.73 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Observed 27 Sep-19 Oct (JST); may now be legitimately used per JPCERT/CC | Japanese breach wave, JPCERT/CC Case E | first seen 2026-09-27 | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
64.44.24.195 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Observed from 15 Oct (JST); may now be legitimately used per JPCERT/CC | Japanese breach wave, JPCERT/CC Case E | first seen 2026-10-15 | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
94.183.184.98 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Observed 13-19 Oct (JST); may now be legitimately used per JPCERT/CC | Japanese breach wave, JPCERT/CC Case E | first seen 2026-10-13 | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
94.183.184.254 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Observed 3-20 Oct (JST); may now be legitimately used per JPCERT/CC | Japanese breach wave, JPCERT/CC Case E | first seen 2026-10-03 | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
95.182.99.112 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Observed 4-19 Oct (JST); may now be legitimately used per JPCERT/CC | Japanese breach wave, JPCERT/CC Case E | first seen 2026-10-04 | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
176.65.144.71 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Observed 23 Sep-17 Oct (JST); may now be legitimately used per JPCERT/CC | Japanese breach wave, JPCERT/CC Case E | first seen 2026-09-23 | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
199.19.95.66 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] WISP C2 node | Storm-3358 financial-sector campaign | first seen 2026-11-02 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/11/06/artex-abuse-expands-as-cybercriminals-target-financial-sector/
199.19.95.67 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] WISP C2 node | Storm-3358 financial-sector campaign | first seen 2026-11-02 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/11/06/artex-abuse-expands-as-cybercriminals-target-financial-sector/
199.19.95.68 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] WISP C2 node | Storm-3358 financial-sector campaign | first seen 2026-11-02 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/11/06/artex-abuse-expands-as-cybercriminals-target-financial-sector/
91.92.240.238 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] ARTEX server | Storm-3358 financial-sector campaign | first seen 2026-11-04 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/11/06/artex-abuse-expands-as-cybercriminals-target-financial-sector/
85.11.168.45 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] ARTEX server | Storm-3358 financial-sector campaign | first seen 2026-11-04 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/11/06/artex-abuse-expands-as-cybercriminals-target-financial-sector/
85.11.167.52 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] C2 server | Storm-3358 financial-sector campaign | first seen 2026-11-04 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/11/06/artex-abuse-expands-as-cybercriminals-target-financial-sector/
178.16.54.129 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] ARTEX server (Microsoft IOC table value) | Storm-3358 financial-sector campaign | first seen 2026-10-19 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/11/06/artex-abuse-expands-as-cybercriminals-target-financial-sector/
31.77.229.35 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] ARTEX server | Storm-3358 financial-sector campaign | first seen 2026-10-28 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/11/06/artex-abuse-expands-as-cybercriminals-target-financial-sector/
178.15.54.129 Intel::ADDR MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] Possible typo variant from Microsoft's hunting query; no threat record | Storm-3358 financial-sector campaign | first seen 2026-10-19 | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/11/06/artex-abuse-expands-as-cybercriminals-target-financial-sector/
199.19.77.84 Intel::ADDR MMD-072-2026 [ARTEX-T3 PAST-INCIDENT IOC] Service-principal sign-ins with exposed secrets; Microsoft advises blocking /32 via Conditional Access | Exposed-secrets agentic campaign | first seen 2026-10-28 | Microsoft Threat Intelligence (exposed secrets, 5 Nov 2026) https://www.microsoft.com/en-us/security/blog/
webhook.site Intel::DOMAIN MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] Public webhook capture service; legitimate uses common | Generic ARTEX tradecraft | first seen 2026-10-30 | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
Mozilla/5.0 (ARTEX) Intel::SOFTWARE MMD-072-2026 [ARTEX-T1 CONFIRMED] User-Agent: Agent driving webshells (fork-specific per community source analysis) | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
Mozilla/5.0 (compatible; ArtExVerify/1.0) Intel::SOFTWARE MMD-072-2026 [ARTEX-T1 CONFIRMED] User-Agent: Scripted WAF-bypass verification | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Neo-reGeorg default UA; used by many actors | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
Python-urllib/3.14 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Generic library UA | Eye Security https://labs.eye.security/how-we-defended-against-an-ai-driven-attack/
Python-urllib/3.12 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Generic library UA; also seen in ConnectWise persistence script | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
python-requests/2.34.2 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Generic library UA (Microsoft, Wiz, JPCERT/CC) | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
python-requests/2.31.0 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Generic library UA | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/
python-requests/2.31 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Generic library UA (ConnectWise advisory form) | ConnectWise / Huntress https://www.huntress.com/blog/vendor-credential-enables-unauthorized-access
curl/7.88.1 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Generic tool UA (Microsoft, Wiz, JPCERT/CC) | JPCERT/CC https://www.jpcert.or.jp/at/2026/at260030.html
azure-toolkit/1.0 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Scripted Azure tooling UA | Microsoft Threat Intelligence https://www.microsoft.com/en-us/security/blog/2026/10/21/storm-0940-uses-artex-agentic-ai-connectwise-supply-chain-compromise/
norma/0.4 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Norma agent SDK; shared by non-ARTEX agents | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
ReconProbe/1.0 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Attribution to Wiz not confirmed; likely model-generated | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
Mozilla/5.0 (Windows NT 10.0; Win64; x64) Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Truncated browser UA | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Truncated browser UA | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/124.0 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Truncated browser UA | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/124.0 Safari/537.36 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Truncated browser UA | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Truncated browser UA | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0 Safari/537.36 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Malformed browser UA (no KHTML) | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0 Safari/537.36 Intel::SOFTWARE MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] User-Agent: Malformed browser UA (no KHTML) | Wiz Research https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
#fields indicator indicator_type meta.source meta.desc meta.url
178.16.54.0/24 Intel::SUBNET MMD-072-2026 [ARTEX-T4 GENERIC - WARNING] Abuse segment around 178.16.54.129 (Spamhaus SBL/DROP neighbours, URLhaus lures); multi-origin hosting: alert only, never auto-block | Storm-3358 financial-sector campaign | first seen 2026-07-09 | Spamhaus / URLhaus (segment reputation) https://urlhaus.abuse.ch/host/178.16.54.12/
# MalwareMustDie.org - ARTEX misuse detection pack - Zeek Intel loader (MMD-072-2026)
# Tiers come from meta.desc: T1/T3 raise a notice, T4 is logged to intel.log only.
@load base/frameworks/intel
@load base/frameworks/notice
@load frameworks/intel/seen
module ARTEX;
export {
redef enum Notice::Type += {
## Intel feed hit (tier taken from the feed description)
Intel_Hit,
## DNS lookup of an ARTEX callback name (suffix match, not covered by Intel exact matching)
Callback_Domain
};
const feed_source = "MMD-072-2026" &redef;
}
redef Intel::read_files += {
"/opt/zeek/share/zeek/site/artex/artex_intel.tsv",
# Optional T4 abuse segment; needs Intel::SUBNET support in your Zeek version
"/opt/zeek/share/zeek/site/artex/artex_intel_subnet_t4.tsv",
};
event Intel::match(s: Intel::Seen, items: set[Intel::Item])
{
for ( item in items )
{
if ( ! item$meta?$source || item$meta$source != feed_source )
next;
local desc = item$meta?$desc ? item$meta$desc : "";
if ( /^\[ARTEX-T4/ in desc )
next; # T4 = enrichment only: stays in intel.log, no notice
local n: Notice::Info = [$note=Intel_Hit,
$msg=fmt("%s (seen in %s)", desc, s$where),
$sub=s$indicator,
$identifier=cat(s$indicator, s$where)];
if ( s?$conn )
n$conn = s$conn;
NOTICE(n);
}
}
# Intel DOMAIN matching is exact, so subdomains and callback services need a suffix check.
event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count)
{
local q = to_lower(query);
if ( /(^|\.)(artex\.lol|artex\.tokena2b\.top|artex\.ok7777\.eu\.cc|artex\.noog2infra\.site|xcai\.pro)$/ in q )
NOTICE([$note=Callback_Domain, $conn=c,
$msg=fmt("[ARTEX-T3 PAST-INCIDENT IOC] DNS lookup of ARTEX operator/LLM gateway name %s. May be reassigned; correlate with T1/T2 before blocking.", q),
$identifier=cat(c$id$orig_h, q)]);
else if ( /\.dnslog\.cn$/ in q && /artx/ in q )
NOTICE([$note=Callback_Domain, $conn=c,
$msg=fmt("[ARTEX-T2 BEHAVIOR] ARTEX diagnostic callback %s. Validate source and scope before containment.", q),
$identifier=cat(c$id$orig_h, q)]);
}
# MalwareMustDie.org - ARTEX misuse detection pack - Zeek HTTP detection (MMD-072-2026)
# Needs cleartext HTTP/1.x: tap behind the TLS-terminating reverse proxy / load balancer.
# Event signatures as in Zeek 5.x-7.x (older Zeek: drop original_name from http_header).
@load base/protocols/http
@load base/frameworks/notice
@load base/frameworks/sumstats
module ARTEX;
export {
redef enum Notice::Type += {
## T1: ARTEX webshell header, ARTEX user-agent, operator webshell key or response marker
Confirmed_HTTP_Indicator,
## T2 (T1 from known cross-campaign hosts): Rule B1 automated recon chain
Behavioral_Recon_Chain
};
# T1 patterns (class A/B per playbook)
const t1_ua_regex = /ArtExVerify\/1\.0|^Mozilla\/5\.0 \(ARTEX\)$/ &redef;
const t1_uri_regex = /[?&]k=x9f3c2b7e(&|$)/ &redef;
const t1_body_marker = "### ARTX-AGENT" &redef;
# B1 recon stages: only the file-extension alternatives are anchored
const b1_recon_uri_regex = /\.js\.map|\/env\.js|\/config\.json|\/swagger|\/openapi|\/api-docs|\/zz-?notexist|\/artx-nonexistent|\/zzz-nonexistent|\.(bak|old|sql|env|zip|7z)(\?|$)/ &redef;
const b1_threshold: double = 5.0 &redef;
const b1_window: interval = 2mins &redef;
# Any B1 hit from these hosts escalates to T1 (playbook 3B.2)
const escalate_hosts: set[addr] = { 38.244.50.120 } &redef;
}
# 1. Headers: X-ARTX-KEY and ARTEX user-agents (headers are parsed after http_request)
event http_header(c: connection, is_orig: bool, original_name: string, name: string, value: string)
{
if ( ! is_orig )
return;
if ( name == "X-ARTX-KEY" )
NOTICE([$note=Confirmed_HTTP_Indicator, $conn=c,
$msg="[ARTEX-T1 CONFIRMED] X-ARTX-KEY webshell header. Indicator unique to ARTEX; treat as likely compromise.",
$sub=fmt("value=%s", value),
$identifier=cat(c$id$orig_h, "x-artx-key")]);
else if ( name == "USER-AGENT" && t1_ua_regex in value )
NOTICE([$note=Confirmed_HTTP_Indicator, $conn=c,
$msg=fmt("[ARTEX-T1 CONFIRMED] ARTEX user-agent: %s", value),
$identifier=cat(c$id$orig_h, value)]);
}
# 2. URI: operator webshell key
event http_request(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string)
{
if ( t1_uri_regex in unescaped_URI )
NOTICE([$note=Confirmed_HTTP_Indicator, $conn=c,
$msg=fmt("[ARTEX-T1 CONFIRMED] ARTEX webshell key in URI: %s", unescaped_URI),
$identifier=cat(c$id$orig_h, "k-param")]);
}
# 3. Response body: webshell output marker (may be missed if split across chunks)
event http_entity_data(c: connection, is_orig: bool, length: count, data: string)
{
if ( ! is_orig && t1_body_marker in data )
NOTICE([$note=Confirmed_HTTP_Indicator, $conn=c,
$msg="[ARTEX-T1 CONFIRMED] ARTEX webshell response marker ### ARTX-AGENT",
$identifier=cat(c$id$resp_h, "artx-agent")]);
}
# 4. Rule B1: feed SumStats once the response status is known (2xx downloads, 404 probes)
event HTTP::log_http(rec: HTTP::Info)
{
if ( ! rec?$uri || ! rec?$status_code )
return;
if ( b1_recon_uri_regex !in rec$uri )
return;
if ( rec$status_code == 404 || (rec$status_code >= 200 && rec$status_code < 300) )
SumStats::observe("artex.b1.recon", [$host=rec$id$orig_h], [$str=rec$uri]);
}
event zeek_init()
{
local r1 = SumStats::Reducer($stream="artex.b1.recon", $apply=set(SumStats::UNIQUE));
SumStats::create([
$name="artex-b1-recon-detection",
$epoch=b1_window,
$reducers=set(r1),
$threshold=b1_threshold,
$threshold_val(key: SumStats::Key, result: SumStats::Result) =
{
return result["artex.b1.recon"]$unique + 0.0;
},
$threshold_crossed(key: SumStats::Key, result: SumStats::Result) =
{
local tier = key$host in escalate_hosts ? "[ARTEX-T1 CONFIRMED]" : "[ARTEX-T2 BEHAVIOR]";
NOTICE([$note=Behavioral_Recon_Chain,
$src=key$host,
$msg=fmt("%s Rule B1 recon chain: %s requested %d distinct config/API/probe URIs in %s. Commodity scanners also trigger this; validate before containment.",
tier, key$host, result["artex.b1.recon"]$unique, b1_window),
$identifier=cat(key$host)]);
}
]);
}
Deployment notes
- Copy the four files to
/opt/zeek/share/zeek/site/artex/, add@load ./artex/artex_intel.zeekand@load ./artex/artex_http_detection.zeektolocal.zeek, then runzeekctl checkandzeekctl deploy. - Run the HTTP script on a sensor that sees decrypted traffic (behind TLS termination). The Intel part works on any sensor.
- Tune
ARTEX::b1_thresholdandARTEX::b1_windowwithredeffor your traffic; allow-list your own scanners and any authorized ARTEX testing. - The scripts use Zeek 5.x-7.x event signatures (on older Zeek, drop
original_namefromhttp_header). SumStats works the same on a Zeek cluster. - Status: experimental. The regex logic was tested against sample URLs, but these scripts have not yet been run on every Zeek version. Please test them on your own build and traffic first, and report false or true positives on the GitHub repository so they can be tuned like the rest of the pack.
malwaremustdie.org - @unixfreaxjp 20261113v0.4rk
Appendix E: Addendum (14 Nov 2026) — updates from further and deeper internal tests, pack v1.1.0
Everything above this appendix stays as published on 13 November 2026. This appendix adds what we learned after running the pack against our own deeper internal simulation, and it is the only place where corrections are made. The pack is now v1.1.0. The detection logic of every 1.0.0-rc1 rule is unchanged (same SIDs, same rev, same Sigma IDs); the only rc1 text change is the B6 release below. New content is appended to the existing files and marked Added in v1.1.0.
What the new dataset tests showed
- Markers are easy to rename. We renamed the ARTEX strings (
artx_*,X-ARTX-KEY,k=x9f3c2b7e, probe and account names) in every positive test case. All 13 marker-based (D0) Sigma rules went silent, which is what we expected. The rules exposed to the same rename that kept firing were the D1 and D2 ones. That is the point of this release: the IOCs and markers are context with a short life, and the behavior is the detection. - Windows was a gap. The rc1 webshell foothold chain (B5) was Linux-only. When we ran the simulated agent against Windows, the files it dropped in
C:\Windows\Temp\and the PowerShell it ran were not detected. - Upload-then-execute did not need the ARTEX file name. Matching on
artx_*.phpmisses the same attack under a random name. Matching on "an upload was accepted, then a script was requested from an upload folder by the same client" does not miss it. - Cloud coverage was Azure-only. Arctic Wolf has since reported AntiFox, a fork of ARTEX 0.1.1 that abuses valid AWS IAM users and assumed EC2 roles to steal credentials. The playbook already listed AWS as a target for KQL; rc1 had no AWS rule. That is corrected now.
- OAuth consent and Graph reconnaissance by an app identity were not covered outside the ConnectWise app IDs.
- An IP spray rotated across many source IPs stays below the per-IP thresholds of both Sigma B3 and KQL k03. This is not fixed in v1.1.0; see "Known gaps" below.
What changed in v1.1.0
| Area | Update |
|---|---|
| Durability axis | New label for every rule: D0 renamable string or IOC, D1 needs a code change to evade, D2 behavior-inherent. All v1.1.0 rules are D2. The durability of the rc1 rules is declared in the linter, so the rc1 rules did not need a new rev. python3 tools/mmd_artex-linter.py --coverage prints a telemetry-layer × durability matrix, so you can see where your coverage depends on strings. |
| Rename-proof B5 | Sigma: upload accepted → server-side script requested from an upload folder (any name, nested folders) within 2 minutes. Suricata 7: SID 4260120/4260121, an xbits pair that keeps the upload/execute state per client. |
| Windows webshell | Sigma and osquery: IIS / PHP-CGI / Apache / Tomcat worker spawns cmd, PowerShell or a common LOLBin. Sigma also covers a web worker writing a script into the web root or C:\Windows\Temp\, and the B5w chain (the drop, then a shell on the same host within 15 minutes). There is a Linux equivalent (web server spawns a shell, interpreter or downloader). |
| AWS (AntiFox) | B4 ported to CloudTrail: one IAM identity reads ≥10 distinct secrets in 10 minutes, makes ≥10 distinct IAM/STS discovery calls in 5 minutes, or touches ≥15 buckets in 10 minutes. Sigma value_count correlations plus a KQL section in k04. Allow-list your IaC and CSPM roles. |
| Identity | OAuth consent with high-privilege Graph scopes, for any app and from any IP (Sigma and KQL k01). Service-principal Graph directory-recon burst (KQL k02, MicrosoftGraphActivityLogs). |
| LLM API egress policy | T4 policy rules for servers that resolve or connect to public LLM API endpoints (Suricata/Snort SID 4260400–4260419, Sigma DNS, KQL k10). An agent harness needs an LLM backend whatever it calls itself. These domains are policy categories, not IOCs: allow-list your sanctioned AI clients and watch your servers. |
| IOC lifetime (correction) | The main post says the IOCs expire within one year. That is still the hunting window, but IP indicators now alert only until 2027-02-11 (90 days) and stay hunt-only until 2027-11-13. They are reassigned too quickly to page on for a full year. The IOC CSV has new alert_until, hunt_until and durability columns, and k05 has a watchlist variant that applies the split. STIX valid_until is unchanged. |
| STIX | AntiFox tool object (derived-from ARTEX), an unattributed AntiFox intrusion set and campaign, and indicators for the new rules. The report is renamed v1.1.0 and its modified date is 2026-11-14. The rc1 objects are unchanged. |
| B6 released | B6 (a vendor service principal joins a privileged role, then adds credentials to another application within 30 minutes, from any source IP) was PROPOSED in rc1 and is now RELEASED. It caught the service-principal credential step in our simulation. Detection logic is unchanged; the Sigma files stay in sigma/proposed/ so existing paths do not break, with modified: 2026-11-14. KQL k11 and the STIX B6 indicators are updated to match. |
| Tools and tests | The Sigma harness now evaluates correlation rules on event sequences. It reads every tests/sigma_events*.json file, reports documented expected misses, and has a --mutate mode that renames the markers and checks each rule's declared durability. New test files only: sigma_events_v1.1.0.json (79 cases), sigma_events_simulation_v1.1.0.json (17 steps of our simulation scenario, synthetic data) and nids_samples_v1.1.0.json. The rc1 test files are unchanged. |
Results
| Check | Result |
|---|---|
| Linter (7 formats) | PASS: Suricata 101 rules, Snort 99, Sigma 56 documents, YARA 4, STIX 452 objects, osquery 14, KQL 11 files / 16 queries |
| Sigma harness | 157/157 pass, including 34 correlation/sequence cases; 43/43 single-event rules have a positive test; 4 documented expected misses |
| Mutation test | 15 rules mutated: all 13 D0 rules died (expected), the D1 and D2 rules survived; 0 durability violations |
| NIDS content | 33/33 pass |
These are offline structure and logic checks, the same as for rc1. Native engine runs, PCAP replay (especially the xbits pair) and a 7-day benign-data run (playbook Section 11) are still required before production use.
Known gaps (documented, not hidden)
- A password spray rotated across many source IPs (one or two accounts per IP) stays below the per-IP thresholds of Sigma B3 and KQL k03. Rely on IdP smart lockout and identity-protection risk detections for now. A per-tenant spray rule is a candidate for a later version.
MARKER123/ARTX123came up in our simulation, but we found no public source for them. They are unverified and are not shipped.C:\Windows\Temp\artx*andi<intentID>_*.ps1remain playbook HOLD items, so there is no name-based rule. When a web worker writes or runs them, the v1.1.0 behavior rules catch them; when a file is written outside a web worker, nothing catches it yet.
Where to get it
The same GitHub folder, same directory structure. See CHANGELOG.md (1.1.0) and README section 12 for which existing file received which rule. Verify the files with MANIFEST.sha256. Please break the rules and send false- and true-positive reports; that is how this pack grows.
malwaremustdie.org - @unixfreaxjp 20261114v1.1.0 (addendum)
Appendix F: Activity Chronology (October 2026 – November 2026)
This appendix is a compiled, chronological reference of publicly reported ARTEX-related activity, added at the suggestion of a reviewing CERT. It is here to show the speed and breadth of multi-actor adoption in one place, and to point at behaviors worth turning into rules, not to replace the behavior-first playbook above.
Read it as context, not as indicators. Every row is drawn from a named vendor report, CERT advisory or press account; it contains no new IOCs, no sample data and no primary telemetry. Attribution, victim counts and “confirmed vs attempted” are the sources’ own wording and are often explicitly tentative (for example, Amazon could not verify outcomes outside its own sensors; Microsoft separates attempted from confirmed impact; CrowdStrike separates targeting counts from confirmed post-exploitation). This is a snapshot as of 14 November 2026 and will go stale; treat it the way the rest of the pack is treated: versioned and corrected over time. The last column cross-references the behavioral rules (B1–B6) and tiers in the pack.
| Date (activity / report) | Actor / cluster (attribution confidence) | Scale & targets | Notable behavioral signals | Relevance to B-rules / tiers | Source(s) |
|---|---|---|---|---|---|
| 26 Jul 2026 | Developer “Autumn-27” (n/a) | Public release | ARTEX published open-source (AGPL-3.0); Go backend, Next.js console, PostgreSQL, planner+worker agents. | Background. | Censys; Wiz |
| Late Aug 2026 | Multiple actors (confirmed abuse) | IR cases | First in-the-wild abuse; ARTEX/CAIRN/PentAGI seen in incident response. | Supports a 1 Sep hunt-start. | Google GTIG / Mandiant |
| From early Sep 2026 | Storm-0940 (China state-aligned; high) | Hundreds of orgs (later) | Microsoft dates Storm-0940 ARTEX use to at least September. | Hunt back to 1 Sep (per Sophos). | Microsoft (21 Oct); Sophos |
| 24 Sep 2026 (ARTEX named 30 Oct) | Unknown (DIVD withholds) | DIVD (1 org) | Two Zammad zero-days chained; initial access to root in ~12 min; non-expiring admin API token planted (artex-i13033); “loud and messy”, its own spray collided with its own activity. | Linux web-spawns-shell + nsenter/root (v1.1.0 D2). i<intentID> naming = Sophos hunt note. | DIVD; Sysdig; CSA |
| Late Sep – early Oct 2026 (report 7 Oct) | Unattributed; likely Chinese-speaking, financial (moderate) | ≥7 Korean financial institutions; ~67–68k people | ARTEX config beside Claude Code sessions on exposed servers; web vuln discovery and data theft; no prior monetisation plan. | Playbook T3 infra; B1/B2 web behavior. | CrowdStrike (7 Oct); Korea FSI |
| 8 Oct 2026 | Autumn-27 (n/a) | Ecosystem | Repo removed / closed-source; “hydra effect”: >12,000 repos, 204 forks with code changes by 12 Nov (ScopeWeaver, “ARTEX PRO”, Korean edition, AntiFox). | Why D0 string IOCs age fast: durability axis D0/D1/D2 (v1.1.0). | Wiz; Cloudflare; FBI |
| 9 Oct 2026 | Campaign vs Indian BFSI (unattributed) | NBFCs, fintech, crypto wallets | CERT-In CIAD-2026-0046: steal payment/partner-bank API credentials via exposed apps/APIs, then call fund-transfer APIs; mule transfers; log deletion. | T4 policy warning tier; B1/B2 API probing. | CERT-In |
| 10–21 Oct 2026 | Storm-0940 (China state-aligned; high) | >2,250 M365 tenants; ConnectWise supply chain | Spray 327 accts / 8 orgs, >151k failures, peak 2,900/min (11 Oct, no success in spray); 15 Oct vendor Cloud Backup app credential mints Graph tokens across tenants; some intrusions to privileged cloud access in <3 h. | B3 spray; ConnectWise app IDs (k01/k02); B6 (released v1.1.0); OAuth high-priv consent (v1.1.0). | Microsoft (21 Oct); Huntress; ConnectWise |
| 19–21 Oct 2026 | Unidentified (n/a) | ~up to 80 Japanese firms; 8 disclosed leaks | GMO Cybersecurity by Ierae found ARTEX traces on six public servers; JPCERT/CC confirmed AI-agent use (vuln scanning, API attacks); minor overlooked weaknesses were entry points. | Playbook T3 infra (GMO/JPCERT update); B1/B2 API rules. | GMO Ierae (19 Oct); JPCERT/CC |
| 21 Oct 2026 | Unattributed | n/a | Customized ARTEX combined with Claude Code, Codex and Grok workspaces; scripts hand results between AI sessions. | Awareness: multi-assistant chaining: detect behavior, not brand. | Zscaler ThreatLabz |
| 22 Oct 2026 | Overlap with Storm-0940 (moderate) | Multiple IT/software vendors | October spraying of Okta/Entra ID, Cognito attacks, M365 integration abuse; baseline “not found” probe before fuzzing (e.g. /zzz-nonexistent-xyz123). | T2 control-404 probe (D0); B3 spray; B2 SSO-route. | Wiz Research |
| 17–28 Oct 2026 (report 29 Oct) | VAPOR PANDA (China-nexus; high) | 200+ orgs, ≥14 countries; gov/defense/telecom | One controller; post-exploitation confirmed at 9; BLOODALCHEMY (DLL sideloading); mainly DeepSeek + unidentified LLM; ~1.4B input tokens in one intrusion; reused keys from a 2022 mail-server export; human at decision points. | B1/B3 behavior. C2 domains are new, not in v1.1.0. | CrowdStrike (29 Oct) |
| 25–30 Oct 2026 (bulletins 2 & 6 Nov) | Security researcher, non-malicious | WorkOS (1 internal tool) | Benchmark agent escaped sandbox; bulk record pull via a guessable dev password; detection took 5 days; UAs artex-enrich/1.0, norma/0.4, “Mozilla/5.0 (compatible; ArtEx/1.0)”; escape mechanism undisclosed. | norma/0.4 = T4. artex-enrich/1.0 and ArtEx/1.0 shipped in v1.1.1 (Suricata/Snort 4260123, 4260124). | WorkOS; CSA (8 Nov) |
| 30 Oct 2026 | Multiple targets (ARTEX / derived) | Multiple orgs/sectors | 24 Sep–27 Oct and ongoing; no successful IdP compromise; header WWW-Authenticate: Basic realm="ARTEX"; Sub2API likely supplied the LLM; password-reset pages + exposed APIs → cloud access, sometimes <1 day, no software CVE. | Gap: realm="ARTEX" header not in v1.1.0 (Sophos IPS 2313265). | Unit 42 |
| 20 Oct – 4 Nov 2026 (report 5 Nov) | Unknown backdoor author | 62 consoles served backdoored build | trhhubsd/ARTEX pulled tomicdd/artex (~9k pulls); congdonglinux/artex identical; hidden check runs the CAPTCHA field as root when it starts with a secret marker: unauthenticated root shell before any credential check. | T1 container-image IOCs tomicdd/artex, congdonglinux/artex (YARA/osquery). | The Hacker News; Censys |
| 4 Nov 2026 | Crafty Falcon (unattributed, AI-assisted, financial) | Indian lenders, fintech, payment, crypto | CERT-In CIAD-2026-0058 (Critical): entry via internet-exposed UAT/staging/test; cloud mgmt abuse; small test transfer then larger via victim’s own payment APIs; timed for weekends/holidays; many near-identical variants refined quickly. | Awareness: keep non-prod off the internet; watch payment APIs; T4 warning tier. | CERT-In; Reuters |
| 5 Nov 2026 | Criminal operators | Thousands of consoles; 3 campaigns | “Hacking on Autopilot”: 1,608 live consoles, 10 full DB leaks; Apple code-signing cert theft (>300 .p12), ~190k gaming creds (~6k live), crypto/gambling payment infra; mostly autonomous after goal-set; DeepSeek Flash dominant; model switch after hitting Opus 5.5 safeguards. | Awareness: cheap, large-scale, goal-set autonomy. | Check Point Research |
| 5 Nov 2026 | n/a (exposure study) | 1,465 hosts (~815 distinct) | “Agentic Asbestos”: exposed consoles US/HK/CN; 155 (10.6%) also ran another tracked threat (Cobalt Strike, Vshell, Adaptix C2); 32 open directories exposed implants; a console need not face the internet. | Awareness: keep consoles off the public internet; verify image provenance. | Censys |
| 6 Nov 2026 | Storm-3358 (Cambodia-based, financial; Microsoft) | Financial orgs, mainly SE Asia | ARTEX + conventional tooling: internet scanning, anonymous file upload + SSRF, webshells, then WISP/vshell/AdaptixC2 via curl/netcat; one case GitHub secret → Azure Key Vault exfiltration in ~5 min; one ARTEX run produced 240 log events + errors (autonomy and visible mistakes coexist). | B4 agentic cloud retry (k04); B1 recon; B2/B5 webshell. | Microsoft Threat Intelligence |
| 9 Nov 2026 | Unattributed | Several AWS environments; financial data | October AWS activity: compromised long-term IAM keys search CloudWatch (FilterLogEvents) for AKIA keys, passwords, file paths; anonymous Cognito user-pool abuse (SignUp, token collection); consoles also under names ScopeWeaver, LUCK; UA sometimes “ARTeX”. | AWS B4 sweeps (Sigma value_count + KQL k04, v1.1.0). Cognito SignUp shipped as a new rule in v1.1.1 (below). | Datadog Security Labs |
| 10 Nov 2026 | Multiple actors | Customer telemetry | Webshells, SQL Server command exec, credential theft, lateral movement, rapid repeated command variants; hunt cloud (SP cred-add / role assign by an app; app sign-in with scripted UA) and host (i<intentID>…ps1; artx temp files; MARKER123/ARTX123); IPS 2313257–2313266. | SP cred-add = B6 (released v1.1.0); scripted-UA sign-in = k02; i<intentID>/artx = Windows web-script-drop (v1.1.0). | Sophos X-Ops |
| 11 Nov 2026 | Unattributed (AntiFox fork) | AWS environments | AntiFox = fork of ARTEX 0.1.1 (v2.0), Alibaba Cloud-hosted; abuses valid IAM users and assumed EC2 roles; enumerated IAM/EC2/S3/Lambda/Secrets Manager/KMS…; GitGuardian lab: an ARTEX build with no secret-scanner found 8/9 planted creds in 6–13 s. | AntiFox tool + AWS campaign in STIX (v1.1.0); AWS B4 secrets/IAM/S3 sweeps. | Arctic Wolf; GitGuardian |
| 12 Nov 2026 | Multiple actors | Salesforce customer orgs | Stolen-credential campaign via compromised app credentials and trusted integration sessions; many code-exec/integration paths tried (anonymous Apex, deployed components, varied auth); rapid dynamic automation beyond human speed. | Awareness: SaaS admin/integration surface in scope; app-credential + integration-session monitoring. | Salesforce Threat Intelligence |
| 13 Nov 2026 | 50+ orchestrator families | Internet-wide | Daily AI-pentest tool requests up >30× since 1 Oct; thousands of source IPs; ARTEX+forks >60% of known orchestrators (12 Nov); one case >69 req/min + 400 DB-dump requests/h; Worker scripts artex-*, artex-pgrecon-*, artex-pgw-*, artex-do-*. | Awareness: rate-limit + schema-validate exposed APIs; T4 LLM-egress policy (v1.1.0) complements. | Cloudflare (Cloudforce One) |
| 13–14 Nov 2026 | Disparate Chinese-nexus groups (moderate) | Hundreds of targets; AI platforms + crypto | MadPot decoys (posing as LLM APIs) captured agent memory (3 Oct–5 Nov). Campaign 1: AI-model API key theft (LiteLLM default key, One API isCliRequest bypass, Langflow CVE-2025-3248, SSRF-to-metadata); stolen keys fund further inference: a self-sustaining loop; creds graded L1–L3. Campaign 2: real-time deepfake injection vs 2 exchanges’ KYC liveness (best within 7 px; all rejected server-side). | T4 LLM-egress policy (v1.1.0). Cognito/CloudWatch shipped in v1.1.1; self-funding loop held for later (below). | Amazon Threat Intelligence (MadPot) |
| 13 Nov 2026 | Cybercriminals + nation-state | 10 sectors | FBI FLASH-20261113-001: automates multiple intrusion phases at machine speed; some intrusions to privileged access in <3 h; favours Chinese models (DeepSeek Flash); maps trust between orgs to reach weak third-party vendors; favours less-monitored systems. | Authoritative confirmation of the playbook’s threat model. | FBI / IC3 |
| Context (ongoing) | Various (partly confirmed) | Ecosystem | GitGuardian: 45 ARTEX-“sibling” agentic frameworks; S-RM (4 Nov) IR markers (SQL “ARTEX’ UNION SELECT 1--”, norma/0.4 UA, /opt/artex/data/task/<n>/…, GitHub branches artex-wtest-<n>); SentinelOne: state-aligned and criminal use converge on one tool. | Reinforces durability: markers (D0) vary by fork; behavior (D2) carries. | GitGuardian; S-RM; SentinelOne |
Minor update v1.1.1 from above recent chronology and candidate detections from newer behaviors
The later reports surface a few behaviors that the current B1–B6 set covers only partly. These were written up as candidates, in the same behavior-first, rename-proof way, subject to a benign-data run before they ship. Most of the list below shipped in minor version update of Artex SIgnature Detection v1.1.1, a GitHub-basis-only update: the Status column below records where each one landed. Two remain of candidates stay as future items.
| Behavior (source) | What was reported | Mapping / candidate rule | Status |
|---|---|---|---|
| Cognito anonymous self-registration sequence | Datadog: anonymous SignUp + token collection against public Cognito user pools, sometimes with an “ARTeX” user agent. | Extends B3/B4 to AWS identity. Candidate rule: a single source completing SignUp → ConfirmSignUp → InitiateAuth/GetId/GetCredentialsForIdentity on a user pool at machine speed, correlated by source IP/UA. CloudTrail / Cognito logs. | Shipped in v1.1.1. Sigma anonymous-request base plus a per-source registration-burst correlation, and KQL k04. T4 base, T2 on the burst. |
| CloudWatch financial-data log sweep | Datadog: compromised long-term IAM keys run FilterLogEvents hunting for AKIA keys, passwords and file paths. | Extends the v1.1.0 AWS B4 sweep. Candidate rule: one identity issuing many FilterLogEvents/GetLogEvents across distinct log groups in a short window, especially with secret-like filter patterns. Pairs with the existing secrets/IAM/S3 value_count rules. | Shipped in v1.1.1. Sigma log-search and secret-pattern bases plus a distinct-log-group sweep correlation, and KQL k04. The secret-pattern search is T2. |
| Self-funding LLM-credential loop | Amazon MadPot: theft of AI-model API keys (LiteLLM, One API family, Dify, Langflow…) graded L1–L3, with stolen keys paying for the inference that drives more theft. | The T4 LLM-egress policy rules (v1.1.0) watch the backend side. Candidate rules: (a) access to AI-gateway admin endpoints / default keys from a new source; (b) a server that both serves an AI gateway and makes outbound LLM-API calls it did not before. | Held for a later version. Detection-only scoping is still under review, and the exploit-specific parts stay out on do-no-harm grounds. The cloud secret-theft half is already covered by B4. |
| Deepfake / KYC liveness protocol probing | Amazon MadPot: real-time deepfake injection against crypto-exchange KYC liveness checks (all rejected server-side). | Out of scope for network/host signatures: this is an application-logic abuse. Awareness only: monitor KYC/liveness endpoints for automated retry bursts and server-side rejection spikes; no pack rule proposed. | Held, awareness only. Application-logic abuse with no reliable host or network signal yet; no pack rule. |
| Fork-renamed markers / headers | WorkOS UAs (artex-enrich/1.0, ArtEx/1.0), Unit 42 header realm="ARTEX", S-RM task paths and SQL markers. | Candidate T2 UA additions and a response-header rule (Sophos IPS 2313265 already covers realm="ARTEX"). Kept as candidates because they are D0 and vary by fork; the durable catch stays the D2 behavior rules. | Shipped in v1.1.1. Suricata/Snort 4260122 (realm="ARTEX" response header), 4260123 (artex-enrich/1.0), 4260124 (ArtEx/1.0), with matching IOC rows. All T2, D0 markers alongside the D2 behavior rules. |
| GitHub secret harvesting to cloud vault / IAM | Microsoft (5 Nov) saw ARTEX agents search public GitHub for credentials, app secrets and AI API keys, then act on them; in one case an agent went from a GitHub search to Azure Key Vault exfiltration in about five minutes. GitGuardian’s lab build of ARTEX, which ships no secret scanner, still found 8 of 9 planted secrets in seconds. Microsoft did not attribute the GitHub scanning to a named actor. | The cloud half (service-principal sign-in, failed ARM call, corrected retry in 28 to 80 seconds, then Key Vault read) is already B4. Candidate rule: correlate a fresh secret-exposure signal (a GitHub secret-scanning or push-protection alert, or a secret newly committed) with a first-seen service-principal or IAM sign-in from a new source within minutes, and alert when a leaked secret is used sooner than a human would rotate it. Entra non-interactive sign-ins, Azure Activity, Key Vault diagnostics. | Shipped in v1.1.1. Cross-signal hunt in KQL k01: a GitHub secret-exposure signal followed within minutes by a first-seen service-principal sign-in. The cloud half stays B4. |
| EDR-aware host selection (security-software discovery) | Reported to MMD as ARTEX agents told to skip or de-prioritise hosts that run EDR, attributed in that report to VAPOR PANDA. No public source names this instruction yet, so the attribution is unverified. Security-software discovery itself (ATT&CK T1518.001) is a common pre-action step for both agentic and human operators. | Candidate rule: a web-facing or newly landed process enumerating installed security products early (service, process, registry or WMI queries for AV and EDR names, for example tasklist, Get-Service, a SELECT from AntiVirusProduct), especially just before the recon chain (B1) or a privileged action. osquery and Sigma process_creation. Keep it behavior-based: the host list and product names vary by environment. | Shipped in v1.1.1 as T4 (second signal only), Sigma process_creation for Linux (ps, pgrep, systemctl) and Windows (tasklist, sc, reg). The VAPOR PANDA attribution stays unverified, so the rule is informational and never fires on its own. |
Minor update v1.1.1 also folded in the six agentic patterns Unit 42 documented, with their own caution that each can also come from ordinary automation: a machine-speed credential-validation pivot, a write-then-delete verification loop, and an HTTP 422 self-correcting retry ship as Sigma base-plus-correlation pairs, while the three timing and cross-service patterns (parallel service targeting, a regular think-then-act cadence, and multi-day periodic polling) ship as KQL hunts, since inter-event timing is not a job for a single Sigma logsource. Every base is T4 and only the correlation is T2, so an authorized tester sees the base as informational.
Stable vs. still-evolving
Reading the chronology against the pack: the stable core, the part worth building durable (D2) detection on, is agentic web recon and upload-then-execute, high-rate password spraying, OAuth/application-credential abuse, and cloud credential sweeps. These recur across state-aligned (VAPOR PANDA, Storm-0940), financially motivated (Storm-3358, Crafty Falcon) and opportunistic use, and even in the accidental WorkOS and DIVD cases. What is still evolving is the packaging: the tool’s name and markers (ARTEX, AntiFox, ScopeWeaver, LUCK, “ARTEX PRO”), the exact strings (D0), the LLM backend, and the newer target surfaces (AWS Cognito/CloudWatch, Salesforce integrations, AI gateways themselves). That split is the point of the pack: detect the stable behavior, treat the evolving strings as short-lived context, and let a reference like this one take in the next report instead of chasing each new name.
Corrections and additions are welcome on the GitHub repository; this chronology will be revised with the pack.
malwaremustdie.org - @unixfreaxjp 20261114v1.1.0 (appendix F, activity chronology)