# Detecting RMM ℹ️ _This was duplicated to this [blog](https://br0k3nlab.com/posts/2023/04/detecting-rmm/) for readability and reference_ --- The most difficult challenge with RMM detection is contextual awareness around usage to determine if it is valid or malicious. - if the software is _not_ used in the envrionment - could it be legitimate by a random empoyee? - is it an attacker BYOL - even so, all occurrences could probably be considered suspicious - if it _is_ used in the environment - is _every_ use of it legitimate? Probably not - this also creates significant living off the land (LOL) opportunity - _some_ occurrences should be considered suspicious - without _any_ contextual awareness, this is an even harder problem Below is a [table](https://gist.github.com/brokensound77/6d8a1e480e65ff20e151099c98267b14#file-rmm-executables-md) of known RMM executables, as well as a raw json [file](https://gist.github.com/brokensound77/6d8a1e480e65ff20e151099c98267b14#file-rmm-executables-raw-json) for processing. ## Approaches to detecting ### A. Explicitly defined RMM software + behavioral (less resilient) These rely on explicity referencing known RMM artifacts (in some way) within the logic 1. Known RMMs 2. Known RMM + low prevalence 3. New executable in environment + known RMM 4. New + RMM + suspicious activity 5. New + RMM + alert ```mermaid flowchart LR subgraph 1 direction LR A[known RMM] end subgraph 2 direction LR B1[known RMM]-->B2[low prevalence] end subgraph 3 direction LR C1[new executable]--> C2[known RMM] end subgraph 4 direction LR D1[new executable]--> D2[known RMM]--> D3[suspicious activity] subgraph suspicious direction LR D21[discovery] D22[lateral movement] D23[...] end end subgraph 5 direction LR E1[new executable]--> E2[known RMM]--> E3[alert] end D3-.->suspicious 1-->AQ[GoToAssistUnattended.exe] 2-->BQ[GoToAssistUnattended.exe + hosts<5] 3-->CQ[executable first seen in now-30d + GoToAssistUnattended.exe] 4-->DQ[executable first seen in now-30d + GoToAssistUnattended.exe + ping 192.168.1/24] 5-->EQ[executable first seen in now-30d + GoToAssistUnattended.exe + alert: new admin user created] ``` ### B. Dynamically and generically defining RMM + behavioral This relies completely on common behaviors of RMM (can misidentify) 1. Logic for generic RMM behaviors (vs pre-defined known RMMs) ## Details ### A1. Known RMMs ```mermaid flowchart LR subgraph 1 direction LR A[known RMM] end 1-->AQ[GoToAssistUnattended.exe] ``` Two options to defining known RMM's #### Option 1: comprehensive list of identified RMM executables Simply build a list of all known executables (see the table below). This is brittle, but more precise
```sql process where event.type == "start" and ( // Windows ( host.os.type == "windows" and process.executable : ( "C:\\Program Files*\\*\\NinjaRMMAgentPatcher.exe", "C:\\Program Files*\\NinjaRMMAgent\\NinjaRMMAgentPatcher.exe", "C:\\ProgramData\\NinjaRMMAgent\\ninjarmm-cli.exe", "C:\\Program Files*\\*\\NinjaRMMAgent.exe", "C:\\Program Files*\\NinjaRMMAgent\\NinjaRMMAgent.exe", "C:\\Program Files*\\ATERA Networks\\AteraAgent\\AteraAgent.exe", "C:\\Program Files*\\ATERA Networks\\AteraAgent\\Packages\\AgentPackageNetworkDiscoveryWG\\AgentPackageNetworkDiscoveryWG.exe", "C:\\Program Files*\\ATERA Networks\\AteraAgent\\Packages\\AgentPackageAgentInformation\\AgentPackageAgentInformation.exe", "C:\\Program Files*\\ATERA Networks\\AteraAgent\\Packages\\AgentPackageSTRemote\\AgentPackageSTRemote.exe", "C:\\Program Files*\\ATERA Networks\\AteraAgent\\Packages\\AgentPackageFileExplorer\\AgentPackageFileExplorer.exe", "C:\\Program Files*\\ATERA Networks\\AteraAgent\\Packages\\AgentPackageMonitoring\\AgentPackageMonitoring.exe", "C:\\Program Files*\\ATERA Networks\\AteraAgent\\Packages\\AgentPackageRuntimeInstaller\\AgentPackageRuntimeInstaller.exe", "C:\\Windows\\SysWOW64\\config\\systemprofile\\AppData\\Local\\GoToAssist Remote Support Applet\\*.tmp\\GoToAssistService.exe", "C:\\Users\\*\\AppData\\Local\\GoToAssist Remote Support Applet\\*.tmp\\GoToAssistProcessChecker.exe", "C:\\Program Files*\\LogMeIn\\GoToAssist Corporate\\*\\G2AC_HostLauncher.exe", "C:\\Program Files*\\GoToMeeting\\*\\G2MInstaller.exe", "C:\\Users\\*\\AppData\\Local\\GoToMeeting\\*\\g2mcomm.exe", "C:\\Users\\*\\AppData\\Local\\GoToMeeting\\*\\g2mlauncher.exe", "C:\\Program Files*\\GoToAssist Remote Support Customer\\*\\g2ax_host_service.exe", "C:\\Program Files*\\GoToAssist Remote Support Customer\\*\\g2ax_comm_customer.exe", "C:\\Users\\*\\AppData\\Local\\GoTo Resolve Applet\\*.tmp\\GoToResolveService.exe", "C:\\Program Files*\\GoToAssist Remote Support Unattended\\*\\GoToAssistTools64.exe", "C:\\Program Files*\\GoToAssist Remote Support Unattended\\*\\GoToAssistUnattended.exe", "C:\\Users\\*\\AppData\\Local\\goto-updater\\pending\\GoToSetup-*.exe", "C:\\Program Files*\\GoToMeeting\\*\\g2mlauncher.exe", "C:\\Users\\*\\AppData\\Local\\GoToAssist Remote Support Applet\\*.tmp\\GoToAssistCrashHandler.exe", "C:\\Users\\*\\AppData\\Local\\GoToMeeting\\*\\g2mupdate.exe", "C:\\ManageEngine\\DesktopCentralMSP_Server\\jre\\bin\\java.exe", "C:\\ManageEngine\\ADManager Plus\\jre\\bin\\java.exe", "C:\\Program Files*\\ManageEngine\\PMP\\tools\\archiver\\windows\\x86-64\\7za.exe", "C:\\ManageEngine\\elasticsearch\\jre\\bin\\java.exe", "C:\\Program Files*\\ManageEngine\\PMP\\jre\\bin\\java.exe", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\bin\\7za.exe", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\bin\\wrapper.exe", "C:\\ManageEngine\\OpManager\\jre\\bin\\java.exe", "C:\\ManageEngine\\EventLog Analyzer\\jre\\bin\\java.exe", "C:\\ManageEngine\\ADAudit Plus\\pgsql\\bin\\postgres.exe", "C:\\ManageEngine\\OpManager\\Probe\\OpManagerProbe\\pgsql\\bin\\postgres.exe", "C:\\Program Files*\\Microsoft Intune Management Extension\\ClientHealthEval.exe", "C:\\Program Files*\\WindowsApps\\Microsoft.*\\IntuneManagementExtensionBridge\\IntuneManagementExtensionBridge.exe", "C:\\Program Files*\\WindowsApps\\Microsoft.*\\BridgeLauncher\\BridgeLauncher.exe", "C:\\Program Files*\\Microsoft Intune Management Extension\\Microsoft.Management.Services.IntuneWindowsAgent.exe", "C:\\Program Files*\\Microsoft Intune Management Extension\\Microsoft.Management.Clients.CopyAgentCatalog.exe", "C:\\Program Files*\\Microsoft Intune Management Extension\\SensorLogonTask.exe", "C:\\Program Files*\\Microsoft Intune Management Extension\\AgentExecutor.exe", "C:\\Users\\*\\AppData\\Local\\MSP Anywhere for N-central\\Viewer\\Tmp\\SWI_MSP_RC_ViewerUpdate-*.exe", "C:\\Program Files*\\DesktopCentral_Agent\\bin\\dcagentservice.exe", "C:\\Program Files*\\DesktopCentral_Agent\\bin\\DCFAService64.exe", "C:\\Program Files*\\DesktopCentral_Agent\\bin\\dcagentregister.exe", "C:\\Program Files*\\DesktopCentral_Server\\pgsql\\bin\\postgres.exe", "C:\\Program Files*\\DesktopCentral_Server\\bin\\wrapper.exe", "C:\\ManageEngine\\DesktopCentral_Server\\bin\\wrapper.exe", "C:\\Program Files*\\DesktopCentral_Server\\bin\\UEMS.exe", "C:\\Program Files*\\DesktopCentral_Server\\nginx\\dcnginx.exe", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\jre\\bin\\java.exe", "C:\\Program Files*\\DesktopCentral_Agent\\bin\\EMSAddonInstaller.exe", "C:\\ManageEngine\\DesktopCentral_Server\\jre\\bin\\java.exe", "C:\\Program Files*\\DesktopCentral_Server\\apache\\bin\\dcserverhttpd.exe", "C:\\Program Files*\\DesktopCentral_Server\\bin\\7za.exe", "C:\\Program Files*\\DesktopCentral_Server\\jre\\bin\\java.exe", "C:\\Program Files*\\DesktopCentral_Server\\bin\\dcnotificationserver.exe", "C:\\Program Files*\\DesktopCentral_Agent\\dcconfig.exe", "C:\\Program Files*\\DesktopCentral_Agent\\patches\\*-gimp-*-setup.exe", "C:\\ManageEngine\\AssetExplorer\\DesktopCentral_Server\\bin\\wrapper.exe", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\lib\\native\\64bit\\wrapper.dll", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\jre\\bin\\awt.dll", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\jre\\bin\\sunec.dll", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\jre\\bin\\freetype.dll", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\jre\\bin\\fontmanager.dll", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\lib\\native\\64bit\\SyMNative.dll", "C:\\Program Files*\\ManageEngine\\ServiceDesk\\DesktopCentral_Server\\lib\\native\\64bit\\OSDSyMNative.dll", "C:\\Windows\\Action1\\action1_remote.exe", "C:\\Windows\\Action1\\action1_agent.exe") ) or // MacOS ( host.os.type == "macos" and process.executable : ( "/Applications/NinjaRMMAgent/programfiles/ninjarmm-macagent", "/Applications/GoToMeeting.app/Contents/MacOS/GoToMeeting", "/Applications/GoToMeeting.app/Contents/Helpers/G2MUpdate", "/Users/*/Library/Application Support/LogMeInInc/GoToMeeting/G2MUpdate", "/Library/Intune/Microsoft Intune Agent.app/Contents/MacOS/IntuneMdmDaemon", "/Applications/MSP Anywhere Agent N-central.app/Contents/Resources/MSP Anywhere Service Configurator.app/Contents/MacOS/MSP Anywhere Service Configurator", "/Applications/MSP Anywhere Agent N-central.app/Contents/Resources/MSP Anywhere Helper") ) ) ```
#### Option 2: resilient patterns of known RMM software This is a more resilient approach, which looks for - unique patterns of the executable path - code signature unique to RMM software
```sql any where event.category : ("process", "library") and event.type == "start" and ( // Windows ( host.os.type == "windows" and ( process.executable : ("?:\\*NinjaRMMAgent*.exe", "?:\\*\\AteraAgent\\*.exe", "?:\\*\\GoToAssist*\\*.exe", "?:\\*\\GoToMeeting\\*.exe", "?:\\*\\GoTo*.exe", "?:\\*\\GoToSetup*.exe", "?:\\*ManageEngine\\*.exe", "?:\\Microsoft Intune*\\*.exe", "?:\\IntuneManagement*\\*.exe", "?:\\*\\*N-central*\\*.exe", "?:\\*\\DesktopCentral*\\*.exe", "?:\\*\\Action1\\*.exe") or dll.path : ("?:\\*NinjaRMMAgent*.dll", "?:\\*\\AteraAgent\\*.dll", "?:\\*\\GoToAssist*\\*.dll", "?:\\*\\GoToMeeting\\*.dll", "?:\\*\\GoTo*.dll", "?:\\*\\GoToSetup*.dll", "?:\\*ManageEngine\\*.dll", "?:\\Microsoft Intune*\\*.dll", "?:\\IntuneManagement*\\*.dll", "?:\\*\\*N-central*\\*.dll", "?:\\*\\DesktopCentral*\\*.dll", "?:\\*\\Action1\\*.dll") or process.code_signature.subject_name : ("NinjaRMM, LLC", "Atera Networks Ltd", "LogMeIn, Inc.", "ZOHO Corporation Private Limited", // could FP due to non-RMM software "Action1 Corporation") or dll.code_signature.subject_name : ("NinjaRMM, LLC", "Atera Networks Ltd", "LogMeIn, Inc.", "ZOHO Corporation Private Limited", // could FP due to non-RMM software "Action1 Corporation") ) ) or // MacOS ( host.os.type == "macos" and ( process.executable : ("/Applications/*NinjaRMMAgent/*", "/Applications/*GoToMeeting*/*", "/Users/*/Library/*/GoToMeeting*/*", "/Library/*Microsoft InTune*/*", "/Users/*/Library/*Microsoft InTune*/*", "/Applications/*N-central*/*") or // or dll.path : () or // process.code_signature.subject_name : () or // dll.code_signature.subject_name : () ) ) // Linux ) ```
### A2. Known RMM + low prevalence ```mermaid flowchart LR subgraph 2 direction LR B1[known RMM]-->B2[low prevalence] end 2-->BQ[GoToAssistUnattended.exe + hosts<5] ``` Perform one of the searches from step 1 and aggregate on: - hosts - users - unique executions Look for low counts ### A3. New executable in environment + known RMM ```mermaid flowchart LR subgraph 3 direction LR C1[new executable]--> C2[known RMM] end 3-->CQ[executable first seen in now-30d + GoToAssistUnattended.exe] ``` Create a [new terms](https://www.elastic.co/guide/en/security/current/rules-ui-create.html#create-new-terms-rule) stlye rule based on step 1 - window history of now-30d - base the new terms on: `process.name`, `host.id` (remove host.id for full environment prevalence) If you do not have a new terms capability, you can perform the search in step 1 to build a list of observed RMM executables, then pivot (or `join`) on a search for recent exections. ### A4. New executable + known RMM + suspicious activity ```mermaid flowchart LR subgraph 4 direction LR D1[new executable]--> D2[known RMM]--> D3[suspicious activity] subgraph suspicious direction LR D21[discovery] D22[lateral movement] D23[...] end end 4-->DQ[executable first seen in now-30d + GoToAssistUnattended.exe + ping 192.168.1/24] ``` Combine step 3 with subsequent suspicious activity (such as lateral movement information gathering). With Elastic, you could do this by: 1. create the rule from step 3 (optionally as a `building_block_rule` to keep noise down) 2. create a separate sequence based rule that looks for the new term _then_ the suspicious activity - to simplify this, you can create _another_ `building_block_rule` for suspicious activity ```sql sequence by host.id, user.id, process.name with maxspan=25m [alert where rule.id == ] [alert where rule.id == ] ``` ### A5. New executable + known RMM + alert ```mermaid flowchart LR subgraph 5 direction LR E1[new executable]--> E2[known RMM]--> E3[alert] end 5-->EQ[executable first seen in now-30d + GoToAssistUnattended.exe + alert: new admin user created] ``` Similar to step 4 except referencing _actual_ alerts for the second part of the sequence ```sql sequence by host.id, user.id, process.name with maxspan=25m [alert where rule.id == ] [alert where true] ``` Leaving subquery 2 generic is a great option, since a newly occurring RMM would be suspicious in this case. It can be tightened down with a few options: - limiting query 2 to certain techniques or subtechniques - add additional logic to query 2 from the raw alert results, or even a subset of alerts - adding additional queries to the seqeunce to express a more progressed attack ### B1. Logic for generic RMM behaviors Rather than using statically defined RMM artifacts based on observations, this entails building out generic logic to identify them. This is a much greater challenge, especially due to their legitimate nature. Additional features such as ML, entity analytics, and other aggregation based searching make a significant difference here. Once a dynamic method is defined, then steps 2-5 apply, creating a sustainable detection approach. I think it _is_ doable from a purely rule-based approach, but I will return to this a bit later ... Also, with the Elastic ESQL piped language, these become much more feasible within a single rule.