AgentBaiting / FakeGit — SmartLoader to StealC via Fake AI Skills and MCP Servers

Roughly 7,600 malicious GitHub repositories, 800+ posing as AI Skills or Model Context Protocol servers, funnelling a LuaJIT-based loader and the StealC infostealer into developer and agent workflows.
Threat
AgentBaiting (FakeGit / SmartLoader)
Severity
ACTIVE CAMPAIGN
Type
Supply chain → loader → infostealer
Initial Access
User / AI-agent execution of downloaded ZIP
Version
v0.1 · 2026-07-28
Author
HuntPack
Confidence
High (primary vendor research + independent malware analysis)
01

Executive Summary

Attacker objective: harvest live browser sessions, credentials, cloud tokens and developer secrets from workstations by getting a human or an AI coding agent to download and run a Windows ZIP that presents itself as an AI Skill or an MCP server.

Island published research on 2026-07-20 describing a wave of the long-running FakeGit operation: about 7,600 malicious GitHub repositories created by roughly 6,600 profiles, of which more than 800 pose as AI Skills or Model Context Protocol (MCP) servers. Those AI-capability repositories were reproduced more than 600 times across public registries including LobeHub, Glama, MCP.so and MCP Market, and the wider operation recorded more than 14 million measured downloads across GitHub Release assets in around 200 repositories. The AI-themed wave built through March and peaked in April 2026.

The new part is the delivery route, not the malware. Island calls it AgentBaiting: the repositories are written to be discovered and parsed by AI agents. An agent searching for a capability finds the repository on its own, treats the attacker's README as legitimate documentation, and hands the install instructions to the operator. In Island's testing Claude Code, Gemini and ChatGPT all surfaced campaign repositories without ever being given a link. This turns a discovery step that used to require a human judgment call into an automated recommendation.

What actually runs: the ZIP contains no MCP manifest and no server code. It contains three or four files: a one-line .cmd or .bat launcher, a renamed LuaJIT interpreter, an optional lua51.dll, and a 300 KB single-line obfuscated Lua script disguised with a benign extension such as .txt, .log, .ico, .class or .ui. The launcher runs start <exe> <payload>. The interpreter is a GUI-subsystem build so no console appears, and the Lua stage additionally calls GetConsoleWindow plus ShowWindow(SW_HIDE) through the LuaJIT FFI. SmartLoader then fingerprints the host, screenshots the desktop, resolves its live C2 from a value stored in a Polygon smart contract, pulls encrypted second stages from GitHub, and reflectively loads a packed StealC PE.

Highest-value defensive angle: the execution chain is structurally weird and does not resemble any legitimate software install. A cmd.exe child that is an unsigned interpreter in a user-writable path, taking a .txt-extension file as its only argument, is a near-unique signature. Two masquerading daily scheduled tasks under %LOCALAPPDATA% named <BenignProductName>_<Base64LoaderId> give a second, independent catch point. Both are cheap to hunt and hard for the operator to change without rewriting the loader.

Defender priority: StealC takes live sessions and OAuth grants, not just passwords. If you confirm SmartLoader execution, password resets alone do not contain it. Revoke browser sessions, OAuth grants, API tokens, cloud keys and developer credentials for the affected user, and treat every AI Skill / MCP server installed from an unvetted repository in the last 120 days as suspect.

02

Source Review & Web Hunter Notes

Thirteen sources fetched and snapshotted on 2026-07-28 into AgentBaiting-SmartLoader-Hunt-sources/. Every atomic indicator in this pack traces to at least one of those snapshots.

TierSourceKey findingCarry forward
1 · PrimaryIsland — AgentBaiting: How 800+ Fake AI Skills and MCP Servers Delivered Malware (2026-07-20)Campaign scale, AgentBaiting technique, ZIP internals (application.cmd / luau.exe / ico64.txt), 10 repository + ZIP SHA-256 pairsYes
1 · PrimaryHexastrike — Cloned, Loaded, and Stolen: 109 Fake GitHub Repositories Delivered SmartLoader and StealCFull reverse-engineering of the same loader family: Polygon dead-drop resolver, contract address and selector, bare-IP C2, two-task persistence, staged StealC PE, loader/payload hashesYes
1 · PrimaryCentri — JIT Happens: Exposing LuaJIT Malware In The WildIndependent SmartLoader dynamic analysis: ip-api.com geolocation check, task caching in the Pictures folder, %APPDATA%\<Base64LoaderId>\ staging, session.lua/debug.lua in %TEMP%, static Lua user agent, scheduled task WindowsErrorReporting_ODEwYes
1 · PrimaryAhnLab ASEC — Distribution of SmartLoader via GitHub Repository Disguised as a Legitimate ProjectFour-file ZIP layout (java.exe / Launcher.cmd / lua51.dll / module.class), persistence copy to %AppData%\ODE3, tasks SecurityHealthService_ODE3 and WindowsErrorRecovery_ODE4, C2 task JSON schemaYes
2 · CorroboratingIntellibron — Lua-JIT SmartLoader: Analyzing the GitHub Campaign Delivering StealerSecond confirmation of SecurityHealthService_ODE3 plus ApplicationExperienceAnalysis_ODE4; compiler.exe / import.ui / Launch.bat variant; ip-api.com lookupYes
2 · CorroboratingCloud Security Alliance Labs — research note on FakeGit / AgentBaiting and the MCP supply chainEcosystem context: registry vetting failures, share of published Skills carrying critical issues, scale of the MCP registryPartial (framing only)
2 · Trade pressBleepingComputer, The Hacker News, Help Net Security, DevOps.com, TechNadu, CyberSecurityNews, GBHackersIndependent restatement of scale and technique; CyberSecurityNews independently reproduces three of Island's ZIP SHA-256 values; The Hacker News adds the historical link to the Lumma-era operation tracked as Water KuritaPartial

Analyst decisions

  • Two waves, one loader. Island documents the July 2026 AI-Skills/MCP wave; Hexastrike, ASEC, Centri and Intellibron document the same SmartLoader family from earlier waves. The lure surface changed. The post-execution chain did not. Indicators are labelled by wave in section 4 so nobody mistakes an April C2 address for current infrastructure.
  • Nothing ships at prevent/critical. Only the three ZIP hashes that appear in two independent sources are proposed at prevent, and at severity high. Everything single-sourced ships at detect or hunt.
  • The Polygon-resolved C2 is deliberately perishable. The operator rotates it by updating one on-chain value. The two observed bare-IP addresses are last-seen 2026-04-12 and are shipped as historical detect, with the behavioural resolver hunt (Q5) carrying the durable detection weight.
  • No repository allow/deny list ships. With ~7,600 repositories across ~6,600 accounts and active rotation, a name list is stale on arrival. The pack hunts the execution chain and the install path instead.
  • Attacker-authored text encountered in a legitimate source. Island quotes the campaign README's own install instructions as evidence ("download the .exe from the Releases page, click More info then Run anyway"). That is reproduced research evidence describing the lure, not guidance to act on, and it did not influence any value in this pack.
03

Hunt Brief & Attack Chain

Attack chain

#StepTelemetryHunt angle
1Attacker clones or fabricates a project, publishes it under a lookalike profile (one character off a real developer), writes a convincing README, attaches a Windows ZIPNone on-endpointExternal: repository inventory, publisher verification
2Repository is indexed by public MCP / Skill registries, reproducing the attacker README and download linkProxy / web gatewayEgress logs to registry domains followed by a GitHub release download
3AgentBaiting: a human or an AI coding agent searching for a capability discovers the repository and surfaces the install instructionsAgent CLI logs, shell history, ProcessRollup2 parentageQ10 — coding-agent process spawning a shell that downloads or extracts an archive
4ZIP downloaded and extracted to Downloads / Temp / DesktopZipFileWritten, PeFileWrittenQ9 — AI/MCP-themed archive dropped; Q2 — Lua runtime unpacked to a user-writable path
5User runs the launcher: a one-line .cmd/.bat containing start <exe> <payload>ProcessRollup2Q1 — the core signature: cmd.exe parent, unsigned interpreter child in a user path, data-file argument
6Renamed LuaJIT interpreter (GUI subsystem, unsigned, no version metadata) executes the Prometheus-obfuscated Lua payload; console hidden via FFI ShowWindowProcessRollup2, PeFileWrittenQ1, Q2; IOA on the parent/child/extension triple
7Anti-debug check using native shellcode copied into executable memoryMemory-scan detections onlyGap — no reliable process-level telemetry
8Host geolocation and fingerprinting via ip-api.com; desktop screenshot captured through GDIDnsRequest, NetworkConnectIP4Q6 — geo-IP lookup from a non-browser process
9C2 resolution: JSON-RPC eth_call to a Polygon RPC endpoint against a fixed contract address and function selector; contract returns the live C2 URLDnsRequest, proxy POST bodiesQ5 — blockchain RPC from a non-browser process; proxy inspection for the selector
10Encrypted second stages pulled from an attacker-controlled GitHub repository (raw content), decrypted in memoryDnsRequest, proxyQ7 — raw GitHub content fetched by a non-developer process
11Persistence: two daily scheduled tasks masquerading as audio, Office, Security Health or Windows Error Reporting components, staged under %LOCALAPPDATA% / %APPDATA% in a Base64-named directoryScheduledTaskRegistered, ProcessRollup2Q3 — task naming pattern; Q4 — schtasks.exe pointing into AppData
12Host data and screenshot exfiltrated to a bare-IP C2 as multipart/form-data; encrypted tasking returned as JSONNetworkConnectIP4, proxyQ8 — known C2 addresses; proxy rule on bare-IP POST
13Packed StealC PE decrypted from a staged blob and reflectively loaded; browser credentials, cookies, live sessions, extension data, mail and remote-access credentials, screenshots exfiltratedFalcon behavioural / memory detectionsPartial — rely on StealC signatures and credential-access IOAs

Hunt hypotheses (ordered by fidelity)

