#!/usr/bin/env python3 # -*- coding: utf-8 -*- # All credit to @an0n_r0 # project : https://github.com/tothi/serviceDetector from impacket.dcerpc.v5 import lsat, lsad from impacket.dcerpc.v5.rpcrt import DCERPCException from impacket.dcerpc.v5.dtypes import NULL, MAXIMUM_ALLOWED, RPC_UNICODE_STRING from impacket.dcerpc.v5 import transport, epm import json import pathlib class CMEModule: ''' Uses LsarLookupNames and NamedPipes to gather information on all endpoint protection solutions installed on the the remote host(s) Module by @mpgn_x64 ''' name = 'enum_av' description = 'Gathers information on all endpoint protection solutions installed on the the remote host(s) via LsarLookupNames (no privilege needed)' supported_protocols = ['smb'] opsec_safe = True multiple_hosts = True def options(self, context, module_options): pass def on_login(self, context, connection): success = 0 results = {} context.log.debug("Detecting installed services on {} using LsarLookupNames()...".format(connection.host)) try: lsa = LsaLookupNames(connection.domain, connection.username, connection.password, connection.hostname if connection.kerberos else connection.host, connection.kerberos, connection.domain, connection.lmhash, connection.nthash) dce, rpctransport = lsa.connect() policyHandle = lsa.open_policy(dce) for i, product in enumerate(conf['products']): for service in product['services']: try: lsa.LsarLookupNames(dce, policyHandle, service['name']) context.log.debug("Detected installed service on {}: {} {}".format(connection.host, product['name'], service['description'])) if product['name'] not in results: results[product['name']] = {"services": []} results[product['name']]['services'].append(service) except Exception as e: pass success += 1 except Exception as e: context.log.error(str(e)) context.log.debug("Detecting running processes on {} by enumerating pipes...".format(connection.host)) try: for f in connection.conn.listPath('IPC$', '\\*'): fl = f.get_longname() for i, product in enumerate(conf['products']): for pipe in product['pipes']: if pathlib.PurePath(fl).match(pipe['name']): context.log.debug("{} running claim found on {} by existing pipe {} (likely processes: {})".format(product['name'], connection.host, fl, pipe['processes'])) if product['name'] not in results: results[product['name']] = {} if "pipes" not in results[product['name']]: results[product['name']]['pipes'] = [] results[product['name']]['pipes'].append(pipe) success += 1 except Exception as e: context.log.error(str(e)) self.dump_results(results, connection.hostname, success, context) def dump_results(self, results, remoteName, success, context): # out1 = "On host {} found".format(remoteName) out1 = "" for item in results: out = out1 if 'services' in results[item]: out += "{} INSTALLED".format(item) if 'pipes' in results[item]: out += " and it seems to be RUNNING".format() # else: # for product in conf['products']: # if (item == product['name']) and (len(product['pipes']) == 0): # out += " (NamedPipe for this service was not provided in config)" elif 'pipes' in results[item]: out += " {} RUNNING".format(item) context.log.highlight(out) if (len(results) < 1) and (success > 1): out = out1 + " NOTHING!".format() context.log.highlight(out) class LsaLookupNames(): timeout = None authn_level = None protocol = None transfer_syntax = None machine_account = False iface_uuid = lsat.MSRPC_UUID_LSAT authn = True def __init__(self, domain="", username="", password="", remoteName="", k=False, kdcHost="", lmhash="", nthash=""): self.domain = domain self.username = username self.password = password self.remoteName = remoteName self.string_binding = r"ncacn_np:{}[\PIPE\lsarpc]".format(remoteName) self.doKerberos = k self.lmhash = lmhash self.nthash = nthash self.dcHost = kdcHost def connect(self, string_binding=None, iface_uuid=None): """Obtains a RPC Transport and a DCE interface according to the bindings and transfer syntax specified. :return: tuple of DCE/RPC and RPC Transport objects :rtype: (DCERPC_v5, DCERPCTransport) """ string_binding = string_binding or self.string_binding if not string_binding: raise NotImplemented("String binding must be defined") rpc_transport = transport.DCERPCTransportFactory(string_binding) # Set timeout if defined if self.timeout: rpc_transport.set_connect_timeout(self.timeout) # Authenticate if specified if self.authn and hasattr(rpc_transport, 'set_credentials'): # This method exists only for selected protocol sequences. rpc_transport.set_credentials(self.username, self.password, self.domain, self.lmhash, self.nthash) if self.doKerberos: rpc_transport.set_kerberos(self.doKerberos, kdcHost=self.dcHost) # Gets the DCE RPC object dce = rpc_transport.get_dce_rpc() # Set the authentication level if self.authn_level: dce.set_auth_level(self.authn_level) # Connect dce.connect() # Bind if specified iface_uuid = iface_uuid or self.iface_uuid if iface_uuid and self.transfer_syntax: dce.bind(iface_uuid, transfer_syntax=self.transfer_syntax) elif iface_uuid: dce.bind(iface_uuid) return dce, rpc_transport def open_policy(self, dce): request = lsad.LsarOpenPolicy2() request['SystemName'] = NULL request['ObjectAttributes']['RootDirectory'] = NULL request['ObjectAttributes']['ObjectName'] = NULL request['ObjectAttributes']['SecurityDescriptor'] = NULL request['ObjectAttributes']['SecurityQualityOfService'] = NULL request['DesiredAccess'] = MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES resp = dce.request(request) return resp['PolicyHandle'] def LsarLookupNames(self, dce, policyHandle, service): request = lsat.LsarLookupNames() request['PolicyHandle'] = policyHandle request['Count'] = 1 name1 = RPC_UNICODE_STRING() name1['Data'] = 'NT Service\{}'.format(service) request['Names'].append(name1) request['TranslatedSids']['Sids'] = NULL request['LookupLevel'] = lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta resp = dce.request(request) return resp conf = { "products": [ { "name": "Bitdefender", "services": [ { "name": "bdredline_agent", "description": "Bitdefender Agent RedLine Service" }, { "name": "BDAuxSrv", "description": "Bitdefender Auxiliary Service" }, { "name": "UPDATESRV", "description": "Bitdefender Desktop Update Service" }, { "name": "VSSERV", "description": "Bitdefender Virus Shield" }, { "name": "bdredline", "description": "Bitdefender RedLine Service" } ], "pipes": [ { "name": "local\\msgbus\\antitracker.low\\*", "processes": [ "bdagent.exe" ] }, { "name": "local\\msgbus\\aspam.actions.low\\*", "processes": [ "bdagent.exe" ] }, { "name": "local\\msgbus\\bd.process.broker.pipe", "processes": [ "bdagent.exe", "bdservicehost.exe", "updatesrv.exe" ] }, { "name": "local\\msgbus\\bdagent*", "processes": [ "bdagent.exe" ] }, { "name": "local\\msgbus\\bdauxsrv", "processes": [ "bdagent.exe", "bdntwrk.exe" ] } ] }, { "name": "Windows Defender", "services": [ { "name": "WinDefend", "description": "Windows Defender Antivirus Service" }, { "name": "Sense", "description": "Windows Defender Advanced Threat Protection Service" }, { "name": "WdNisSvc", "description": "Windows Defender Antivirus Network Inspection Service" } ], "pipes": [] }, { "name": "ESET", "services": [ { "name": "ekm", "description": "ESET" }, { "name": "epfw", "description": "ESET" }, { "name": "epfwlwf", "description": "ESET" }, { "name": "epfwwfp", "description": "ESET" }, { "name": "EraAgentSvc", "description": "ESET" } ], "pipes": [ { "name": "nod_scriptmon_pipe", "processes": [ "" ] } ] }, { "name": "CrowdStrike", "services": [ { "name": "CSFalconService", "description": "CrowdStrike Falcon Sensor Service" } ], "pipes": [ { "name": "CrowdStrike\\{*", "processes": [ "CSFalconContainer.exe", "CSFalconService.exe" ] } ] }, { "name": "SentinelOne", "services": [ { "name": "SentinelAgent", "description": "SentinelOne Endpoint Protection Agent" }, { "name": "SentinelStaticEngine", "description": "Manage static engines for SentinelOne Endpoint Protection" }, { "name": "LogProcessorService", "description": "Manage logs for SentinelOne Endpoint Protection" } ], "pipes": [ { "name": "SentinelAgentWorkerCert.*", "processes": [ "" ] }, { "name": "DFIScanner.Etw.*", "processes": [ "SentinelStaticEngine.exe" ] }, { "name": "DFIScanner.Inline.*", "processes": [ "SentinelAgent.exe" ] } ] }, { "name": "Carbon Black App Control", "services": [ { "name": "Parity", "description": "Carbon Black App Control Agent" } ], "pipes": [] }, { "name": "Cybereason", "services": [ { "name": "CybereasonActiveProbe", "description": "Cybereason Active Probe" }, { "name": "CybereasonCRS", "description": "Cybereason Anti-Ransomware" }, { "name": "CybereasonBlocki", "description": "Cybereason Execution Prevention" } ], "pipes": [ { "name": "CybereasonAPConsoleMinionHostIpc_*", "processes": [ "minionhost.exe" ] }, { "name": "CybereasonAPServerProxyIpc_*", "processes": [ "minionhost.exe" ] } ] }, { "name": "Symantec Endpoint Protection", "services": [ { "name": "SepMasterService", "description": "Symantec Endpoint Protection" }, { "name": "SepScanService", "description": "Symantec Endpoint Protection Scan Services" }, { "name": "SNAC", "description": "Symantec Network Access Control" } ], "pipes": [] } ] }