ℹ️ This was duplicated to this blog 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 of known RMM executables, as well as a raw json file for processing.
These rely on explicity referencing known RMM artifacts (in some way) within the logic
- Known RMMs
 - Known RMM + low prevalence
 - New executable in environment + known RMM
 - New + RMM + suspicious activity
 - New + RMM + alert
 
 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]   
    This relies completely on common behaviors of RMM (can misidentify)
- Logic for generic RMM behaviors (vs pre-defined known RMMs)
 
 flowchart LR
    subgraph 1
      direction LR
      A[known RMM]
    end
    1-->AQ[GoToAssistUnattended.exe]
    Two options to defining known RMM's
Simply build a list of all known executables (see the table below). This is brittle, but more precise
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")
  )
)This is a more resilient approach, which looks for
- unique patterns of the executable path
 - code signature unique to RMM software
 
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
) 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
 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 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.
 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:
- create the rule from step 3 (optionally as a 
building_block_ruleto keep noise down) - 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_rulefor suspicious activity 
 - to simplify this, you can create another 
 
sequence by host.id, user.id, process.name with maxspan=25m
[alert where rule.id == <new_term_rule_step3>]
[alert where rule.id == <suspicious_rule_step4>] 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
sequence by host.id, user.id, process.name with maxspan=25m
[alert where rule.id == <new_term_rule_step3>]
[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
 
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.
Great work!