#HypothesisMITREFalcon eventsExpected FPConf
H1A batch launcher started an unsigned interpreter from a user-writable directory, passing a non-script data file as its only argumentT1204.002, T1059.003, T1036.005ProcessRollup2, SyntheticProcessRollup2Rare. Some game mod loaders and a few legacy installersHigh
H2A Lua runtime component (lua51.dll or a LuaJIT interpreter) was written into Downloads, Temp, AppData or ProgramDataT1105, T1036.005PeFileWritten, NewExecutableWrittenGame clients, Wireshark, Redis modules, some CAD toolsHigh
H3A scheduled task was registered whose name is a benign Windows/Office product name followed by an underscore and a short Base64-looking tokenT1053.005, T1036.004ScheduledTaskRegisteredVery rare. Some vendor updaters append a GUID, not a 3-8 char tokenHigh
H4schtasks.exe /create registered an action pointing at a binary under AppData or ProgramData with a text-extension argumentT1053.005ProcessRollup2Software deployment agents, Teams/Chrome/Edge updatersMedium
H5A non-browser, non-wallet process resolved a public blockchain RPC endpoint (dead-drop resolver)T1102.001, T1568DnsRequest, SuspiciousDnsRequestCrypto wallets, web3 dev tooling, node.exe in blockchain reposMedium
H6A non-browser process performed a geolocation lookup against a public IP-info service shortly after first executionT1614, T1082DnsRequestVPN clients, some telemetry SDKs, licensing checksMedium
H7Raw GitHub content was fetched by a process that is not a browser, package manager or developer toolT1102, T1105DnsRequestHigh in engineering estates. Scoped by process, not by domainMedium
H8An endpoint connected to a documented SmartLoader or StealC bare-IP C2T1071.001, T1041NetworkConnectIP4Effectively none, but the addresses rotateMedium
H9An archive whose name is themed around AI, MCP, Skills or an agent was written to Downloads, Temp or DesktopT1195.001, T1608.001ZipFileWrittenHigh in AI-forward estates. Triage aid, not an alertLow
H10An AI coding agent process spawned a shell that downloaded, cloned or expanded an archive from a code-hosting siteT1195.001, T1105, T1059ProcessRollup2High wherever agents are sanctioned. Baseline firstLow

Gap flagged from the scaffold: steps 7 (native anti-debug shellcode) and 13 (in-memory StealC load) have no reliable process-level telemetry. They are covered only by Falcon behavioural and memory-scan detections, and are marked GAP in the coverage map.

04

Consolidated IOC Table

Read the wave column. The July 2026 AI-Skills wave supplies the ZIP hashes. The April 2026 wave supplies the loader, payload and network infrastructure, which is the same malware family but older infrastructure. Nothing here is a substitute for the behavioural queries in section 8.

Delivery packages — AI Skills / MCP wave (July 2026)

TypeValueContextConfAction
sha25691e5dbfaf45edf25fbc2168f92083e05dfa427afa7633e991392e33cc7427dadawesome-skills-claude-3.3.zip — repo spoofing a widely used Claude Skills collectionHighprevent
sha256c15693106682f2ddb26649cab6e1962a64537627cde4c5d3c79d5a0be8c1b5a8mcp-walmart-2.2.zip — the repo Gemini and ChatGPT both recommended in testingHighprevent
sha25666afc7d87d10dbe392898c4e5c613e0442fabb396415c2bef3a5ef2ac752c5adserver_databricks_mcp_1.6.zip — three-file ZIP: launcher, renamed LuaJIT runtime, disguised Lua payloadHighprevent
sha256216a2c99fd42c00f9323d8b16dd19f622f7f4778b2b1d7cf07a3de5621fd1546yu-ai-agent-1.0-beta.3.zipHighdetect
sha256498fe8fb806cd0e6685f97fc7d74de769dae5a28cdc821557b7585ad5ad83147agent_ai_awesome_skills_2.0.zipHighdetect
sha25662744baa8077bb8be237647fd78e3bea2ca0932bf4be3d5618600f97118095f8for-security-mcp-3.3.zip — lure aimed at security teamsHighdetect
sha2561da8df487d30b988f3c350c065206726aaa13f079a07151cd42ab5579994b9deplugins_claude_awesome_code_2.4.zipHighdetect
sha256a33f40cab1ab7f971d3464af3e7595918107332b9e83342007571842b9e22826mcp-server-jenkins-3.2.zip — build-infrastructure lureHighdetect
sha2563c858facbad66f5479e2c4add171421dc1b6488b36f33e7cff073aba585954a7gateway-docker-mcp-v1.6-alpha.5.zipHighdetect
sha256fc1278f419e611bf40ca414099bfd9ad98a31ffb054371e8cb65a84849b00eafalibabacloud-skills-bigdata-v1.7.zipHighdetect

Loader components and payloads — April 2026 wave

TypeValueContextConfAction
sha256fad3d429172932b72e50f52af169a80439464e3538d97810509090e2e6cdf32aSmartLoader LuaJIT interpreter shipped as loader.exeHighdetect
sha256bff0904456e3151221d29ed1d7c88fc31587efbdfb28817cdcb7ec7f20cade21SmartLoader LuaJIT interpreter shipped as selector.exeHighdetect
sha256bbd438d3d7a59152f1dd5e45bb8d22ee1c07f95cfe42cebbe756aaf4feadc875SmartLoader LuaJIT interpreter shipped as unit.exeHighdetect
sha2563595a6b226ce4daa0a28edea152b3a887c01f6323db1d082f6568c995cdefb55SmartLoader LuaJIT interpreter shipped as luajit.exeHighdetect
sha25609e0f7616dfd2f7eb2876f6ef7331d6dbc78775acd594a94b0397a56717d1fccSmartLoader-bundled lua51.dll runtimeHighdetect
sha256440ceb0dc5911faca54ed9a4dd186dad3d006ae4f52d0bb7d1e4b4edd8c3693aSmartLoader-bundled lua51.dll runtimeHighdetect
sha25687de3e5a8ef669589c421220cd392ae8027a8f8d3cd97d35ac339f87dcff12c8Packed x64 StealC PE recovered from the staged GitHub blob; PE timestamp precedes staging-repo creation by minutesHighdetect

Network and infrastructure

TypeValueContextConfAction
ipv4144.31.57.65SmartLoader C2 returned by the Polygon contract. Last seen 2026-04-12. Rotates.Mediumdetect
ipv4144.31.57.67SmartLoader C2, same hosting range as the aboveMediumdetect
ipv4213.176.73.149StealC C2Mediumdetect
contract0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdcPolygon smart contract used as the dead-drop resolver. Durable across C2 rotation, so higher value than the IPs above.Highhunt
selector0x3bc5de30Contract function selector called to retrieve the C2 string. Hunt in proxy POST bodies.Highhunt
domainpolygon.drpc.orgPublic Polygon RPC endpoint abused for the eth_call. Legitimate service. Alert on the calling process, never on the domain alone.Mediumhunt
urlhttps://raw.githubusercontent.com/deepanshugoel99/long/refs/heads/main/long/long/message1.txtEncrypted second-stage Lua blobHighhunt
urlhttps://raw.githubusercontent.com/deepanshugoel99/long/refs/heads/main/long/long/message2.txtEncrypted StealC PE blobHighhunt
uri-patternPOST /api/<base64_victim_id>Exfiltration endpoint, multipart/form-data with host metadata and screenshotHighhunt
uri-patternPOST /task/<base64_victim_id>Task-completion callback, returns HTTP 204Highhunt
user-agents3klqc1wa6ntg1szvckzi0nt9oumpwy6hhqStatic Lua user agent observed across requests in an independent SmartLoader analysisMediumhunt

Host artefacts (behavioural — these are the durable ones)

TypeValueContextConfAction
task-nameSecurityHealthService_ODE3Persistence task. Confirmed independently by two analyses.Highhunt
task-nameWindowsErrorRecovery_ODE4 · ApplicationExperienceAnalysis_ODE4 · WindowsErrorReporting_ODEw · AudioManager_ODM3 · OfficeClickToRunTask_7d7757Same masquerade family across samples. The stable part is the shape: benign product name, underscore, 3-8 char Base64-looking loader ID.Highhunt
directory%LOCALAPPDATA%\<Base64LoaderId>\ and %APPDATA%\<Base64LoaderId>\Staging directory holding the copied interpreter, lua51.dll and the cached Lua stageHighhunt
filenamelua51.dll · luajit.exe · luau.exe · java.exe · loader.exe · unit.exe · selector.exe · boot.exe · compiler.exe · load.exe · util.exeRenamed LuaJIT interpreters and the Lua runtime DLL. Unsigned, no version metadata, GUI subsystem.Mediumhunt
filenameLauncher.cmd · Launcher.bat · Application.cmd · Application.bat · App.bat · Launch.bat · ErrorHandler.cmd · application.cmdOne-line launchers containing start <exe> <payload>Mediumhunt
filenamemodule.class · import.ui · ico64.txt · conf.txt · proto.txt · package.txt · buff.log · session.lua · debug.luaPrometheus-obfuscated single-line Lua payloads, roughly 296-309 KB, disguised with benign extensionsMediumhunt
05

Affected Surface & Telemetry Matrix

SurfaceWhy it is exposedRequired telemetryPriorityGap risk
Windows developer and analyst workstationsPrimary execution target. The ZIP is a Windows package and the whole chain is Win32.Falcon sensor: ProcessRollup2, PeFileWritten, ScheduledTaskRegistered, DnsRequest, NetworkConnectIP4CriticalLow — standard sensor coverage
AI coding agents and their host processes (CLI agents, IDE extensions, MCP clients)AgentBaiting makes the agent the discovery and recommendation layer. Agent-initiated downloads inherit the user's session.ProcessRollup2 parentage, agent CLI transcripts, shell historyCriticalHigh — agent transcripts are rarely centralised, and parentage alone does not show intent
MCP server / Skill configuration directoriesA malicious capability is installed by writing config, not by installing a package. There is no package manager to audit.File-integrity monitoring on agent config paths; source control on the config repoHighHigh — Falcon does not emit file-write telemetry for arbitrary JSON/YAML by default
Browser session and token storesStealC's actual objective. Cookies, live sessions, extension data.Falcon credential-access IOAs; IdP sign-in logs for impossible-travel after infectionCriticalMedium — theft itself is quiet; detect via downstream session reuse
Web proxy / egressBlockchain RPC, raw GitHub content and bare-IP POST all traverse it.Proxy logs with URL path, method and user agent; TLS inspection for the eth_call bodyHighMedium — without TLS inspection the contract selector is invisible
Software inventory / AI capability registerYou cannot match newly published campaign repositories against your estate without knowing what is installed.Inventory of Skill/MCP source repo, commit, version, package hashHighHigh — almost nobody has this yet
macOS / Linux developer machinesObserved packages are Windows-only, but the lure and the registry listings are cross-platform.Process telemetry for the same discovery-to-download pathLowLow — no non-Windows payload documented in the cited research
06

