From d4aa81bc2e4ac9c6f1ad051501c4176d90933905 Mon Sep 17 00:00:00 2001 From: XiaoliChan <2209553467@qq.com> Date: Sat, 26 Aug 2023 11:42:54 +0800 Subject: [PATCH] [wmi] Finished todo list after PR #114 Signed-off-by: XiaoliChan <2209553467@qq.com> --- cme/modules/enum_dns.py | 4 +- cme/modules/get_netconnections.py | 4 +- cme/modules/rdp.py | 1 - cme/protocols/wmi.py | 62 ++++++++++--------------------- cme/protocols/wmi/proto_args.py | 6 +-- 5 files changed, 26 insertions(+), 51 deletions(-) diff --git a/cme/modules/enum_dns.py b/cme/modules/enum_dns.py index 0e0c2ae0..b738c37c 100644 --- a/cme/modules/enum_dns.py +++ b/cme/modules/enum_dns.py @@ -13,7 +13,7 @@ class CMEModule: name = "enum_dns" description = "Uses WMI to dump DNS from an AD DNS Server" - supported_protocols = ["smb"] + supported_protocols = ["wmi"] opsec_safe = True multiple_hosts = True @@ -72,4 +72,4 @@ class CMEModule: log_name = "DNS-Enum-{}-{}.log".format(connection.args.target[0], datetime.now().strftime("%Y-%m-%d_%H%M%S")) write_log(data, log_name) - context.log.display(f"Saved raw output to {log_name}") + context.log.display(f"Saved raw output to ~/.cme/logs/{log_name}") diff --git a/cme/modules/get_netconnections.py b/cme/modules/get_netconnections.py index 4eeb7a78..578ba541 100755 --- a/cme/modules/get_netconnections.py +++ b/cme/modules/get_netconnections.py @@ -15,7 +15,7 @@ class CMEModule: name = "get_netconnections" description = "Uses WMI to query network connections." - supported_protocols = ["smb"] + supported_protocols = ["wmi"] opsec_safe = True multiple_hosts = True @@ -37,4 +37,4 @@ class CMEModule: log_name = "network-connections-{}-{}.log".format(connection.args.target[0], datetime.now().strftime("%Y-%m-%d_%H%M%S")) write_log(json.dumps(data), log_name) - context.log.display("Saved raw output to {}".format(log_name)) + context.log.display(f"Saved raw output to ~/.cme/logs/{log_name}") diff --git a/cme/modules/rdp.py b/cme/modules/rdp.py index ee9d69af..a0eba628 100644 --- a/cme/modules/rdp.py +++ b/cme/modules/rdp.py @@ -16,7 +16,6 @@ from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_LEVEL_PKT_PRIVACY class CMEModule: name = "rdp" description = "Enables/Disables RDP" - #supported_protocols = ["smb"] supported_protocols = ["smb" ,"wmi"] opsec_safe = True multiple_hosts = True diff --git a/cme/protocols/wmi.py b/cme/protocols/wmi.py index 2e995177..72cc7a7a 100644 --- a/cme/protocols/wmi.py +++ b/cme/protocols/wmi.py @@ -175,61 +175,39 @@ class wmi(connection): try: dcom = DCOMConnection(self.conn.getRemoteName(), self.username, self.password, self.domain, self.lmhash, self.nthash, oxidResolver=True, doKerberos=self.doKerberos ,kdcHost=self.kdcHost, aesKey=self.aesKey) iInterface = dcom.CoCreateInstanceEx(CLSID_WbemLevel1Login, IID_IWbemLevel1Login) - self.firewall_check(iInterface, self.args.rpc_timeout) + flag, self.stringBinding = dcom_FirewallChecker(iInterface, self.args.rpc_timeout) except Exception as e: try: dcom.disconnect() except: pass - if str(e).lower().find("connect") > 0: - self.logger.fail(f'Check admin error: dcom initialization failed with stringbinding: "{self.stringBinding}", please try "--rpc-timeout" option. (probably is admin)') - elif str(e).find("access_denied") > 0: - pass - else: + if not str(e).find("access_denied") > 0: self.logger.fail(str(e)) else: - try: - iWbemLevel1Login = IWbemLevel1Login(iInterface) - iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) - except Exception as e: + if not flag: + self.logger.fail(f'Check admin error: dcom initialization failed with stringbinding: "{self.stringBinding}", please try "--rpc-timeout" option. (probably is admin)') try: dcom.disconnect() except: pass - - if str(e).find("access_denied") > 0: - pass - else: - self.logger.fail(str(e)) else: - dcom.disconnect() - self.logger.extra['protocol'] = "WMI" - self.admin_privs = True - return + try: + iWbemLevel1Login = IWbemLevel1Login(iInterface) + iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) + except Exception as e: + try: + dcom.disconnect() + except: + pass - def firewall_check(self, iInterface ,timeout): - stringBindings = iInterface.get_cinstance().get_string_bindings() - for strBinding in stringBindings: - if strBinding['wTowerId'] == 7: - if strBinding['aNetworkAddr'].find('[') >= 0: - binding, _, bindingPort = strBinding['aNetworkAddr'].partition('[') - bindingPort = '[' + bindingPort + if not str(e).find("access_denied") > 0: + self.logger.fail(str(e)) else: - binding = strBinding['aNetworkAddr'] - bindingPort = '' - - if binding.upper().find(iInterface.get_target().upper()) >= 0: - stringBinding = 'ncacn_ip_tcp:' + strBinding['aNetworkAddr'][:-1] - break - elif iInterface.is_fqdn() and binding.upper().find(iInterface.get_target().upper().partition('.')[0]) >= 0: - stringBinding = 'ncacn_ip_tcp:%s%s' % (iInterface.get_target(), bindingPort) - - self.stringBinding = stringBinding - rpctransport = transport.DCERPCTransportFactory(stringBinding) - rpctransport.set_connect_timeout(timeout) - rpctransport.connect() - rpctransport.disconnect() + dcom.disconnect() + self.logger.extra['protocol'] = "WMI" + self.admin_privs = True + return def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="", kdcHost="", useCache=False): logging.getLogger("impacket").disabled = True @@ -417,7 +395,7 @@ class wmi(connection): WQL = self.args.wmi.strip('\n') if not namespace: - namespace = self.args.namespace + namespace = self.args.wmi_namespace try: dcom = DCOMConnection(self.conn.getRemoteName(), self.username, self.password, self.domain, self.lmhash, self.nthash, oxidResolver=True, doKerberos=self.doKerberos ,kdcHost=self.kdcHost, aesKey=self.aesKey) @@ -428,7 +406,6 @@ class wmi(connection): iEnumWbemClassObject = iWbemServices.ExecQuery(WQL) except Exception as e: self.logger.fail('Execute WQL error: {}'.format(e)) - iWbemServices.RemRelease() dcom.disconnect() return False else: @@ -447,7 +424,6 @@ class wmi(connection): break try: iEnumWbemClassObject.RemRelease() - iWbemServices.RemRelease() dcom.disconnect() except: pass diff --git a/cme/protocols/wmi/proto_args.py b/cme/protocols/wmi/proto_args.py index 46c6ea7f..a8b779c9 100644 --- a/cme/protocols/wmi/proto_args.py +++ b/cme/protocols/wmi/proto_args.py @@ -4,7 +4,7 @@ def proto_args(parser, std_parser, module_parser): wmi_parser = parser.add_parser('wmi', help="own stuff using WMI", parents=[std_parser, module_parser], conflict_handler='resolve') wmi_parser.add_argument("-H", '--hash', metavar="HASH", dest='hash', nargs='+', default=[], help='NTLM hash(es) or file(s) containing NTLM hashes') wmi_parser.add_argument("--port", type=int, choices={135}, default=135, help="WMI port (default: 135)") - wmi_parser.add_argument("--rpc-timeout", help="RPC connection timeout, default 2 secondes", type=int, default=2) + wmi_parser.add_argument("--rpc-timeout", help="RPC/DCOM(WMI) connection timeout, default is %(default)s secondes", type=int, default=2) # For domain options dgroup = wmi_parser.add_mutually_exclusive_group() @@ -12,8 +12,8 @@ def proto_args(parser, std_parser, module_parser): dgroup.add_argument("--local-auth", action='store_true', help='Authenticate locally to each target') egroup = wmi_parser.add_argument_group("Mapping/Enumeration", "Options for Mapping/Enumerating") - egroup.add_argument("-q", metavar='QUERY', dest='wmi',type=str, help='Issues the specified WMI query') - egroup.add_argument("--namespace", metavar='NAMESPACE', type=str, default='root\\cimv2', help='WMI Namespace (default: root\\cimv2)') + egroup.add_argument("--wmi", metavar='QUERY', dest='wmi',type=str, help='Issues the specified WMI query') + egroup.add_argument("--wmi-namespace", metavar='NAMESPACE', type=str, default='root\\cimv2', help='WMI Namespace (default: root\\cimv2)') cgroup = wmi_parser.add_argument_group("Command Execution", "Options for executing commands") cgroup.add_argument("--no-output", action="store_true", help="do not retrieve command output")