From 86514796921bf3a1bdfd1b1b1a4e06c7eb7db894 Mon Sep 17 00:00:00 2001 From: mpgn Date: Mon, 5 Jul 2021 21:11:35 +0200 Subject: [PATCH] Add spooler service module Add spooler service module to detect if the service is enabled or not using RCP call from https://raw.githubusercontent.com/SecureAuthCorp/impacket/master/examples/rpcdump.py --- cme/modules/spooler.py | 106 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 cme/modules/spooler.py diff --git a/cme/modules/spooler.py b/cme/modules/spooler.py new file mode 100644 index 00000000..9b410ee3 --- /dev/null +++ b/cme/modules/spooler.py @@ -0,0 +1,106 @@ +from impacket.examples import logger +from impacket import uuid, version +from impacket.dcerpc.v5 import transport, epm +from impacket.dcerpc.v5.rpch import RPC_PROXY_INVALID_RPC_PORT_ERR, \ + RPC_PROXY_CONN_A1_0X6BA_ERR, RPC_PROXY_CONN_A1_404_ERR, \ + RPC_PROXY_RPC_OUT_DATA_404_ERR + +KNOWN_PROTOCOLS = { + 135: {'bindstr': r'ncacn_ip_tcp:%s[135]'}, + 445: {'bindstr': r'ncacn_np:%s[\pipe\epmapper]'}, + } + +class CMEModule: + ''' + For printnightmare: detect if print spooler is enabled or not. Then use @cube0x0's project https://github.com/cube0x0/CVE-2021-1675 or Mimikatz from Benjamin Delpy + Module by @mpgn_x64 + + ''' + name = 'spooler' + description = 'Detect if print spooler is enabled or not' + supported_protocols = ['smb'] + opsec_safe= True + multiple_hosts = True + + def options(self, context, module_options): + self.port = 135 + if 'PORT' in module_options: + self.port = int(module_options['PORT']) + + def on_login(self, context, connection): + + entries = [] + lmhash = getattr(connection, "lmhash", "") + nthash = getattr(connection, "nthash", "") + + self.__stringbinding = KNOWN_PROTOCOLS[self.port]['bindstr'] % connection.host + logging.debug('StringBinding %s' % self.__stringbinding) + rpctransport = transport.DCERPCTransportFactory(self.__stringbinding) + rpctransport.set_credentials(connection.username, connection.password, connection.domain, lmhash, nthash) + rpctransport.setRemoteHost(connection.host) + rpctransport.set_dport(self.port) + + try: + entries = self.__fetchList(rpctransport) + except Exception as e: + error_text = 'Protocol failed: %s' % e + logging.critical(error_text) + + if RPC_PROXY_INVALID_RPC_PORT_ERR in error_text or \ + RPC_PROXY_RPC_OUT_DATA_404_ERR in error_text or \ + RPC_PROXY_CONN_A1_404_ERR in error_text or \ + RPC_PROXY_CONN_A1_0X6BA_ERR in error_text: + logging.critical("This usually means the target does not allow " + "to connect to its epmapper using RpcProxy.") + return + + # Display results. + endpoints = {} + # Let's groups the UUIDS + for entry in entries: + binding = epm.PrintStringBinding(entry['tower']['Floors']) + tmpUUID = str(entry['tower']['Floors'][0]) + if (tmpUUID in endpoints) is not True: + endpoints[tmpUUID] = {} + endpoints[tmpUUID]['Bindings'] = list() + if uuid.uuidtup_to_bin(uuid.string_to_uuidtup(tmpUUID))[:18] in epm.KNOWN_UUIDS: + endpoints[tmpUUID]['EXE'] = epm.KNOWN_UUIDS[uuid.uuidtup_to_bin(uuid.string_to_uuidtup(tmpUUID))[:18]] + else: + endpoints[tmpUUID]['EXE'] = 'N/A' + endpoints[tmpUUID]['annotation'] = entry['annotation'][:-1].decode('utf-8') + endpoints[tmpUUID]['Bindings'].append(binding) + + if tmpUUID[:36] in epm.KNOWN_PROTOCOLS: + endpoints[tmpUUID]['Protocol'] = epm.KNOWN_PROTOCOLS[tmpUUID[:36]] + else: + endpoints[tmpUUID]['Protocol'] = "N/A" + + for endpoint in list(endpoints.keys()): + if "MS-RPRN" in endpoints[endpoint]['Protocol']: + logging.debug("Protocol: %s " % endpoints[endpoint]['Protocol']) + logging.debug("Provider: %s " % endpoints[endpoint]['EXE']) + logging.debug("UUID : %s %s" % (endpoint, endpoints[endpoint]['annotation'])) + logging.debug("Bindings: ") + for binding in endpoints[endpoint]['Bindings']: + logging.debug(" %s" % binding) + logging.debug("") + context.log.highlight('Spooler service enabled') + break + + if entries: + num = len(entries) + if 1 == num: + logging.info('Received one endpoint.') + else: + logging.info('Received %d endpoints.' % num) + else: + logging.info('No endpoints found.') + + + def __fetchList(self, rpctransport): + dce = rpctransport.get_dce_rpc() + dce.connect() + resp = epm.hept_lookup(None, dce=dce) + dce.disconnect() + return resp +