ATT&CK Mapping

TacticTechniqueObserved behaviourQuery or control
Resource DevelopmentT1608.001 — Stage Capabilities: Upload Malware~7,600 repositories host malicious ZIPs in Releases or in the treeExternal; hardening H-S1 (curated catalog)
Resource DevelopmentT1585.001 — Establish Accounts: Social Media / Developer Accounts~6,600 profiles, several a single character off a real developer's handleHardening H-I3 (verify publisher, not project)
Initial AccessT1195.001 — Supply Chain Compromise: Software Dependencies and Development ToolsPoisoned AI Skill / MCP capability supply chain, amplified by registry listingsQ9, Q10; hardening H-I1
ExecutionT1204.002 — User Execution: Malicious FileUser or agent-guided operator runs the extracted launcherQ1
ExecutionT1059.003 — Command and Scripting Interpreter: Windows Command ShellOne-line .cmd/.bat containing start <exe> <payload>Q1, Q4
ExecutionT1059 — Command and Scripting Interpreter (Lua via LuaJIT)Prometheus-obfuscated Lua executed by a renamed LuaJIT interpreter using FFI to reach Win32 directlyQ1, Q2; IOA-1
PersistenceT1053.005 — Scheduled Task/Job: Scheduled TaskTwo daily tasks with independent recovery paths (cached local stage, and re-download from GitHub)Q3, Q4
Defense EvasionT1036.005 — Masquerading: Match Legitimate Name or LocationLuaJIT renamed to java.exe, luau.exe, compiler.exe; payload given a .txt/.class/.ui extensionQ1, Q2
Defense EvasionT1036.004 — Masquerade Task or ServiceTask names imitating Security Health, Windows Error Reporting, Office Click-to-Run, audio managersQ3
Defense EvasionT1564.003 — Hide Artifacts: Hidden WindowGUI-subsystem interpreter plus GetConsoleWindow and ShowWindow(SW_HIDE) via FFIBehavioural only — no direct query
Defense EvasionT1027 / T1140 — Obfuscated Files, Deobfuscate/DecodeSingle-line ~300 KB Prometheus-obfuscated Lua; encrypted GitHub-staged blobs decrypted in memoryFile-size heuristic in native hunts
Defense EvasionT1622 — Debugger EvasionAnti-debug check via native shellcode copied into executable memoryGAP
Defense EvasionT1620 — Reflective Code LoadingPE parsing structures plus thread-creation primitives used to load StealC without touching diskGAP — memory-scan detections only
DiscoveryT1082 / T1614 — System Information and Location DiscoveryHost fingerprint JSON; geolocation lookup against a public IP-info serviceQ6
CollectionT1113 — Screen CaptureDesktop screenshot captured through the GDI pipeline and uploaded with the fingerprintCovered indirectly via Q8 exfil traffic
Command and ControlT1102.001 — Web Service: Dead Drop ResolverJSON-RPC eth_call to a Polygon RPC endpoint against a fixed contract and selector returning the live C2Q5
Command and ControlT1102 / T1105 — Web Service, Ingress Tool TransferEncrypted second-stage Lua and StealC PE pulled from raw GitHub contentQ7
Command and ControlT1071.001 — Application Layer Protocol: Web ProtocolsHTTP POST to a bare-IP C2 with multipart/form-dataQ8
Credential AccessT1555.003 — Credentials from Web BrowsersStealC harvests browser passwords, mail and remote-access credentialsFalcon credential-access IOAs
Credential AccessT1539 — Steal Web Session CookieLive sessions and extension data taken, which is why password resets alone do not contain itIdP session revocation (containment phase 2)
ExfiltrationT1041 — Exfiltration Over C2 ChannelScreenshot and fingerprint uploaded to /api/<base64_victim_id>Q8; proxy rule
07

Native Audit-Log Hunts (non-CQL)

Run these where Falcon telemetry is thin: agent configuration files, scheduled-task inventory, and the AI capability register.

N1 — Enumerate scheduled tasks matching the SmartLoader masquerade shape

Any task whose name is a benign product name followed by an underscore and a short alphanumeric token, whose action lives under a user-writable directory.

Get-ScheduledTask | ForEach-Object {
  $a = ($_.Actions | Where-Object { $_.Execute }) 
  foreach ($act in $a) {
    if ($act.Execute -match '(?i)\\(AppData|ProgramData)\\' -and
        $_.TaskName -match '^[A-Za-z]+_[A-Za-z0-9]{3,8}$') {
      [pscustomobject]@{
        Task = $_.TaskName
        Path = $_.TaskPath
        Exec = $act.Execute
        Args = $act.Arguments
        Author = $_.Author
      }
    }
  }
} | Format-Table -AutoSize

N2 — Find staged Lua runtime components under user profiles

$roots = @($env:LOCALAPPDATA, $env:APPDATA, "$env:USERPROFILE\Downloads", $env:TEMP)
Get-ChildItem -Path $roots -Recurse -Force -ErrorAction SilentlyContinue `
  -Include 'lua51.dll','luajit.exe','luau.exe' |
  Select-Object FullName, Length, CreationTime,
    @{n='Signed';e={ (Get-AuthenticodeSignature $_.FullName).Status }} |
  Format-Table -AutoSize

N3 — Find single-line Lua payloads disguised with benign extensions

The payloads are 296-309 KB and are one single line. Legitimate .txt, .log and .ico files of that size are essentially never one line.

$roots = @($env:LOCALAPPDATA, $env:APPDATA, "$env:USERPROFILE\Downloads", $env:TEMP)
Get-ChildItem -Path $roots -Recurse -Force -File -ErrorAction SilentlyContinue `
  -Include '*.txt','*.log','*.ico','*.license','*.class','*.ui','*.dat' |
  Where-Object { $_.Length -gt 200KB -and $_.Length -lt 600KB } |
  ForEach-Object {
    $lines = 0
    try { $lines = (Get-Content -LiteralPath $_.FullName -TotalCount 3 -ErrorAction Stop).Count } catch {}
    if ($lines -le 1) { [pscustomobject]@{ File=$_.FullName; KB=[int]($_.Length/1KB); Created=$_.CreationTime } }
  } | Format-Table -AutoSize

N4 — Inventory installed MCP servers and Agent Skills

There is no package manager here, so the config files are the inventory. Diff this output against a reviewed catalog and treat anything unrecognised as unvetted until proven otherwise.

