ARTEX: An Agentic Pentesting Framework Turned Espionage Tool
The adversary’s use of the ARTEX agent framework, the wider ARTEX threat picture, the activity recorded in our environment, and the defensive outcomes achieved.
On 17 October 2026 a China-based intrusion set started using a publicly released, open-source agentic penetration-testing framework called ARTEX against more than 200 organizations in at least 14 countries. ARTEX is not a tool an operator drives by hand. It plans, it writes its own JavaServer Pages web shells, it re-encodes its own commands the moment a web application firewall blocks them, and in one recorded engagement it consumed about 1.4 billion input tokens before anyone noticed it was there.
What follows is the whole case, written from our side of the wire: what the public advisories state, what our own telemetry recorded, where the two agree, where the record is still open, and what was closed and then verified by attempting the action again as the application account.
The interesting part is not that an artificial intelligence framework was used. It is that the framework arrived better documented than the defensive tooling pointed at it, and that it was being improved while it worked.
Section 3 opens the machinery: one turn of the agent loop at a time, the four channels the bots use to hand work to each other, and the minute by minute trace of that loop inside our estate.
Throughout, source reported material and our own recorded material are labelled separately with these marks.
As always, names have been changed, except for our external entity.
A note on naming. Host names, internal domain names, application names, service accounts and case record identifiers in this post have been replaced with role-based labels carrying a single name, cybercrypto. The labels are stable throughout and can be read positionally:
cybercrypto-app-dev-01throughcybercrypto-app-dev-05are the development application servers.cybercrypto-app-prod-01is the production application server.cybercrypto-app-web-01is the web server.cybercrypto-cloud-01is the cloud instance.cybercrypto-grants-gateway,cybercrypto-ci,cybercrypto-scm,cybercrypto-wiki,cybercrypto-dev,cybercrypto-artifacts,cybercrypto-iamandcybercrypto-webare the public-facing and internal service endpoints.cybercrypto-svc-01throughcybercrypto-svc-04are service accounts.cybercrypto-app-reg-01andcybercrypto-app-reg-02are cloud application registrations.
Security products in our environment are described by their role rather than by vendor.
External adversary infrastructure, file hashes, tool names and published advisory identifiers are reproduced exactly as reported, because those are the parts you need in order to defend.
- The actor uses AI-driven ARTEX to scale a global espionage campaign (reported 27 October 2026; cited here by advisory identifier)
- Threat actor abuses agentic AI pentesting framework to target South Korean financial institutions
- TAG-217 targets South Korean financial services with ARTEX
- Microsoft Storm-0940 and the ConnectWise Cloud Backup supply chain activity
- Chinese AI tool linked to Korean bank hacks halts public updates
1Bottom line
Nine findings, each marked with where it comes from.
- The campaign
Source reporting - The actor used the publicly released agentic framework ARTEX, run mainly on DeepSeek models, against more than 200 organizations in at least 14 countries from 17 October 2026. The source advisory confirms post-exploitation activity at nine. It attributes the campaign to that adversary with moderate confidence.
- The controller address is in our record, and we had it first
Our record - Advisory CSA-261253, published 27 October, lists
118.128.151.28as the ARTEX controller. Our case record had already named that address as the actor’s address on 26 October. - Techniques the advisories report are present in our record
Our record - JavaServer Pages web shells, Base64-encoded echo commands, and queries for Enterprise Admins and Domain Admins. The advisories name no victims, and this post does not identify any.
- Shell writes were detected as they happened
Our record - On 27 October, five endpoint web shell alerts on
cybercrypto-app-dev-02each fired within one second of a web shell write. A further alert fired oncybercrypto-app-prod-01on 29 October at 15:05:22. - The exploit chain is closed where it was proven open
Our record - On
cybercrypto-app-prod-01,cybercrypto-app-web-01andcybercrypto-cloud-01, the web-root write and the root escalation are both closed. Each closure was verified by attempting the action as the application account. - The campaign indicators are enforced
Our record - Every advisory address and domain is covered by kill rules, and the advisory hashes are set to prevent.
- No sign-in from the controller succeeded
Our record - All four identity events from
118.128.151.28are failures. - No campaign malware was found on screened endpoints
Our record - The vendor hashes and file names returned no match across the endpoint telemetry planes over 30 days.
- ARTEX is used by more than one actor
Source reporting - The source advisory and Microsoft both report this. A commercial edition went on sale on 16 October 2026.
2Threat overview
What the cited sources state. Confidence language is the source’s own.
2.1 ARTEX
- ARTEX is an open-source agentic penetration-testing framework developed in China. It was published on GitHub by the developer “Autumn-27” (Zscaler ThreatLabz; CSA-261253) and first released in July 2026 (Korea JoongAng Daily).
- Zscaler reports that ARTEX shipped a default blocklist restricting the targeting of government entities and universities, and that the blocklist did not extend to financial institutions.
- Autumn-27 converted the project to closed source on 8 October 2026, and Reuters reported the GitHub page had been taken down. Korea JoongAng Daily notes that previously released source and downloaded copies remain usable.
- On 16 October 2026 ThreatBook launched RedAgents, a hosted platform of artificial intelligence penetration-testing agents. Its launch roster includes Artex Pro, an enterprise edition built on the open-source Artex. ThreatBook states the open-source edition was a personal project of the RedAgents product lead (ThreatBook announcement, 20 October 2026).
2.2 The ARTEX campaign
Adversary and attribution. The advisory identifies a China-based targeted intrusion adversary, first observed in February 2021 using the ProxyLogon exploit chain. The source advisory attributes this campaign to that adversary with moderate confidence (CSA-261253). It describes this as the adversary’s first observed artificial-intelligence-driven intrusion, and states the campaign is separate from the ARTEX activity Microsoft tracks as Storm-0940.
Reach against result
One ARTEX controller, 17 to 27 October 2026. Bar length is to scale. Sources: CSA-261253, CSA-261264.
Scale. The source advisory recorded one ARTEX controller, 118.128.151.28, targeting entities in at least 14 countries from 17 to 27 October 2026 (CSA-261253). At least 20 engagements reached more than 200 distinct organizations; post-exploitation was confirmed at nine (CSA-261253, CSA-261264). In one intrusion, the planning agents consumed about 1.4 billion input tokens (vendor research blog, 29 October 2026).
Models. Worker agents were configured with ARTEX_LLM_BASE_URL set to https://api.deepseek.com/v1, and all 35,159 recorded tool-call identifiers follow DeepSeek’s format. The source assesses that the workers almost certainly used DeepSeek models, with high confidence. Planner agents used a second, subscription-based service that the source has not identified (CSA-261264).
Operator and endpoint sensor. Operator instructions were written in Chinese, labelled 【人类指令】 (human instruction). They directed the agent to write web shells, use Base64-encoded echo commands, extract domain administrator passwords and enumerate sensor coverage (CSA-261253). Rather than disable the sensor, the operator directed the agent to avoid it and look for hosts without it (CSA-261264).
Targeting
- Foreign ministries in Latin America, Europe, Asia and the Middle East.
- 19 U.S.-based companies in one engagement, in the pharmaceutical, semiconductor, defense, nuclear and financial sectors.
- Telecommunications providers in the U.S., Belgium and the Philippines.
- Think tanks, shipping and critical-minerals entities, and a U.S. newspaper’s advertising platform.
Sources: CSA-261253, CSA-261264.
Tooling
- BLOODALCHEMY, side-loaded by a legitimate GameHook binary renamed
svchost.exe, and a second loaderacrobat_compat.dll. - Cobalt Strike, loaded by
libcef.dll. - Stowaway, SoftEther and Chisel.
- At the Greek government entity GR1, WebLogic CVE-2020-14882 and CVE-2020-14883 were used to deploy web shells.
Sources: CSA-261253, CSA-261264.
2.3 Other reported ARTEX activity
Storm-0940 (Microsoft, 21 October 2026)
- Microsoft reports that Storm-0940 used ARTEX from September 2026 against hundreds of organizations.
- On 15 October the group compromised Microsoft 365 environments belonging to ConnectWise Cloud Backup customers, attempting sign-ins to more than 2,250 tenants.
- ARTEX was used to speed up reconnaissance, password spraying and OAuth application abuse.
- Microsoft reports that threat actors in other regions have also used ARTEX.
South Korean financial sector, late September to early October 2026
- The source advisory reported on 7 October that an actor used ARTEX and commercial models against South Korean financial institutions.
- Zscaler reports personal data of about 67,000 individuals exfiltrated. Recorded Future cites public reporting of at least 68,000 people across at least seven institutions.
- Recorded Future tracks the actor as TAG-217 and places its infrastructure testing as early as 17 to 22 August 2026. It notes that the evidence does not establish that an artificial intelligence system acted without a human operator.
- Zscaler reports that the actor used Claude Code sessions to seek advice on selling the stolen data and to locate Korean-language Telegram channels that sell data.
Time from intrusion to detection, as reported by Korean press
Hours. Bar length is to scale.
2.4 Source assessments
| Assessment, as stated | Confidence | Source |
|---|---|---|
| The activity is attributed to a China-based targeted intrusion adversary | Moderate | CSA-261253 |
| China-nexus adversaries will highly likely continue adopting agentic frameworks such as ARTEX in the short term | High | CSA-261253, CSA-261264 |
| ARTEX workers almost certainly used DeepSeek models | High | CSA-261264 |
| ARTEX use has highly likely given the adversary access at a scale that would previously have required a substantially larger team | High | CSA-261264 |
| Defenders’ responses ended individual engagements rather than the campaign | Moderate | CSA-261264 |
| The adversary’s success with a publicly available framework and a China-based commercial model represents a likely emerging trend in China-nexus targeted intrusion activity | Moderate | CSA-261264 |
45.116.20.180 is highly likely compromised | High | CSA-261264 |
| It is highly likely that more threat actors will incorporate ARTEX and similar artificial intelligence penetration-testing tools into their operations | Highly likely (as stated) | Recorded Future Insikt Group |
3Anatomy of the bot
How the ARTEX loop actually works, and where it touched us.
This section exists because the phrase “artificial intelligence agent” hides the mechanism, and the mechanism is the part you can see, measure and interrupt. ARTEX is not a program that does a thing. It is a loop that writes a new program for nearly every step it takes, calls a hosted model to decide what to write next, and hands the result to a tool. Everything below is either published in the source reporting or visible in our own telemetry, and the two are labelled separately.
3.1 The framework is a product, and it has a release history
ARTEX was published as open source on GitHub by the developer known as Autumn-27. At the time of collection the repository carried 2,062 stars and 534 forks, a hosted demonstration site, and this technology stack: a Go back end, an embedded Next.js front end, PostgreSQL for state, and model configuration by application programming interface key (ANTHROPIC_API_KEY or OPENAI_API_KEY) or through its own user interface.
Its own licence text forbids using it against any website, online service or networked system, authorised or not. It shipped with default interception rules that block targeting of .gov and .edu domains, including their Chinese equivalents, and did not extend that blocklist to financial institutions. The blocklist is a configuration file, not a control, and anyone who downloads the framework can edit it.
Two months from publication to a hosted commercial edition
2026. The gaps between entries are shown in days.
- 26 JulyARTEX repository created on GitHub, licensed AGPL-3.0
- 17 to 22 AugustInfrastructure testing attributed to the South Korean financial actor (Recorded Future)22 days after release
- 7 to 8 OctoberARTEX use against South Korean financial institutions is disclosed publiclyabout seven weeks later
- 8 to 9 OctoberThe author converts the project to closed source and the repository is taken down
- 16 OctoberA commercial successor, ARTEX Pro, goes on sale on a hosted multi-agent platform
- 17 OctoberThe ARTEX controller at
118.128.151.28begins targeting entities in at least 14 countriesone day after the commercial launch - 24 to 30 OctoberActivity recorded in our estate (section 4)
The lesson for defenders sits in the middle of that timeline: pulling a repository does not recall the copies. Forks are already in the wild, a commercial edition needs no download at all, and one vendor reports detectable user agents on hundreds of internet-exposed instances of the framework. Blocking the tool was never available as a strategy. Blocking the endpoint it thinks with, and detecting the shape of the loop, is.
3.2 The cast: an operator, a planner and workers
Three parties sit in the loop, and the source reporting separates them cleanly.
The operator
A human. The only human input.
Goals are written in Chinese, marked 【人类指令】 (human instruction), and timestamped in China Standard Time. That is the only human input in the entire chain, and it is injected in band, into the same task channel the bots use.
The planner agents
The reasoning tier.
They take one goal and break it into ordered tasks. In the published campaign the planners ran on a separate, subscription-based model service, returned quota errors, and exhausted every profile on 25 October. The provider has not been identified.
The worker agents
The execution tier.
Workers were configured with an environment variable, ARTEX_LLM_BASE_URL, pointed at https://api.deepseek.com/v1. All 35,159 recorded tool call identifiers follow the identifier format used by DeepSeek.
The split between those last two tiers is the architectural detail worth keeping. Reasoning ran on a subscription model. Execution ran on a metered application programming interface. That is a cost decision, and it produces two different traffic profiles to hunt: a small volume of high value planning, and a large volume of cheap execution. It also means the adversary is on a budget. When the planner profiles ran dry on 25 October, the loop lost its reasoning tier and the workers were left holding context.
The loop, end to end
Three places the loop lives: the adversary’s infrastructure, the model providers it rents reasoning from, and the target estate where its tool calls land. Steps 1 to 4 are from the source reporting; steps 5 and 6 are what we recorded.
3.3 One turn of the loop
Every step the framework takes has the same shape. Read it as a sequence, because each numbered item is something that can be instrumented.
- An instruction enters. The operator types a goal into the task console. Goals recorded in the source reporting: write web shells, use Base64-encoded echo commands, extract domain administrator passwords, enumerate endpoint sensor coverage.
- The planner decomposes it. The planner model turns one goal into an ordered list of tasks and writes that list to disk. The published paths show a task store rather than a message bus:
/opt/artex/data/tasks/10/deploy2/is task number 10, second deployment, and/srv/artex-old/is a previous generation kept beside it. - A worker picks up a task and is handed a tool set. The tool set is the framework’s own capability surface: command execution, file transfer, web shell deployment, web application probing, credential reads.
- The worker emits a tool call. Every call carries an identifier. In our telemetry a climbing number is visible on disk: staging names are
ifollowed by five or six digits, under/tmpor the application account’s home directory. We recordedi25344throughi26145on 25 October, andi45844throughi46077on 29 October, an increase of about 20,700 in four days. We read that number as a per-call counter; the framework’s source would confirm it. - The tool runs and the output returns into the worker’s context. The model reads the result and decides the next call. That is the entire engine, and it explains why the loop changes technique when a technique fails. The failure is just another observation in the context window.
- The result is written back to the task record. The planner reads it and issues the next task, or the operator writes a new instruction. The loop continues until the goal is met or the budget runs out.
3.4 How the bots communicate
The framework has four communication channels. Only one of them resembles a conversation, and it is not the one that carries the work.
/opt/artex/data/tasks/10/deploy2/api.deepseek.com/v1?c= command parameters, Lightweight Directory Access Protocol binds, kinit with a host keytabSo the bots do not talk to each other the way a person would recognise. They hand work to each other through persisted state, and the model endpoint is the one participant that belongs neither to the adversary nor to the target. Three consequences follow, and they are the reason this section is here:
- The task store is the coordination point. Interrupt it and the planner has nothing to hand off to.
- The model endpoint is the only hard dependency. Cut it and the worker holds cached context and nothing else. It does not have a fallback, because the framework was never designed to run without a model.
- Volume is measurable. A tool call counter and a token count turn “the agent was active” into a number with a rate attached, which is a far more durable detection primitive than a file hash that dies on the next turn.
3.5 The loop inside our telemetry, minute by minute
The clearest window we have is the evening of 24 October, against cybercrypto-grants-gateway and then cybercrypto-app-dev-01. Times are UTC. Hollow red markers are requests the edge refused; filled markers are requests the application served.
- 18:58 to 19:57WebLogic console and
wls-wsatpaths requested oncybercrypto-grants-gateway, every one answered 403Probing before the successful path. Failed attempts are kept in context and do not stop the run. - 22:36:27First local login to the file applicationAccess acquired.
- 22:50:18Write through the file application’s file managerWeb shell deployed, 13 minutes 51 seconds after the login. The first command request reached it 44 seconds later, at 22:51:02.
- 22:51:02 to 22:57:19Command requests blocked by edge rules, then served as split, trimmed and Base64-encoded variants, HTTP 200 at the application. Shells
zq7f3k2.jspandz8k4m2x9.jsp.The re-encode step. A block is an observation. The next turn works around it, repeatedly, without losing the goal. - 22:51:16One served request:
?c=echo Y2F0IC9ldGMvaG9zdHM= | base64 -d | shDecoded, the command iscat /etc/hosts. Reconnaissance through the shell it just built.
# What the served request did, step by step $ echo Y2F0IC9ldGMvaG9zdHM= | base64 -d cat /etc/hosts # ...and the trailing "| sh" then runs that text as a command.
The interval is the interesting measurement. Between the first blocked request and a working replacement form the gap is seconds, and it repeats across several variants in the same window. A person rewriting a blocked command by hand takes minutes and stops after one or two attempts. A loop takes seconds and does not get bored. That difference in tempo is the cheapest machine behaviour signal available to a defender, and it depends on no adversary address at all.
3.6 The loop adapts, so detection must not be anchored
Tool switching inside one primitive class. The privilege step is an interpreter loader hijack. The recorded form is RUBYOPT pointed at a staged file and passed to ohai. The same class covers PERL5OPT, PYTHONPATH, LD_PRELOAD and BASH_ENV. An agent that reads its own error messages will try each of them in turn.
# Recorded: loader hijack through a sudo grant (staged file name abbreviated) sudo -n RUBYOPT=-r<file>.rb /usr/bin/ohai version # Recorded: rogue local-mode Chef run with a staged cookbook sudo -n /usr/bin/chef-client -z -o recipe[probe] # The class to hunt: any interpreter loader variable carried through sudo # (regular expression over the process command line) sudo\s+(-\S+\s+)*(RUBYOPT|PERL5OPT|PYTHONPATH|LD_PRELOAD|BASH_ENV)=
A second, independent execution path. Beside the loader hijack, the same behaviour appeared inside a rogue local-mode Chef run, with the same injection carried in the cookbook. That path is the only one that surfaced two of the six hosts we know about. Had the rule set been anchored to the loader hijack alone, a third of the affected hosts would have stayed invisible.
Which rule saw which host
Recorded event counts per host, 24 to 29 October. A shaded cell is a match. Outlined cells are hosts that only one rule surfaced.
| Host | Loader-hijack rule | Chef rule |
|---|---|---|
cybercrypto-app-dev-01 | 150 | 528 |
cybercrypto-app-dev-02 | 15 | 21 |
cybercrypto-app-dev-03 | 15 | 2 |
cybercrypto-app-dev-04 | no match | 181 |
cybercrypto-app-dev-05 | no match | 1 |
cybercrypto-app-prod-01 | 42 | no match |
Sensor inventory instead of sensor evasion. The operator did not instruct the agents to disable the endpoint sensor. It instructed them to find hosts without it, judging by task list and folder listings, and to enumerate sensor coverage. The Chinese term recorded is 猎鹰, a bird-of-prey name the instructions use for the endpoint sensor. The defensive reading matters: endpoint agent tampering is not the adversary’s primary lever, because the cheap answer is to move to a host where there is nothing to tamper with.
A budget, not unlimited capability. Planner profiles exhausted their quota on 25 October, and the planners ran on a different service from the workers. About 1.4 billion input tokens were consumed by the planning agents in one published engagement, while post-exploitation was confirmed at nine of more than 200 organisations approached. High volume, low conversion. The framework scales reach far faster than it scales success, which is exactly why reach is the thing to detect.
3.7 Instrumenting the loop
Map each stage to what is observable and the detection problem becomes a coverage problem. The two highlighted stages are worth more than the rest.
- Goal entryoperator to plannerNot observable. It happens on infrastructure we do not control.State it as a blind spot rather than pretending otherwise.
- Reasoningworker to model endpointOutbound HTTPS from a server to a model endpoint, with no browser involved. In the published configuration:
api.deepseek.com, and the same hook coversapi.anthropic.com,open.bigmodel.cnandapi.x.ai.The single highest value hook in this table. The loop cannot reason without it, and it does not depend on any address the adversary rents or rotates. - Task storeplanner to workerCreation of task directories and deployment subdirectories on a host:
/opt/artex/data/tasks/<id>/<deploy>/,/srv/artex-old/Structural rather than lexical. The directory shape is the framework’s, not the operator’s preference, so it survives a change of target or technique. - Loop tempothe tool call counterStaging directory names carrying a climbing number, for example
/tmp/ifollowed by five or six digitsIt counts loop turns rather than content. A rate is comparable across hosts and across days, and it does not care what the tool call did. - Privileged executiontool to hostA
sudogrant carrying an interpreter loader variable pointed outside trusted pathsIt matches a class of behaviour, so it covers variants the agent has not tried yet. - Target interactiontool to applicationFile creation in a served web root; commands in query parameters; encoded or split re-sends seconds after a block; directory queries for privileged groups; ticket requests using a host keytab; credential file readsApplication and identity level, so it holds even when every file hash has changed. A block followed by a working variant seconds later is a machine, not a person.
Reasoning traffic is the dependency the framework cannot replace, and loop tempo is the behaviour it cannot hide. Neither is a hash, and neither expires when the adversary edits a script. Tempo is measurable on any estate the loop touches. Reasoning traffic is measurable wherever an agent runs on infrastructure you can see; when the engine runs on the adversary’s own servers, as it did here, that hook sits with the network egress point and the model provider rather than with the target.
4Activity recorded in our environment
Facts from Incident Response telemetry and the case record. ATT&CK identifiers classify the recorded behaviour; they do not attribute it.
4.1 Contact from advisory infrastructure
The controller address, 118.128.151.28 (ARTEX controller, CSA-261253), as it appears in each telemetry plane:
| Plane | 118.128.151.28 |
|---|---|
| Edge web application firewall (rule-match feed) | 855 rule-matched events on 28 host names, 24 Oct 16:37:13 to 30 Oct 01:11:37. Most carry the block action (cybercrypto-grants-gateway 363; cybercrypto-artifacts 84). The remaining rows were recorded under rules configured with the log or skip action, as the policy specifies. |
| Perimeter firewall | 3,088 rows, 24 Oct 16:36:41 to 29 Oct 23:08:40. The action breakdown covers 2,780 of them: Block 2,530 (262 destinations), Allow 156 (26), Trust 94 (16). Allow and Trust are outcomes of the configured policy. As a destination: 0 rows. |
| Secondary edge network | 12 deny events on cybercrypto-web, 24 Oct 16:35:18 to 25 Oct 17:25:11 |
| Secure web gateway | 285 rows, 25 Oct 19:49:12 to 29 Oct 19:48:51 |
| Private access broker | 17 requests to cybercrypto-iam, 25 Oct 05:48:47 to 14:09:58, every one answered 303. Paths: / (repeated), /identity/connect/token, /api, /swagger, /odata, /help, /.well-known/apple-app-site-association. User agent recorded in the sample row: curl/7.76.1. |
| Identity sign-in and logon events | 4 events, all failures (section 4.3) |
Perimeter firewall actions on traffic from 118.128.151.28
2,780 rows with an action recorded, 24 to 29 October. Each action is the outcome of the configured policy. Bar length is to scale.
The remaining advisory infrastructure, as it appears in our telemetry:
| Advisory address | Recorded in our telemetry |
|---|---|
151.236.22.111 (jump host and SOCKS egress) | Perimeter firewall: 174 events to 21 destinations, 25 Oct 07:02:08 to 29 Oct 21:21:06 |
45.74.31.41 (SOCKS5 egress) | Perimeter firewall: 2 Block events from an internal address to port 9891, 26 Oct 05:17:53 to 05:20:34 |
45.116.20.180 (Chisel relay) | Secondary edge network: 1 event on cybercrypto-web, 25 Oct 17:25:16 |
203.32.25.165 (ARTEX console) | Secondary edge network: 1 event on cybercrypto-web, 25 Oct 17:25:19 |
| Remaining six advisory addresses | No rows in the screened planes |
4.2 Host activity by tactic
| Tactic (ATT&CK) | Recorded activity | Host, time |
|---|---|---|
| Web shell (T1505.003) | Write through the file application’s file manager after the first local login to that application at 22:36:27. The entry path into the application is not established. | cybercrypto-app-dev-01, 24 Oct 22:50:18 |
| Obfuscation (T1027) | Command requests blocked by edge firewall rules were followed within seconds by split, trimmed or Base64-encoded forms that returned 200 at the application, for example ?c=echo Y2F0IC9ldGMvaG9zdHM= | base64 -d | sh at 22:51:16. Shells: zq7f3k2.jsp, z8k4m2x9.jsp. | cybercrypto-app-dev-01, 24 Oct 22:51:02 to 22:57:19 |
| Privilege escalation (T1548.003, T1574) | Loader hijack through a sudo grant: sudo -n RUBYOPT=-r<file>.rb /usr/bin/ohai version. Events: cybercrypto-app-dev-01 150 (25 Oct 02:53:51 to 05:53:49); cybercrypto-app-dev-03 15 (25 Oct 02:14:39 to 02:32:40); cybercrypto-app-dev-02 15 (27 Oct 16:59:18 to 17:50:42); cybercrypto-app-prod-01 42 (29 Oct 17:13:41 to 18:18:40). Staging directories: /tmp/iNNNNN, the application account’s home directory (~/iNNNNN), and on cybercrypto-app-prod-01 /data/staging (26 of the 42 events). | Four hosts, 25 to 29 Oct |
| Privilege escalation (T1548.003) | Local-mode Chef runs: sudo -n /usr/bin/chef-client -z -o recipe[probe] with a staged cookbook path. Events: cybercrypto-app-dev-01 528; cybercrypto-app-dev-04 181; cybercrypto-app-dev-02 21; cybercrypto-app-dev-03 2; cybercrypto-app-dev-05 1. The first Chef payload on cybercrypto-app-dev-02 returned uid=0(root). Whether the escalation on cybercrypto-app-dev-03 succeeded is open in the record. | Five hosts, 24 Oct 23:08:05 to 25 Oct 04:59:04 |
| Credential access (T1003.008, T1552.004) | On cybercrypto-app-dev-03: /etc/shadow reads, kinit with the host keytab, and a simple bind as the application service account with the password in the request parameter. On cybercrypto-app-prod-01: sudo -n /bin/cat through /var/scm/cache/../../../ against /etc/shadow, the .ssh/id_rsa files of three service accounts (cybercrypto-svc-01, cybercrypto-svc-02, cybercrypto-svc-03), one user’s .bash_history, and /var/scm/cache/core.key. | cybercrypto-app-dev-03, 25 Oct 01:43 to 03:51; cybercrypto-app-prod-01, 29 Oct 17:49:29 to 17:53:19 |
| Discovery (T1087.002, T1069.002) | ldapsearch for Enterprise Admins and Domain Admins; Lightweight Directory Access Protocol reads of security descriptors over GSSAPI | cybercrypto-app-dev-03, 25 Oct |
| Internal proxy (T1090.001) | Python TCP relay mapping local ports 41445, 42445 and 43445 to 445, and 41985 to 5985, on three development application servers | cybercrypto-app-dev-03, 25 Oct 03:02 |
| Web shell (T1505.003) | Five 428-byte JavaServer Pages shells, SHA256 757a5ca1b9490f3e3f84df969fe312ea5ace2401c865d9dfbdb96ae6901005a0. Only 2kt0lguw.jsp served requests (200 from 16:37:26 to 18:10:06). | cybercrypto-app-dev-02, 27 Oct 16:28:58 to 16:37:26 |
| Web shell (T1505.003) | pzk8m31x.jsp copied into the file application’s WAR roots | cybercrypto-app-prod-01, 29 Oct 15:05:22 |
4.3 Identity
| Time | Plane | Account / application | Result |
|---|---|---|---|
| 25 Oct 16:33:08 | Directory logon events | Microsoft 365 | ✕ Failed |
| 25 Oct 16:36:07 | Identity provider sign-in logs | cybercrypto-svc-04 / cybercrypto-app-reg-01 | ✕ Failed (invalid credentials) |
| 29 Oct 23:55:06 | Directory logon events | Microsoft 365 | ✕ Failed |
| 29 Oct 23:56:34 | Identity provider sign-in logs | the application service account / cybercrypto-app-reg-02 | ✕ Failed (invalid credentials) |
No successful sign-in from 118.128.151.28 is recorded in the identity provider sign-in logs.
4.4 Advisory reporting set against our record
| Advisory reporting ● | Our record ● | See |
|---|---|---|
118.128.151.28: ARTEX controller (CSA-261253) | Edge, firewall, proxy and identity events, 24 to 30 October | Section 4.1 |
| Operator instruction to write web shells; JavaServer Pages web shells listed (CSA-261253, CSA-261264) | JavaServer Pages shells on cybercrypto-app-dev-01, cybercrypto-app-dev-03, cybercrypto-app-dev-02 and cybercrypto-app-prod-01; 23 web shell SHA256 values held | Section 4.2 |
| Operator instruction to use Base64-encoded echo commands (CSA-261253) | ?c=echo Y2F0IC9ldGMvaG9zdHM= | base64 -d | sh served by the file application, 24 Oct 22:51:16 | Section 4.2 |
| Operator instruction to extract domain administrator passwords (CSA-261253) | ldapsearch for Enterprise Admins and Domain Admins on cybercrypto-app-dev-03 | Section 4.2 |
| Web shells avoiding command literals through reflection and string concatenation (CSA-261264) | Command strings split, trimmed and Base64-encoded after edge firewall blocks, 24 Oct | Section 4.2 |
| WebLogic CVE-2020-14882 and CVE-2020-14883 at GR1 (CSA-261253) | WebLogic console and wls-wsat paths requested on cybercrypto-grants-gateway, 24 Oct 18:58 to 19:57, all answered 403 | Section 3.5 |
| BLOODALCHEMY, Cobalt Strike, Stowaway, SoftEther (CSA-261253, CSA-261264) | No match in the endpoint telemetry planes, 30 days | Section 5 |
5Defensive outcomes
What was closed, how it was verified, and what is now watching.
- Controller identified before vendor reportingThe case record named
118.128.151.28as the actor’s address on 26 October 2026. CSA-261253, which lists the address as the ARTEX controller, was published on 27 October. 26 OctoberOur case record names the address27 OctoberCSA-261253 lists it as the controller - Shell writes detected as they happened27 Oct: five endpoint web shell alerts on
cybercrypto-app-dev-02, each within one second of a shell write, 16:28:58 to 16:37:26. 29 Oct: an endpoint web shell alert oncybercrypto-app-prod-01at 15:05:22. - Exploit chain closed, verified by attemptBoth halves of the chain are closed on
cybercrypto-app-prod-01,cybercrypto-app-web-01(34 roots) andcybercrypto-cloud-01(7 roots): the application account can no longer write into a served web root, and can no longer run code as root through the sudo loader. Each closure was verified by attempting the action as the application account. A two-minute guard re-applies both closures.cybercrypto-app-dev-01andcybercrypto-app-dev-03are contained at the endpoint agent. - Campaign indicators enforcedCustom indicator groups for Windows, Linux and Mac carry process-kill rules on the advisory addresses and domains. 11 SHA256 values are set to prevent. 11 addresses and 6 domains are set to detect. On
cybercrypto-app-prod-01a host firewall drop set holds the 11 advisory addresses; it had matched 0 packets as of 29 Oct 23:05. - Web shell detection specific to the applicationA custom indicator group for the file application is enabled. It detects file creation in the file application’s WAR roots, kills the Java process spawning a shell on the file application’s managed servers, and kills sudo environment injection. The application on
cybercrypto-app-prod-01shuts down automatically on any qualifying endpoint alert on that host (60-second check, live from 29 Oct 23:43:41). - Behavioural detection content measured against live dataOur behavioural detection pack was run against live data. The loader-hijack rule matches four hosts. The Chef rule matches five, two of which (
cybercrypto-app-dev-04,cybercrypto-app-dev-05) the loader rule does not surface. - Application defect fixed at sourceThe file application’s file manager was fixed in the application archive and submitted for test on 29 October 2026 at 22:46 EDT. The result was successful.
- Identity plane heldNo successful sign-in from
118.128.151.28. All four attempts failed (section 4.3). - No campaign malware on screened endpointsThe vendor hashes and file names returned 0 rows across the endpoint telemetry planes over 30 days.
Plane Events screened Hosts Matches DNS 978,168,281 40,799 0 File 8,928,426,222 51,309 0 Process 8,514,413,067 51,338 0 Connection 8,166,669,337 49,401 0
6Collection coverage and limits
What this record can and cannot show.
- The edge web application firewall feed records only requests that match a rule. Requests that match no rule are absent from that feed by design.
- Some telemetry sources returned query errors or held no current data for the window. Those sources are not counted as negatives.
- The internal device behind the two blocked connections to
45.74.31.41on 26 October is not identified. - The entry path into the file application is not established. Whether the Chef escalation on
cybercrypto-app-dev-03succeeded is open in the record. - The advisories name no victim organizations. This post does not map any described entity to our environment.
- A negative result means no match in the plane and window queried. It does not cover planes or hosts that were not queried.
7Indicators
Behaviour first, then infrastructure, then hashes. The behavioural rows are the ones that outlive the campaign.
7.1 Behavioural indicators from our record
| Indicator | Type | Basis |
|---|---|---|
sudo with RUBYOPT, PERL5OPT, PYTHONPATH, LD_PRELOAD or BASH_ENV pointing at a staged file | Behaviour | RUBYOPT=-r<file>.rb /usr/bin/ohai version recorded on four hosts |
sudo -n /usr/bin/chef-client -z -o recipe[...] with a cookbook path under /tmp | Behaviour | Recorded on five hosts, 24 to 25 Oct |
Staging under /tmp/iNNNNN, ~/iNNNNN in the application account’s home directory, /data/staging/iNNNNN*.rb | Path | Loader file locations recorded on cybercrypto-app-dev-01, cybercrypto-app-dev-02 and cybercrypto-app-prod-01 |
sudo -n /bin/cat with a /var/scm/cache/../../../ traversal | Behaviour | Recorded on cybercrypto-app-prod-01, 29 Oct 17:49 to 17:53 |
| Relay listeners on 41445, 42445, 43445 forwarding to 445, and 41985 to 5985 | Behaviour | Recorded on cybercrypto-app-dev-03, 25 Oct |
ROOTOK / ROOT_OK_<n> marker strings | String | Recorded in Chef payloads on cybercrypto-app-dev-03 and cybercrypto-app-dev-02 |
Web shells zq7f3k2.jsp, z8k4m2x9.jsp, 2kt0lguw.jsp, pzk8m31x.jsp | File name | Case record, 24 to 29 Oct |
SHA256 757a5ca1b9490f3e3f84df969fe312ea5ace2401c865d9dfbdb96ae6901005a0 | Hash | 428-byte JavaServer Pages shell, cybercrypto-app-dev-02, 27 Oct |
7.2 Network indicators from our record
| Indicator | Basis |
|---|---|
118.128.151.28 | Case actor address from 24 Oct; ARTEX controller per CSA-261253; recorded as MOACK.Co.LTD in our edge data |
118.128.151.10, .40, .41, .42, .51, .52, .57, .58, .62, .82 | Supplied to the case on 29 Oct; same /24 as the controller |
209.50.255.91, 45.61.188.134, 2605:6404:18a:6838:b5a1:939d:de90:4c45 | Actor network values from case analysis, 28 Oct |
7.3 Indicators from the advisories
| Address | Description (as published) | Advisory |
|---|---|---|
118.128.151.28 | ARTEX controller and open-directory IP address | CSA-261253 |
65.20.92.170 | ARTEX engine egress IP address | CSA-261253 |
151.236.22.111 | Jump host and SOCKS egress IP address | CSA-261253 |
148.113.46.187 | Proxy egress IP address | CSA-261253 |
45.74.31.41 | SOCKS5 egress IP address | CSA-261253 |
45.153.126.223 | Resolution of nginxmysql.com | CSA-261253 |
89.46.234.50 | Resolution of sqlserver-sqlite.com | CSA-261253 |
192.121.47.20 | Resolution of www.ddduuuppp.com | CSA-261253 |
203.32.25.165 | ARTEX console and Secure Shell dynamic-forwarding exit IP address | CSA-261264 |
104.233.154.148 | Open-directory and Secure Shell dynamic-forwarding upstream IP address (port 20068; open directory on port 8080) | CSA-261264 |
45.116.20.180 | Compromised server used as Chisel relay, port 8443 | CSA-261264 |
| Domain | Description (as published) | Advisory |
|---|---|---|
nginxmysql.com | BLOODALCHEMY command-and-control domain | CSA-261253 |
sqlserver-sqlite.com | BLOODALCHEMY command-and-control domain | CSA-261253 |
www.ddduuuppp.com | BLOODALCHEMY command-and-control domain | CSA-261253 |
www.developgram.online | Cobalt Strike command-and-control domain | CSA-261264 |
| SHA256 | Description (as published) | Advisory |
|---|---|---|
3fb5a9fb3e2cb1d6208966bd4e55d10282d19c7250d827efa560463d60a12ee4 | BLOODALCHEMY loader DLL graphics-hook-filter64.dll | CSA-261253 |
364251838edfcf5ef1107fa692da3c5bd9a540482449f645992830134bf807ab | BLOODALCHEMY payload file graphics-hook_config.bin | CSA-261253 |
55ddd6bbe962a260dba426d33f26bfb0925c18d85ca49a3183a9dcdaf3df0bbe | Stowaway binary llll | CSA-261253 |
fa10f23220ab85fecc7f351f97fb6f56f3be3db587f5e0ba9a4069697279c774 | SoftEther binary renamed MStrmanager.exe | CSA-261253 |
49fe70419fd19b81ca8d730a6ef7c1ec71b681d60b390761070d42686c7d2068 | Legitimate GameHook binary named svchost.exe, used for side-loading | CSA-261253 |
2efc820d9fd40a382a595e8953f382e1291bcb145c7d83b7def8f5b6fe1ae2fb | Cobalt Strike loader DLL libcef.dll | CSA-261264 |
2748a0a10a86a81be7e2ab813e7a85885d1b259b38057438e48a67e44803bd45 | Encrypted Cobalt Strike payload file cache.dat | CSA-261264 |
5ec24779c24bcbf02fbd32acfbb98cb1d6ffa9cc719a2a4c4dfaf5f6faf781fb | Decrypted Cobalt Strike Beacon | CSA-261264 |
3b65d3675f9108060c1bbd5ddceeddbc249f765a5081cf4a3f30707c8f3fc6d5 | BLOODALCHEMY loader DLL acrobat_compat.dll | CSA-261264 |
d62619b54f75eeb491a963dd637bb88898855e2b73e97606c37bab117ad1c259 | Encrypted BLOODALCHEMY payload file 99cd33a02d60e2a3.dat | CSA-261264 |
0beb5aca4ba62671580558661c8bc1b3881c1d749789cbd2f2279ab87dac77e4 | Decrypted BLOODALCHEMY backdoor | CSA-261264 |
| Fingerprint or marker | Description (as published) | Advisory |
|---|---|---|
134f28f7cd6c67ade04d7ca1166b175bc4751a837b6b6ac02eae02cf85a42f6e | TLS certificate on all three BLOODALCHEMY command-and-control addresses | CSA-261253 |
21d14d00021d21d21c42d43d0000007abc6200da92c2a1b69c0a56366cbe21 | JARM hash shown with that certificate | CSA-261253 |
ad0778dcefab688f3734a14d07946e9fb300776b773846265922e0eb1a4855a3 | Self-signed TLS certificate on the ARTEX console at 203.32.25.165 | CSA-261264 |
artx or artex in command lines; artx-prefixed AWS roles; art18- Systems Manager comments; C:\ProgramData\artx5v\ | ARTEX markers | CSA-261253 |
itop_hook | Daily scheduled task for BLOODALCHEMY persistence | CSA-261264 |
/opt/artex/data/tasks/10/deploy2/; /srv/artex-old/ | Paths recorded in ARTEX infrastructure | CSA-261264 |