$paths = @(
  "$env:USERPROFILE\.claude",
  "$env:USERPROFILE\.cursor",
  "$env:USERPROFILE\.codex",
  "$env:APPDATA\Claude",
  "$env:APPDATA\Code\User"
)
Get-ChildItem -Path $paths -Recurse -Force -File -ErrorAction SilentlyContinue `
  -Include 'mcp.json','*mcp*.json','settings.json','SKILL.md' |
  Select-Object FullName, Length, LastWriteTime |
  Sort-Object LastWriteTime -Descending | Format-Table -AutoSize

# then review every server command and every skill source for an .exe / .zip install step
Get-ChildItem -Path $paths -Recurse -Force -File -Filter '*.json' -ErrorAction SilentlyContinue |
  Select-String -Pattern 'releases/download|\.zip|\.exe|Invoke-WebRequest|curl ' |
  Select-Object Path, LineNumber, Line

N5 — Proxy / web gateway queries

  • Dead-drop resolver: HTTP POST to any *.drpc.org or public Ethereum/Polygon JSON-RPC host from a user agent that is not a browser. With TLS inspection, match request bodies containing eth_call together with the contract address 0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdc or selector 0x3bc5de30. This is the single highest-fidelity network signal in the chain.
  • Static Lua user agent: match the literal user-agent string s3klqc1wa6ntg1szvckzi0nt9oumpwy6hhq. Cheap to add, zero legitimate use.
  • Bare-IP POST: POST requests whose Host header is a raw IPv4 address with a URI matching /api/ or /task/ followed by a Base64 token, content type multipart/form-data.
  • Registry-to-download pivot: a session that visits an MCP or Skill registry domain and then downloads a .zip from a GitHub release within the same hour, from a host with no prior GitHub release-download history.

N6 — Identity-side follow-up

  • For any host with a confirmed or suspected hit, pull IdP sign-ins for that user over the following 30 days and look for session reuse from a new ASN or a new device fingerprint with no fresh MFA interaction. StealC steals cookies, so the attacker arrives already authenticated.
  • Review OAuth grants and personal access tokens created or last-used after the suspected execution time, especially source-control, cloud and secrets-manager scopes.
08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.

None of these queries carries an in-query time filter. Set the window with the console time picker; the intended lookback is recorded as a // LOOKBACK: comment in each card. The AI-Skills wave peaked in April 2026, so a 120-day retrospective sweep is more useful than a 7-day one for Q1 to Q4.

Q1 · Batch launcher starts an interpreter with a data-file argument (core SmartLoader chain)
CONF HIGHFP LOWCOST LOW

Looks for: the one structural fact the whole campaign depends on. A .cmd/.bat launcher runs start <exe> <payload>, so Falcon sees a cmd.exe parent, a child executable sitting in a user-writable path, and a command line whose final token has a non-executable data extension. Legitimate installers do not look like this. FP: a handful of game mod loaders and legacy self-extracting tools; exclude by hashing the child and allowlisting the known-good ones.

// HUNT: SmartLoader launcher chain -- cmd.exe starts a renamed LuaJIT interpreter with a disguised Lua payload
// MITRE: T1204.002 | T1059.003 | T1036.005 | CONF: high  FP: low  COST: low
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows)
// LOOKBACK: 120d -- the AI-themed wave peaked April 2026
// TUNING: allowlist by SHA256HashData once you have baselined the handful of legitimate
// TUNING: interpreter-plus-data-file launchers in your estate (game mod loaders, legacy SFX tools)
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| ParentBaseFileName=/^cmd\.exe$/i
| CommandLine=/\.(txt|log|ico|license|class|ui|dat|cfg|bin)\s*$/i
| ImageFileName=/\\(Users|ProgramData)\\/i
| FileName!=/^(cmd|powershell|pwsh|conhost|reg|findstr|timeout|xcopy|robocopy|attrib|net|net1|tasklist|where|more|type)\.exe$/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, ImageFileName, CommandLine, SHA256HashData])
Q2 · Lua runtime staged into a user-writable directory
CONF HIGHFP MEDCOST LOW

Looks for: lua51.dll or a LuaJIT interpreter written into Downloads, Temp, AppData or ProgramData. Both the initial ZIP extraction and the persistence copy pass through here, so this fires twice per infection. FP: game clients, Wireshark, Redis modules and some CAD suites bundle Lua; those install under Program Files, which this query already excludes, but portable copies in Downloads will hit.

// HUNT: LuaJIT runtime or interpreter dropped into a user-writable staging path
// MITRE: T1105 | T1036.005 | CONF: high  FP: medium  COST: low
// REQUIRES: PeFileWritten / NewExecutableWritten
// LOOKBACK: 120d
// TUNING: exclude ContextBaseFileName for sanctioned game launchers and installers
// TUNING: (steam.exe, wireshark installers, vendor setup binaries) after baselining one week
#event_simpleName=/^(PeFileWritten|NewExecutableWritten)$/
| TargetFileName=/\\(AppData|ProgramData|Downloads|Temp)\\/i
| TargetFileName=/\\(lua51\.dll|luajit\.exe|luau\.exe|lua\.exe|lua5[0-9]*\.dll)$/i
| table([@timestamp, ComputerName, UserName, ContextBaseFileName, TargetFileName, SHA256HashData])
Q3 · Scheduled task masquerading as a Windows or Office component with a Base64 loader suffix
CONF HIGHFP LOWCOST LOW

Looks for: the persistence naming convention. Four independent analyses of this loader family recorded task names of the form <BenignProductName>_<3-8 char Base64 loader id>. The first alternation matches the exact families observed; the second, broader clause catches renamed variants. FP: essentially none in the first clause. Genuine Microsoft tasks do not carry a short underscore suffix.

// HUNT: SmartLoader persistence -- scheduled task masquerading as a Microsoft component
// MITRE: T1053.005 | T1036.004 | CONF: high  FP: low  COST: low
// REQUIRES: ScheduledTaskRegistered
// LOOKBACK: 120d
// FALSE POSITIVES: none observed for the named clause; a few vendor updaters append a full GUID
// FALSE POSITIVES: rather than a 3-8 char token, which the length bound already excludes
#event_simpleName=/^ScheduledTaskRegistered$/
| TaskName=/(SecurityHealthService|SecurityHealthSystray|WindowsErrorRecovery|WindowsErrorReporting|ApplicationExperienceAnalysis|AudioManager|AudioSrv|OfficeClickToRunTask|OfficeTelemetry|MicrosoftEdgeUpdate)_[A-Za-z0-9+=]{3,8}$/i
| table([@timestamp, ComputerName, UserName, TaskName, TaskAuthor])
Q4 · schtasks.exe registering an action under AppData with a text-extension argument
CONF HIGHFP MEDCOST LOW

Looks for: the same persistence event from the process side, which catches variants whose task name does not match Q3's list. The discriminator is the combination of a user-writable action path and a data-file argument. FP: software deployment agents and browser updaters register AppData tasks routinely; the text-extension clause removes almost all of them, and the parent-process exclusion removes the rest.

// HUNT: schtasks.exe creating persistence pointing at a user-writable interpreter + data payload
// MITRE: T1053.005 | CONF: high  FP: medium  COST: low
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2
// LOOKBACK: 120d
// TUNING: exclude ParentBaseFileName for your deployment stack (ccmexec.exe, IntuneManagementExtension.exe,
// TUNING: msiexec.exe, setup.exe) and for signed browser updaters before promoting this to an alert
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| FileName=/^schtasks\.exe$/i
| CommandLine=/\/create/i
| CommandLine=/(AppData\\Local|AppData\\Roaming|ProgramData)/i
| CommandLine=/\.(txt|log|lua|class|ui|ico|dat)/i
| ParentBaseFileName!=/^(ccmexec|IntuneManagementExtension|msiexec|setup|GoogleUpdate|MicrosoftEdgeUpdate)\.exe$/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Q5 · Blockchain dead-drop resolver — RPC endpoint resolved by a non-browser process
CONF HIGHFP MEDCOST LOW

Looks for: SmartLoader's C2 resolution. It does not hardcode a C2; it calls a Polygon smart contract through a public JSON-RPC provider and reads the returned string. That call is the durable indicator because the operator rotates the C2 by editing one on-chain value, not by rebuilding the loader. FP: crypto wallets, MetaMask helper processes, hardhat/foundry and any node.exe running a web3 project. Exclude by process, not by domain.

// HUNT: dead-drop resolver -- public blockchain RPC resolved by a process that is not a browser or wallet
// MITRE: T1102.001 | T1568 | CONF: high  FP: medium  COST: low
// REQUIRES: DnsRequest / SuspiciousDnsRequest
// LOOKBACK: 120d
// TUNING: exclude ContextBaseFileName for sanctioned wallet and web3 tooling (node.exe on dev
// TUNING: subnets, MetaMask host processes, hardhat, foundry, geth). Do NOT allowlist the domain itself.
#event_simpleName=/^(DnsRequest|SuspiciousDnsRequest)$/
| DomainName=/(^|\.)(drpc\.org|polygon-rpc\.com|llamarpc\.com|ankr\.com|infura\.io|alchemy\.com|quiknode\.pro|blastapi\.io|publicnode\.com)$/i
| ContextBaseFileName!=/^(chrome|msedge|firefox|brave|opera|iexplore|safari|node|geth)\.exe$/i
| groupBy([ComputerName, ContextBaseFileName, DomainName], function=count(as=Lookups))
| sort(Lookups, order=desc)
Q6 · Geolocation fingerprint from a non-browser process
CONF MEDFP MEDCOST LOW

Looks for: the host-profiling step. Two independent analyses of this loader recorded an ip-api.com lookup early in execution. On its own it is weak; correlated with a Q1 or Q3 hit on the same host it is strong. FP: VPN clients, licensing checks and some telemetry SDKs use the same services. Treat a single lookup as enrichment and only escalate when the calling process also appears in another query.

// HUNT: SmartLoader host fingerprinting -- public geo-IP service queried by a non-browser process
// MITRE: T1614 | T1082 | CONF: medium  FP: medium  COST: low
// REQUIRES: DnsRequest / SuspiciousDnsRequest
// LOOKBACK: 30d
// TUNING: exclude your VPN client, EDR/telemetry agents and licensing services by ContextBaseFileName;
// TUNING: use this as a correlation signal against Q1/Q3 hits rather than a standalone alert
#event_simpleName=/^(DnsRequest|SuspiciousDnsRequest)$/
| DomainName=/^(ip-api\.com|api\.ipify\.org|ipinfo\.io|icanhazip\.com|ifconfig\.me|ipwho\.is|checkip\.amazonaws\.com)$/i
| ContextBaseFileName!=/^(chrome|msedge|firefox|brave|opera|iexplore|svchost|teams|slack)\.exe$/i
| groupBy([ComputerName, ContextBaseFileName, DomainName], function=count(as=Lookups))
| sort(Lookups, order=desc)
Q7 · Raw GitHub content fetched by a process that is not a developer tool
CONF MEDFP HIGHCOST MED

Looks for: the second-stage staging fetch. SmartLoader re-downloads an encrypted Lua blob from an attacker repository on every persistence run, which is what makes the infection survive deletion of the cached stage. FP: high in any engineering estate. This is a triage aid scoped by process, not a standalone alert. Rank by rarity of the calling process on the host, and prioritise processes running from AppData.

// HUNT: SmartLoader second-stage staging -- raw GitHub content pulled by a non-developer process
// MITRE: T1102 | T1105 | CONF: medium  FP: high  COST: medium
// REQUIRES: DnsRequest / SuspiciousDnsRequest
// LOOKBACK: 30d
// TUNING: exclude your full developer toolchain by ContextBaseFileName (git, node, python, pip, go,
// TUNING: code, devenv, curl, wget, gh) and every browser; then rank surviving processes by rarity
// TUNING: per host. A process seen on one host in the estate is the one worth opening.
#event_simpleName=/^(DnsRequest|SuspiciousDnsRequest)$/
| DomainName=/^(raw\.githubusercontent\.com|objects\.githubusercontent\.com|gist\.githubusercontent\.com)$/i
| ContextBaseFileName!=/^(git|git-remote-https|gh|code|devenv|node|npm|yarn|python|python3|pip|go|curl|wget|msedge|chrome|firefox|brave|dotnet|java)\.exe$/i
| groupBy([ComputerName, ContextBaseFileName], function=count(as=Fetches))
| sort(Fetches, order=desc)
Q8 · Connection to a documented SmartLoader or StealC C2
CONF MEDFP LOWCOST LOW

Looks for: the three bare-IP C2 addresses recovered during reverse engineering of this loader family. Confidence is rated medium not because the attribution is weak but because the addresses are last-seen 2026-04-12 and the operator rotates them from the smart contract. Run it as a retrospective sweep, keep Q5 as the forward-looking control.

// HUNT: known SmartLoader / StealC bare-IP C2 (historical -- rotates via the Polygon contract)
// MITRE: T1071.001 | T1041 | CONF: medium  FP: low  COST: low
// REQUIRES: NetworkConnectIP4
// LOOKBACK: 120d retrospective sweep
#event_simpleName=/^NetworkConnectIP4$/
| in(RemoteAddressIP4, values=["144.31.57.65", "144.31.57.67", "213.176.73.149"])
| table([@timestamp, ComputerName, UserName, ContextBaseFileName, RemoteAddressIP4, RemotePort])
Q9 · AI / MCP / Skill-themed archive written to a user directory
CONF MEDFP HIGHCOST LOW

Looks for: the delivery artefact itself. Campaign ZIP names follow the repository's lure, so they carry AI, MCP, Skill, agent or vendor-integration wording. FP: high wherever AI tooling is genuinely in use. Use it to build the target list for the N3 single-line-payload sweep, and to hash every hit against section 10's CSV, not as an alert.

// HUNT: AgentBaiting delivery -- AI/MCP/Skill-themed archive dropped into a user-writable directory
// MITRE: T1195.001 | T1608.001 | CONF: medium  FP: high  COST: low
// REQUIRES: ZipFileWritten
// LOOKBACK: 120d
// TUNING: this is a triage feed, not an alert. Hash every hit against the section 10 CSV first,
// TUNING: then exclude ContextBaseFileName for your sanctioned package managers and IDEs.
#event_simpleName=/^ZipFileWritten$/
| TargetFileName=/\\(Downloads|Temp|Desktop|AppData)\\/i
| TargetFileName=/(mcp|skill|claude|agent|copilot|gemini|chatgpt|openai|llm|ai)[-_]/i
| table([@timestamp, ComputerName, UserName, ContextBaseFileName, TargetFileName, SHA256HashData])
Q10 · AI coding agent spawning a shell that downloads, clones or expands an archive
CONF MEDFP HIGHCOST MED

Looks for: the AgentBaiting step directly. When an agent surfaces a campaign repository and the operator accepts, the retrieval usually runs as a child of the agent process rather than as a browser download, so it never passes through any browser-download control you have. FP: high wherever agents are sanctioned, because this is also what legitimate agent work looks like. Baseline for a week first, then alert only on retrievals whose target host or repository is outside your approved catalog.

// HUNT: AgentBaiting -- coding-agent process spawns a shell that retrieves or expands remote content
// MITRE: T1195.001 | T1105 | T1059 | CONF: medium  FP: high  COST: medium
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2
// LOOKBACK: 30d
// TUNING: baseline one week before alerting. Then keep only retrievals whose target is outside the
// TUNING: approved capability catalog, and always keep any hit whose target is a releases/download URL
// TUNING: -- a legitimate MCP server or Skill is source plus a manifest, never a downloaded Windows binary.
#event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/
| ParentBaseFileName=/^(node|claude|cursor|code|windsurf|codex|gemini|copilot|aider|continue|python|python3)\.exe$/i
| FileName=/^(cmd|powershell|pwsh|curl|tar|expand|git)\.exe$/i
| CommandLine=/(Invoke-WebRequest|Invoke-RestMethod|Start-BitsTransfer|Expand-Archive|releases\/download|git\s+clone|curl\s+-|tar\s+-x)/i
| table([@timestamp, ComputerName, UserName, GrandparentBaseFileName, ParentBaseFileName, FileName, CommandLine])
09

CrowdStrike Custom IOA Recommendations

Three of the ten queries are strong enough to promote to Custom IOAs. The rest stay hunt/investigate-only because their false-positive profile depends on estate-specific baselining.

IOA-1 — Interpreter launched from a shell with a data-file argument Promote

FieldValue
Rule groupProcess Creation (Windows)
ActionDetect · Severity High (start at Monitor for 7 days, then raise)
Parent image.*\\cmd\.exe
Image filename.*\\(Users|ProgramData)\\.*\.exe
Command line.*\.(txt|log|ico|license|class|ui|dat|cfg|bin)\s*$
ExclusionsSHA-256 allowlist built from the Q1 baseline; sanctioned game-mod launchers
Why it holdsThe operator can rename the interpreter and change the payload extension, but not remove the shell-parent plus data-file-argument shape without rewriting the launcher model that every observed variant shares.

IOA-2 — Scheduled task masquerading as a Microsoft component Promote

FieldValue
Rule groupProcess Creation (Windows) — schtasks.exe
ActionDetect · Severity High
Image filename.*\\schtasks\.exe
Command line(?i).*/create.*(AppData\\(Local|Roaming)|ProgramData).*\.(txt|log|lua|class|ui|ico|dat).*
ExclusionsParent image matching your deployment stack and signed browser updaters
Why it holdsBoth persistence paths register a task whose action is an interpreter under AppData taking a text-extension argument. Renaming the task does not change that.

IOA-3 — Lua runtime written to a user-writable path Promote after baseline

FieldValue
Rule groupFile Creation (Windows)
ActionMonitor first · raise to Detect · Severity Medium once the estate baseline is clean
Target filename.*\\(AppData|ProgramData|Downloads|Temp)\\.*\\(lua51\.dll|luajit\.exe|luau\.exe)
ExclusionsSanctioned game clients and network-analysis tooling by writing-process image
Why it holdsEvery documented variant ships the Lua runtime with the payload; the three-file variants link it statically but still drop the interpreter itself.

Hunt / investigate-only (do not promote)

  • Q5, Q6, Q7 — DNS-based. Their FP profile is entirely determined by which developer and wallet tooling you sanction. Run as scheduled searches feeding a triage queue, not as IOAs.
  • Q8 — atomic and perishable. Ship the addresses through IOC Management (section 10) instead, where they can expire.
  • Q9, Q10 — high FP by design. These are the AgentBaiting visibility layer; their value is inventory and triage, not alerting.

Falcon prevention policy adjuncts

  • Enable Suspicious Process Blocking and Script-Based Execution Monitoring in the assigned prevention policy for developer workstations. The Lua stage is not a script Falcon parses, but the shell launcher is.
  • Add the section 10 CSV to IOC Management. The three double-sourced ZIP hashes are proposed at prevent; everything else at detect so it enriches rather than blocks.
10

Machine-Readable IOC Appendix

Falcon IOC Management CSVbulk import
type,value,action,severity,expiration,description,tags
sha256,91e5dbfaf45edf25fbc2168f92083e05dfa427afa7633e991392e33cc7427dad,prevent,high,2027-01-28,SmartLoader package awesome-skills-claude-3.3.zip,campaign:AgentBaiting
sha256,c15693106682f2ddb26649cab6e1962a64537627cde4c5d3c79d5a0be8c1b5a8,prevent,high,2027-01-28,SmartLoader package mcp-walmart-2.2.zip,campaign:AgentBaiting
sha256,66afc7d87d10dbe392898c4e5c613e0442fabb396415c2bef3a5ef2ac752c5ad,prevent,high,2027-01-28,SmartLoader package server_databricks_mcp_1.6.zip,campaign:AgentBaiting
sha256,216a2c99fd42c00f9323d8b16dd19f622f7f4778b2b1d7cf07a3de5621fd1546,detect,high,2027-01-28,SmartLoader package yu-ai-agent-1.0-beta.3.zip,campaign:AgentBaiting
sha256,498fe8fb806cd0e6685f97fc7d74de769dae5a28cdc821557b7585ad5ad83147,detect,high,2027-01-28,SmartLoader package agent_ai_awesome_skills_2.0.zip,campaign:AgentBaiting
sha256,62744baa8077bb8be237647fd78e3bea2ca0932bf4be3d5618600f97118095f8,detect,high,2027-01-28,SmartLoader package for-security-mcp-3.3.zip,campaign:AgentBaiting
sha256,1da8df487d30b988f3c350c065206726aaa13f079a07151cd42ab5579994b9de,detect,high,2027-01-28,SmartLoader package plugins_claude_awesome_code_2.4.zip,campaign:AgentBaiting
sha256,a33f40cab1ab7f971d3464af3e7595918107332b9e83342007571842b9e22826,detect,high,2027-01-28,SmartLoader package mcp-server-jenkins-3.2.zip,campaign:AgentBaiting
sha256,3c858facbad66f5479e2c4add171421dc1b6488b36f33e7cff073aba585954a7,detect,high,2027-01-28,SmartLoader package gateway-docker-mcp-v1.6-alpha.5.zip,campaign:AgentBaiting
sha256,fc1278f419e611bf40ca414099bfd9ad98a31ffb054371e8cb65a84849b00eaf,detect,high,2027-01-28,SmartLoader package alibabacloud-skills-bigdata-v1.7.zip,campaign:AgentBaiting
sha256,fad3d429172932b72e50f52af169a80439464e3538d97810509090e2e6cdf32a,detect,high,2027-01-28,SmartLoader LuaJIT interpreter loader.exe,campaign:FakeGit
sha256,bff0904456e3151221d29ed1d7c88fc31587efbdfb28817cdcb7ec7f20cade21,detect,high,2027-01-28,SmartLoader LuaJIT interpreter selector.exe,campaign:FakeGit
sha256,bbd438d3d7a59152f1dd5e45bb8d22ee1c07f95cfe42cebbe756aaf4feadc875,detect,high,2027-01-28,SmartLoader LuaJIT interpreter unit.exe,campaign:FakeGit
sha256,3595a6b226ce4daa0a28edea152b3a887c01f6323db1d082f6568c995cdefb55,detect,high,2027-01-28,SmartLoader LuaJIT interpreter luajit.exe,campaign:FakeGit
sha256,09e0f7616dfd2f7eb2876f6ef7331d6dbc78775acd594a94b0397a56717d1fcc,detect,high,2027-01-28,SmartLoader bundled lua51.dll runtime,campaign:FakeGit
sha256,440ceb0dc5911faca54ed9a4dd186dad3d006ae4f52d0bb7d1e4b4edd8c3693a,detect,high,2027-01-28,SmartLoader bundled lua51.dll runtime,campaign:FakeGit
sha256,87de3e5a8ef669589c421220cd392ae8027a8f8d3cd97d35ac339f87dcff12c8,detect,high,2027-01-28,StealC packed PE staged from GitHub,campaign:FakeGit
ipv4,144.31.57.65,detect,high,2026-10-28,SmartLoader C2 last seen 2026-04-12 rotates via Polygon contract,campaign:FakeGit
ipv4,144.31.57.67,detect,high,2026-10-28,SmartLoader C2 last seen 2026-04-12 rotates via Polygon contract,campaign:FakeGit
ipv4,213.176.73.149,detect,high,2026-10-28,StealC C2 last seen 2026-04-12,campaign:FakeGit
ipv4,REPLACE_WITH_CURRENT_C2_FROM_CONTRACT_QUERY,detect,high,2026-10-28,live C2 read from the Polygon dead-drop contract at triage time,campaign:FakeGit
Behavioral Signaturesdurable — survives rotation
# Execution
parent=cmd.exe AND child=*.exe under \Users\ or \ProgramData\ AND cmdline ends .txt|.log|.ico|.license|.class|.ui|.dat
unsigned GUI-subsystem PE64 with no version metadata, sitting beside lua51.dll
single-line file 296-309 KB with a .txt / .log / .ico / .class / .ui extension

# Persistence
scheduled task named <BenignProductName>_<3-8 char base64 id>
two daily tasks registered within minutes of each other on one host
task action under %LOCALAPPDATA%\ or %APPDATA%\<base64 id>\

# Command and control
JSON-RPC eth_call to a public Polygon/Ethereum RPC host from a non-browser, non-wallet process
HTTP POST to a bare IPv4 host, URI /api/<base64> or /task/<base64>, multipart/form-data
static user agent s3klqc1wa6ntg1szvckzi0nt9oumpwy6hhq
raw.githubusercontent.com fetch by a process running from %APPDATA% or %LOCALAPPDATA%

# Collection artefacts
cached task file in the user's Pictures folder named after the machine GUID
session.lua or debug.lua written to %TEMP%
Named Tooling & Infrastructurepivot / enrich
# Malware
SmartLoader          LuaJIT-based loader, Prometheus-obfuscated Lua stage
StealC               infostealer final payload (browser creds, cookies, sessions, extensions, screenshots)
Prometheus           Lua obfuscator used on the payload

# Dead-drop resolver (durable across C2 rotation)
polygon.drpc.org                                    public RPC endpoint abused for the eth_call
0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdc          resolver contract address
0x3bc5de30                                          function selector returning the C2 string

# Second-stage staging
https://raw.githubusercontent.com/deepanshugoel99/long/refs/heads/main/long/long/message1.txt
https://raw.githubusercontent.com/deepanshugoel99/long/refs/heads/main/long/long/message2.txt

# Persistence task names observed across samples
SecurityHealthService_ODE3   WindowsErrorRecovery_ODE4   ApplicationExperienceAnalysis_ODE4
WindowsErrorReporting_ODEw   AudioManager_ODM3           OfficeClickToRunTask_7d7757

# Renamed LuaJIT interpreters observed
luau.exe  java.exe  luajit.exe  lua.exe  loader.exe  unit.exe  selector.exe  boot.exe  compiler.exe  load.exe  util.exe

# Launcher scripts observed
Launcher.cmd  Launcher.bat  Application.cmd  Application.bat  App.bat  Launch.bat  ErrorHandler.cmd  application.cmd

# Disguised Lua payloads observed
module.class  import.ui  ico64.txt  conf.txt  proto.txt  func.txt  package.txt  dynasm.txt  buff.log  static.txt  uix.txt  x64.txt  tree.txt
AI Capability Inventory Auditrun this first
# For every MCP server and Agent Skill installed in the last 120 days, record and review:
#   source repository URL, owner handle, commit SHA, version, package SHA-256
#
# Reject on sight, no exceptions:
#   - install step that downloads a .zip or .exe from a Releases page
#   - README that says to click "More info" then "Run anyway" past SmartScreen
#   - package containing a .cmd/.bat launcher plus an interpreter binary
#   - no manifest, no source, only a Windows archive
#
# Verify the publisher, not the project:
#   - compare the owner handle character by character against the upstream project owner
#   - check account age, other repositories, and whether the profile mirrors a real developer
#   - a registry listing (LobeHub, Glama, MCP.so, MCP Market) is NOT a signal of legitimacy;
#     those listings reproduce the attacker's own README
#
# Cross-reference every recorded package hash against the CSV block in this pack.

Placeholder note: the live C2 row ships as REPLACE_WITH_CURRENT_C2_FROM_CONTRACT_QUERY on purpose. The current address exists only as a value inside the Polygon contract and changes whenever the operator updates it. Read it at triage time rather than shipping a guess.

11

Detection Validation Gates

GateCheckPass criteria
1 · Telemetry readyConfirm ProcessRollup2, PeFileWritten, ZipFileWritten, ScheduledTaskRegistered, DnsRequest and NetworkConnectIP4 are all present for the developer-workstation host group over the last 24 hoursAll six event types return rows. If ZipFileWritten or ScheduledTaskRegistered is empty, Q3, Q4 and Q9 are blind and must be marked as such in the coverage map before the hunt is called complete.
2 · Benign baselineRun Q1, Q2, Q3 and Q5 across a 30-day window before promoting anythingQ1 and Q3 should return single-digit results in a typical estate. If Q1 returns hundreds, an interpreter-plus-data-file pattern is in legitimate use and must be allowlisted by hash before IOA-1 is enabled.
3 · Positive test — execution chainOn an isolated test host, create a directory containing a renamed copy of a benign LuaJIT interpreter and a .txt file, plus a one-line .cmd running start interp.exe payload.txt. Execute the .cmd.Q1 returns the event within the normal ingest delay. This validates the parent/child/extension logic without any malicious code.
4 · Positive test — persistenceOn the same test host, register a scheduled task named SecurityHealthService_TEST01 whose action is a binary under %LOCALAPPDATA% with a .txt argumentQ3 and Q4 both return the event. Remove the task afterwards.
5 · Positive test — resolverFrom a non-browser process on the test host, resolve a public Polygon RPC hostnameQ5 returns the lookup and correctly attributes it to the calling process.
6 · Tuning appliedEvery query rated FP medium or higher carries a // TUNING: or // FALSE POSITIVES: line inside the query block, and the exclusion has been populated with real values from your estateQ2, Q4, Q5, Q6, Q7, Q9, Q10 all have estate-specific exclusions filled in, not just the shipped placeholders.
7 · PromotionIOA-1 and IOA-2 run in Monitor mode for 7 days with zero unexplained hits before being raised to DetectZero unresolved detections across the monitoring window; every hit either confirmed malicious or added to the exclusion list with a written justification.
8 · ProvenanceEvery atomic indicator shipped in section 10 traces to a saved source snapshotcheck_ioc_provenance.py exits 0 against AgentBaiting-SmartLoader-Hunt-sources/.
12

Hardening — Tiered

This campaign never exploits anything. It publishes convincing repositories and waits for discovery to do the work, so the controls that matter are the ones that break the discovery-to-execution path rather than the ones that patch a vulnerability.

Immediate — deploy this week, no compatibility risk

H-I1 · Block unsigned executables running from user-writable paths on developer workstations

MITRE M1038 (Execution Prevention) · M1045 (Code Signing). Authority: CIS Microsoft Windows 11 Enterprise Benchmark §18 (AppLocker/WDAC), Microsoft Security Baseline for Windows 11. The entire chain runs an unsigned interpreter from %USERPROFILE%, %LOCALAPPDATA% or %APPDATA%. A WDAC or AppLocker publisher rule in audit mode costs nothing and immediately shows you every candidate.

Verify: Get-AppLockerPolicy -Effective -Xml, or for WDAC check event log Microsoft-Windows-CodeIntegrity/Operational for 3076/3077.

H-I2 · Enable ASR rule "Block executable files from running unless they meet a prevalence, age, or trusted list criterion"

MITRE M1038. Authority: Microsoft Defender ASR documentation; CIS Windows 11 Benchmark §18.10.43. GUID 01443614-cd74-433a-b99e-2ecdc07bfc25. The campaign's interpreters are freshly compiled with regular refreshes, so they have no prevalence and no age. Deploy in Audit for one week, then Block on the developer ring.

Verify: Get-MpPreference | Select-Object -ExpandProperty AttackSurfaceReductionRules_Ids.

H-I3 · Publish a rejection rule for capability packages, and tell people it exists

MITRE M1051 (Update Software) is the wrong lever here; the right one is M1017 (User Training) paired with a hard technical rule. A legitimate MCP server or Agent Skill is source code with a manifest. It is never a Windows ZIP containing a launcher script, a renamed runtime and a payload disguised as a text file. Any capability whose install step is "download the archive and run the executable" is rejected on sight, no exceptions and no manager override.

Verify: run the N4 inventory script fleet-wide and confirm zero installed capabilities have a .zip or .exe install step.

H-I4 · Add the section 10 CSV to Falcon IOC Management

MITRE M1031 (Network Intrusion Prevention). Three hashes at prevent, the rest at detect, with the stated expirations so the perishable network indicators age out on their own.

Verify: re-run Q8 after import and confirm any historical hit now also raises an IOC detection.

Near term — 1 to 4 weeks, pilot on a ring first

H-N1 · Build a curated catalog of reviewed Skills, MCP servers and agent plugins

MITRE M1016 (Vulnerability Scanning) and M1051, applied to the capability supply chain. Authority: NIST SP 800-161r1 (C-SCRM) §3.1; CSA guidance on MCP registry vetting. The campaign depends entirely on open discovery. A curated internal catalog removes its audience, human and agent alike, and gives teams a fast sanctioned path so the control does not get routed around. Point every agent's default capability source at the catalog.

Verify: agent configuration files reference only catalog sources; N4 output shows no unlisted entries.

H-N2 · Require an isolated evaluation environment for every new capability

MITRE M1048 (Application Isolation and Sandboxing). Authority: NIST SP 800-161r1 §3.4. Evaluate with no browser sessions, no cloud credentials, no SSH keys and no production data present. The campaign's packages fail this test in seconds because there is nothing inside them that does what the README claims.

Verify: the evaluation VM template has no credential material; confirm by running a secrets scanner against the golden image.

H-N3 · Egress policy for blockchain RPC and raw code-hosting content

MITRE M1037 (Filter Network Traffic). Block or explicitly allowlist public Ethereum/Polygon JSON-RPC endpoints from the corporate estate; outside wallets and blockchain development the legitimate footprint is close to zero, and blocking it breaks the dead-drop resolver outright. Restrict raw.githubusercontent.com to hosts with a documented developer need.

Verify: from a standard workstation, attempt a POST to a public Polygon RPC host and confirm the proxy denies it.

H-N4 · Treat agent-initiated retrievals as a first-class monitored path

MITRE M1047 (Audit). Agent-initiated downloads, git clone calls and shell commands bypass browser-download controls entirely because no browser is involved. Ship agent CLI transcripts and shell history to the SIEM, and give changes to Skill directories and MCP configurations the same review weight as a browser download.

Verify: confirm Q10 returns rows for a deliberate agent-initiated git clone on a test host, and that the agent transcript for the same action is searchable in the SIEM.

H-N5 · Inventory every AI capability in use, with hashes

MITRE M1016. Record source repository, owner, commit, version and package hash. Without it, a newly published list of campaign repositories cannot be matched against your estate at all. With it, the match takes minutes.

Verify: pick three random workstations and confirm every installed capability appears in the register with a hash.

Strategic — 1 to 3 months, architectural or vendor coordination

H-S1 · Least agency, not just least privilege, for agent tooling

MITRE M1026 (Privileged Account Management) extended to non-human actors. Treat every MCP tool description as untrusted input on the same footing as a web page. Constrain what an agent is permitted to do (install, execute, network-fetch) separately from what it is permitted to read. ⚠ best-practice, no formal benchmark — MCP-specific hardening standards are still emerging; the CSA research note and vendor guidance are the current best authority.

H-S2 · WDAC in enforced mode on developer workstations

MITRE M1038, M1045. Authority: Microsoft WDAC deployment guidance; DISA Windows 11 STIG WN11-00-000040. Moving H-I1 from audit to enforcement is the control that ends this class of attack rather than detecting it. It needs a genuine application-inventory project first, which is why it sits here rather than in the immediate tier.

H-S3 · Short-lived, phishing-resistant credentials and token binding

MITRE M1032 (Multi-factor Authentication), M1017. StealC takes live sessions, so the mitigation that actually reduces impact is making a stolen cookie worthless: token binding or device-bound session credentials, short session lifetimes for high-value applications, and continuous access evaluation on the IdP.

Verify: replay a captured session cookie from an unmanaged device in a controlled test and confirm the IdP rejects it.

H-S4 · Browser session and secret hygiene on developer endpoints

MITRE M1027 (Password Policies), M1017. Move cloud and source-control credentials out of browser profiles and local config files into a broker that issues short-lived tokens. This directly reduces what StealC can take on a successful run.

13

Deployable Playbooks

P1 — AppLocker audit rule for unsigned executables in user-writable paths (H-I1)

Prerequisites: Windows 10/11 Enterprise or Education; Application Identity service (AppIDSvc) set to Automatic; local admin or GPO edit rights; a test ring of no more than 20 developer workstations. Reboot required: No, but the Application Identity service must be running and a gpupdate is needed. Rollback: delete the GPO link (or run Set-AppLockerPolicy -XmlPolicy <empty-policy>.xml with a policy containing no rule collections), then gpupdate /force. Audit-mode rules never block, so rollback restores logging volume only, not user access.

# 1. Ensure the Application Identity service is running (required for AppLocker)
Set-Service -Name AppIDSvc -StartupType Automatic
Start-Service -Name AppIDSvc

# 2. Generate a baseline from the test ring so you can see what would be blocked
$rules = Get-ChildItem -Path "$env:USERPROFILE","$env:LOCALAPPDATA","$env:APPDATA" `
           -Recurse -Include '*.exe','*.dll' -Force -ErrorAction SilentlyContinue |
         Get-AppLockerFileInformation |
         New-AppLockerPolicy -RuleType Publisher,Hash -User Everyone -Optimize

# 3. Export, set every rule collection to AuditOnly, and review before enforcing
$rules | Set-AppLockerPolicy -XmlPolicy 'C:\Temp\AppLocker-Audit.xml'

# 4. Review what fired after 7 days
Get-WinEvent -LogName 'Microsoft-Windows-AppLocker/EXE and DLL' |
  Where-Object { $_.Id -in 8003,8004 } |
  Select-Object TimeCreated, Id, Message -First 100

P2 — Enable the ASR prevalence/age rule in Audit, then Block (H-I2)

Prerequisites: Microsoft Defender Antivirus in active mode (not passive) with cloud-delivered protection enabled; Windows 10 1803+ or Windows 11; Defender for Endpoint licence for centralised reporting. If Defender runs in passive mode alongside Falcon, ASR rules do not apply and this playbook does not apply either. Reboot required: No. Rollback: run the same command with -AttackSurfaceReductionRules_Actions Disabled, or Remove-MpPreference -AttackSurfaceReductionRules_Ids <GUID>. Takes effect immediately, no reboot.

# Step 1 - Audit for 7 days on the developer ring
Add-MpPreference -AttackSurfaceReductionRules_Ids '01443614-cd74-433a-b99e-2ecdc07bfc25' `
                 -AttackSurfaceReductionRules_Actions AuditMode

# Step 2 - Review what would have been blocked
Get-WinEvent -LogName 'Microsoft-Windows-Windows Defender/Operational' |
  Where-Object { $_.Id -eq 1122 } |
  Select-Object TimeCreated, Message -First 100

# Step 3 - After a clean audit window, switch to Block
Set-MpPreference -AttackSurfaceReductionRules_Ids '01443614-cd74-433a-b99e-2ecdc07bfc25' `
                 -AttackSurfaceReductionRules_Actions Enabled

# Verify
Get-MpPreference | Select-Object -ExpandProperty AttackSurfaceReductionRules_Ids
Get-MpPreference | Select-Object -ExpandProperty AttackSurfaceReductionRules_Actions

P3 — Fleet sweep and clean removal of SmartLoader persistence

Prerequisites: local admin on the target host; PowerShell 5.1+; run the read-only sweep first and review its output before running the removal block. Do not run removal on a host that is still under investigation, since it destroys the persistence artefacts. Reboot required: No. Rollback: none available for the removal block by design, which is why the sweep is a separate step. Export the sweep output to a file before removal so the artefacts are preserved as evidence; restoring a deleted malicious task is never desirable, but the evidence is.

# ---- STEP 1: SWEEP ONLY (read-only, safe to run fleet-wide) ----
$hits = @()
Get-ScheduledTask | ForEach-Object {
  $t = $_
  foreach ($act in ($t.Actions | Where-Object { $_.Execute })) {
    if ($act.Execute -match '(?i)\\(AppData|ProgramData)\\' -and
        $t.TaskName -match '^[A-Za-z]+_[A-Za-z0-9+=]{3,8}$') {
      $hits += [pscustomobject]@{
        Host = $env:COMPUTERNAME; Task = $t.TaskName; Path = $t.TaskPath
        Exec = $act.Execute; Args = $act.Arguments; Author = $t.Author
      }
    }
  }
}
$hits | Export-Csv -NoTypeInformation "C:\Temp\smartloader-sweep-$env:COMPUTERNAME.csv"
$hits | Format-Table -AutoSize

# ---- STEP 2: PRESERVE EVIDENCE (run before removal) ----
foreach ($h in $hits) {
  $dir = Split-Path -Parent $h.Exec
  if (Test-Path $dir) {
    Compress-Archive -Path $dir -DestinationPath "C:\Temp\evidence-$($h.Task).zip" -Force
    Get-ChildItem -Path $dir -Force | Get-FileHash -Algorithm SHA256 |
      Export-Csv -NoTypeInformation -Append "C:\Temp\smartloader-hashes-$env:COMPUTERNAME.csv"
  }
}

# ---- STEP 3: REMOVE (only after evidence capture and IR sign-off) ----
foreach ($h in $hits) {
  Unregister-ScheduledTask -TaskName $h.Task -TaskPath $h.Path -Confirm:$false
  $dir = Split-Path -Parent $h.Exec
  if (Test-Path $dir) { Remove-Item -LiteralPath $dir -Recurse -Force }
}
# Cached tasking and staged second stages
Remove-Item "$env:TEMP\session.lua","$env:TEMP\debug.lua" -Force -ErrorAction SilentlyContinue

P4 — Proxy rules for the dead-drop resolver and exfiltration path (H-N3)

Prerequisites: a web proxy or secure web gateway with category and destination control; TLS inspection for the body-matching rules (the URL-level rules work without it); an approved exception list for genuine wallet and web3 development hosts before you switch from monitor to block. Reboot required: No. Rollback: set each rule back to Monitor, or delete the rule. Because rule 1 can break genuine blockchain development work, deploy it in Monitor for 7 days and build the exception list from what it sees; keeping the exception list under version control is what makes rollback a one-line revert.

# Rule 1 - Blockchain RPC egress (deploy MONITOR first, then BLOCK)
#   Match:  destination host matches *.drpc.org, *.infura.io, *.alchemy.com,
#           *.ankr.com, *.quiknode.pro, *.llamarpc.com, *.publicnode.com,
#           polygon-rpc.com
#   Except: hosts in the approved web3-development group
#   Action: BLOCK, log, alert to the hunt queue

# Rule 2 - Dead-drop contract call (requires TLS inspection)
#   Match:  method=POST AND body contains "eth_call"
#           AND body contains "0x1823A9a0Ec8e0C25dD957D0841e3D41a4474bAdc"
#                OR body contains "0x3bc5de30"
#   Action: BLOCK, high-severity alert -- this is the highest-fidelity network signal in the chain

# Rule 3 - Static Lua user agent
#   Match:  User-Agent equals s3klqc1wa6ntg1szvckzi0nt9oumpwy6hhq
#   Action: BLOCK, high-severity alert

# Rule 4 - Bare-IP exfiltration pattern
#   Match:  method=POST AND Host header is a raw IPv4 literal
#           AND uri matches ^/(api|task)/[A-Za-z0-9+/=]{8,}$
#           AND content-type contains multipart/form-data
#   Action: BLOCK, high-severity alert

# Rule 5 - Raw code-hosting content for non-developers
#   Match:  destination host in (raw.githubusercontent.com,
#           objects.githubusercontent.com, gist.githubusercontent.com)
#   Except: hosts in the approved developer group
#   Action: MONITOR, feed the hunt queue (blocking this estate-wide breaks real work)
14

Containment Runbook

Sequence matters. StealC exfiltrates live sessions, so credential revocation has to happen even if the endpoint is already isolated, and it has to cover session tokens and OAuth grants, not just passwords.

PhaseActionsOwnerEvidence to capture
0 · Triage
0-30 min
Confirm the hit is real: does the process tree show a shell parent, an unsigned interpreter in a user path, and a data-file argument? Check for a second scheduled task on the same host. Pull the ZIP hash and compare against the section 10 CSV. SOC L1 Falcon process tree export; scheduled task list; ZIP and payload SHA-256
1 · Isolate
30-60 min
Network-contain the host in Falcon. Do not power off; the loader keeps state in memory and the packed StealC image is never written to disk. Snapshot memory if your process supports it. SOC L2 Containment timestamp; memory image if captured
2 · Revoke
within 2 h — do not defer
For the affected user: revoke all browser sessions and IdP refresh tokens; revoke OAuth grants; rotate source-control PATs and SSH keys; rotate cloud access keys; rotate any secret present in a local config file or browser profile. Force re-authentication with MFA on every device. IAM + Cloud Revocation ticket with token IDs; list of rotated secrets
3 · Scope
2-8 h
Run Q1 through Q4 fleet-wide over 120 days. Run Q8 as a retrospective sweep. Run the N4 capability inventory across every host belonging to the same team. Identify the source repository and check whether any teammate installed the same capability. Threat Hunt Query results; list of affected hosts and users; source repository URL and owner handle
4 · Eradicate
8-24 h
Run playbook P3 steps 1 and 2 on every affected host, get IR sign-off, then step 3. Remove the downloaded archive and the extracted directory. For any host with confirmed StealC execution, rebuild rather than clean: the loader supports arbitrary in-memory payloads and you cannot enumerate what else ran. Endpoint Eng P3 sweep CSV and hash CSV per host; rebuild tickets
5 · Recover
24-72 h
Release containment only after the host is clean or rebuilt and the user's credentials are fully rotated. Restore the user with new credentials on a clean device. Monitor their IdP sign-ins for 30 days for session reuse from a new ASN or device fingerprint. SOC + IAM Clean-host attestation; 30-day IdP monitoring rule ID
6 · Report and prevent
72 h+
Report the repository and profile to GitHub and to any registry that lists it. Add the package hash to the section 10 CSV and to IOC Management. Add the capability to the rejected list in the curated catalog. Feed the source repository owner handle into the publisher-verification check so the same lookalike pattern is caught next time. Threat Intel Abuse report references; updated catalog and IOC entries
15

Detection Coverage Map

TechniqueBehaviourCQLIOACoverage
T1608.001 · Stage CapabilitiesMalicious repositories published and indexedGAP external; covered by H-N1 catalog
T1585.001 · Establish AccountsLookalike developer profilesGAP external; covered by H-I3 publisher verification
T1195.001 · Supply Chain CompromiseAgent or user installs a poisoned capabilityQ9, Q10Partial — high FP, inventory-driven
T1204.002 · User ExecutionLauncher executed after extractionQ1IOA-1Good
T1059.003 · Windows Command ShellOne-line start launcherQ1, Q4IOA-1Good
T1059 · Lua via LuaJITObfuscated Lua executed by a renamed interpreterQ1, Q2IOA-1, IOA-3Good
T1036.005 · MasqueradingInterpreter renamed; payload given a benign extensionQ1, Q2IOA-1, IOA-3Good
T1105 · Ingress Tool TransferLua runtime and payload staged to diskQ2IOA-3Good
T1053.005 · Scheduled TaskTwo daily tasks with independent recovery pathsQ3, Q4IOA-2Good
T1036.004 · Masquerade Task or ServiceTask named after a Microsoft componentQ3IOA-2Good
T1564.003 · Hidden WindowGUI-subsystem PE plus FFI ShowWindowGAP — no process-level signal; caught only as a property of the Q1 child
T1622 · Debugger EvasionAnti-debug shellcode in executable memoryGAP — Falcon memory-scan detections only
T1614 / T1082 · Location and System DiscoveryGeo-IP lookup and host fingerprintQ6Partial — correlation signal only
T1113 · Screen CaptureDesktop screenshot via GDIGAP — visible only as exfil volume in Q8 / proxy
T1102.001 · Dead Drop ResolverPolygon contract eth_call returns the live C2Q5Good with proxy rule 2; Partial on DNS alone
T1102 · Web ServiceEncrypted second stages pulled from raw GitHubQ7Partial — high FP, process-scoped
T1071.001 / T1041 · Web Protocols, Exfil over C2Multipart POST to a bare-IP C2Q8Partial — addresses rotate; proxy rule 4 carries the durable half
T1620 · Reflective Code LoadingStealC PE decrypted and loaded in memoryGAP — memory-scan and StealC behavioural detections only
T1555.003 / T1539 · Browser Credentials, Session CookiesStealC harvests credentials, cookies and live sessionsPartial — Falcon credential-access IOAs plus IdP session-reuse monitoring

Coverage summary: 8 of 19 mapped techniques are covered well, 6 partially, and 5 are gaps. The gaps cluster in two places, and neither is fixable with process telemetry: the pre-execution reputation problem (repository publication and lookalike accounts) belongs to the curated catalog and publisher verification in section 12, and the in-memory half of the chain (anti-debug, reflective load, screen capture) belongs to Falcon's memory-scanning and behavioural layers rather than to a query. The execution and persistence steps in between are the ones this pack covers hard, and they sit on the only path the operator cannot avoid.

Validation gates for all of the above are in section 11. Do not promote IOA-1 or IOA-2 past Monitor until gates 2, 3, 4 and 7 pass in your own estate; Q1's false-positive floor depends entirely on whether any legitimate interpreter-plus-data-file launcher exists in your image.

16

Hunt Summary Ticket

TITLE:      AgentBaiting / FakeGit -- SmartLoader to StealC via fake AI Skills and MCP servers
SEVERITY:   High (active campaign, ~7,600 repositories, 14M+ measured downloads)
SCOPE:      Windows developer, analyst and AI-agent-enabled workstations. 120-day retrospective.

HYPOTHESIS: A user or an AI coding agent discovered a repository posing as an AI Skill or MCP
            server, downloaded its ZIP, and ran the bundled launcher. That launcher started a
            renamed LuaJIT interpreter against an obfuscated Lua payload disguised with a benign
            extension, which established two masquerading scheduled tasks under %LOCALAPPDATA%,
            resolved its C2 from a Polygon smart contract, and loaded StealC in memory.

QUERIES:    Q1  launcher chain: cmd.exe parent + interpreter in user path + data-file argument
            Q2  lua51.dll / LuaJIT interpreter written to a user-writable path
            Q3  scheduled task named <MicrosoftComponent>_<base64 loader id>
            Q4  schtasks.exe /create pointing into AppData with a text-extension argument
            Q5  blockchain RPC resolved by a non-browser, non-wallet process
            Q6  geo-IP lookup from a non-browser process
            Q7  raw GitHub content fetched by a non-developer process
            Q8  known SmartLoader / StealC bare-IP C2 (retrospective)
            Q9  AI/MCP/Skill-themed archive dropped to a user directory
            Q10 coding agent spawning a shell that downloads, clones or expands content

DO FIRST:   1. Run Q1 and Q3 over 120 days. These two carry the pack.
            2. Run N4 (capability inventory) on every AI-agent-enabled workstation.
            3. Import the section 10 CSV into Falcon IOC Management.
            4. Enable the ASR prevalence/age rule in Audit on the developer ring (P2).

FINDINGS:   [ ] Q1 hits: ______   [ ] Q3 hits: ______   [ ] Q2 hits: ______
            [ ] Unvetted capabilities found by N4: ______
            [ ] Hosts requiring rebuild: ______

GAPS:       Anti-debug shellcode, reflective StealC load and screen capture have no process
            telemetry -- memory-scan detections only. Repository publication and lookalike
            account creation are external and covered by the curated catalog (H-N1) plus
            publisher verification (H-I3), not by any query. Agent CLI transcripts are the
            single biggest visibility gap: without them Q10 sees the shell but not the intent.

ACTIONS:    [ ] Isolate + revoke sessions and OAuth grants on any confirmed host (containment 1-2)
            [ ] Rebuild any host with confirmed StealC execution -- do not clean
            [ ] Stand up the curated capability catalog (H-N1)
            [ ] Report repository and profile to GitHub and to every registry listing it

OWNER:      Threat Hunt / SOC
VERSION:    v0.1 -- 2026-07-28
17

Changelog

v0.12026-07-28Initial pack. 10 CQL queries, 3 Custom IOA candidates, 20 atomic indicators traced to 13 saved source snapshots, 13 hardening controls across three tiers, 4 deployable playbooks and a 7-phase containment runbook. Indicators split by wave: ZIP hashes from the July 2026 AI-Skills wave, loader and network infrastructure from the April 2026 wave of the same loader family. Live C2 shipped as a labelled placeholder because it is resolved on demand from a Polygon smart contract.
18

References

TierSourceUsed forAccessed
1Island — AgentBaiting: How 800+ Fake AI Skills and MCP Servers Delivered MalwarePrimary research. Campaign scale, AgentBaiting technique, ZIP internals, 10 ZIP SHA-256 pairs, defensive guidance2026-07-28
1Hexastrike — Cloned, Loaded, and Stolen: 109 Fake GitHub Repositories Delivered SmartLoader and StealCLoader reverse engineering, Polygon dead-drop resolver, C2 addresses, persistence design, staged StealC PE, component hashes2026-07-28
1Centri — JIT Happens: Exposing LuaJIT Malware In The WildIndependent dynamic analysis: geo-IP check, Base64 loader-ID staging directories, task caching, static Lua user agent2026-07-28
1AhnLab ASEC — Distribution of SmartLoader Malware via GitHub Repository Disguised as a Legitimate ProjectFour-file ZIP layout, persistence copy path, scheduled task names, C2 tasking schema2026-07-28
2Intellibron — Lua-JIT SmartLoader: Analyzing the GitHub Campaign Delivering StealerSecond confirmation of the scheduled task names and the launcher/interpreter/payload triple2026-07-28
2Cloud Security Alliance Labs — research note on FakeGit, AgentBaiting and the MCP supply chainEcosystem context: registry vetting failures, scale of the MCP and Skill ecosystem2026-07-28
2BleepingComputer — FakeGit campaign uses 7,600 GitHub repos to push SmartLoader malwareIndependent restatement of scale and technique2026-07-28
2The Hacker News — FakeGit Campaign Uses 7,600 GitHub Repositories to Spread SmartLoader MalwareHistorical link to the earlier Lumma-era operation tracked as Water Kurita2026-07-28
2CyberSecurityNews — AgentBaiting Campaign Uses 800 Fake AI Skills and MCP ServersSecond independent reproduction of three ZIP SHA-256 values, which is what supports the prevent action on those three rows2026-07-28
2GBHackers — AgentBaiting Uses Fake AI Skills and MCP Servers to Deliver SmartLoader and StealCCorroboration of the execution chain summary2026-07-28
2Help Net Security — AI agents tricked into recommending malicious GitHub repositoriesCorroboration of the AgentBaiting testing results2026-07-28
2DevOps.com — FakeGit Targets AI Coding Agents with Malicious GitHub ReposDeveloper-workflow framing2026-07-28
2TechNadu — AgentBaiting: FakeGit Weaponizes 800+ Fake AI Skills for SmartLoaderRegistry-distribution detail and vendor guidance on treating tool descriptions as untrusted input2026-07-28
FrameworkMITRE ATT&CKTechnique and mitigation identifiers throughout sections 6 and 122026-07-28

Source snapshots for every entry above are saved alongside this file in AgentBaiting-SmartLoader-Hunt-sources/. Every atomic indicator in section 10 was mechanically traced back to those snapshots before publication.