From ab6509daf1418e60e0cd440cb11c54e56cd6af69 Mon Sep 17 00:00:00 2001 From: XiaoliChan <2209553467@qq.com> Date: Sat, 9 Sep 2023 12:25:34 +0800 Subject: [PATCH 1/4] [wmi] Improve admin check & bug fix Signed-off-by: XiaoliChan <2209553467@qq.com> --- cme/connection.py | 6 +++++- cme/protocols/wmi.py | 41 +++++++++++++++++------------------------ poetry.lock | 7 +++---- pyproject.toml | 2 +- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/cme/connection.py b/cme/connection.py index 09aa0ef3..5c86b196 100755 --- a/cme/connection.py +++ b/cme/connection.py @@ -42,7 +42,7 @@ def requires_admin(func): return wraps(func)(_decorator) -def dcom_FirewallChecker(iInterface, timeout): +def dcom_FirewallChecker(iInterface, timeout=None): stringBindings = iInterface.get_cinstance().get_string_bindings() for strBinding in stringBindings: if strBinding['wTowerId'] == 7: @@ -60,6 +60,10 @@ def dcom_FirewallChecker(iInterface, timeout): stringBinding = 'ncacn_ip_tcp:%s%s' % (iInterface.get_target(), bindingPort) if "stringBinding" not in locals(): return True, None + + # if not timeout, which means not doing firewall check. + if not timeout: + return True, stringBinding try: rpctransport = transport.DCERPCTransportFactory(stringBinding) rpctransport.set_connect_timeout(timeout) diff --git a/cme/protocols/wmi.py b/cme/protocols/wmi.py index c5eb8fb9..72e2a5a6 100644 --- a/cme/protocols/wmi.py +++ b/cme/protocols/wmi.py @@ -164,36 +164,29 @@ class wmi(connection): def check_if_admin(self): 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) + dcom.set_connect_timeout(self.args.rpc_timeout) iInterface = dcom.CoCreateInstanceEx(CLSID_WbemLevel1Login, IID_IWbemLevel1Login) - flag, self.stringBinding = dcom_FirewallChecker(iInterface, self.args.rpc_timeout) + _, self.stringBinding = dcom_FirewallChecker(iInterface) + iWbemLevel1Login = IWbemLevel1Login(iInterface) + iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) except Exception as e: if "dcom" in locals(): dcom.disconnect() - if not str(e).find("access_denied") > 0: - self.logger.fail(str(e)) - else: - if not flag or not self.stringBinding: - dcom.disconnect() - error_msg = f'Check admin error: dcom initialization failed with stringbinding: "{self.stringBinding}", please try "--rpc-timeout" option. (probably is admin)' - - if not self.stringBinding: - error_msg = "Check admin error: dcom initialization failed: can't get target stringbinding, maybe cause by IPv6 or any other issues, please check your target again" - - self.logger.fail(error_msg) if not flag else self.logger.debug(error_msg) - else: - try: - iWbemLevel1Login = IWbemLevel1Login(iInterface) - iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) - except Exception as e: - dcom.disconnect() + error_msg = str(e).lower() - if not str(e).find("access_denied") > 0: - self.logger.fail(str(e)) - else: - dcom.disconnect() - self.logger.extra['protocol'] = "WMI" - self.admin_privs = True + if error_msg.find("access_denied") > 0: + pass + else: + if error_msg.find("timed out") > 0 or error_msg.lower().find("connection refused") > 0: + error_msg = f'Check admin error: dcom initialization failed with stringbinding: "{self.stringBinding}", please try "--rpc-timeout" option. (probably is admin)' + elif not self.stringBinding: + error_msg = "Check admin error: dcom initialization failed: can't get target stringbinding, maybe cause by IPv6 or any other issues, please check your target again" + self.logger.fail(error_msg) + else: + 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): diff --git a/poetry.lock b/poetry.lock index 5065c3d1..c3d433fd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -853,9 +853,8 @@ files = [ [[package]] name = "impacket" -version = "0.12.0.dev1+20230816.160145.f6e03b99" +version = "0.12.0.dev1+20230905.183005.f0a4bf2b" description = "Network protocols Constructors and Dissectors" -category = "main" optional = false python-versions = "*" files = [] @@ -876,9 +875,9 @@ six = "*" [package.source] type = "git" -url = "https://github.com/mpgn/impacket.git" +url = "https://github.com/XiaoliChan/impacket.git" reference = "gkdi" -resolved_reference = "f6e03b99ce9da7f502a03488c8d26151236fa679" +resolved_reference = "0ccac0aa8e07655678b717debc97696581080d9b" [[package]] name = "importlib-metadata" diff --git a/pyproject.toml b/pyproject.toml index 4b6bff24..cbc915ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ neo4j = "^4.1.1" pylnk3 = "^0.4.2" pypsrp = "^0.7.0" paramiko = "^2.7.2" -impacket = { git = "https://github.com/mpgn/impacket.git", branch = "gkdi" } +impacket = { git = "https://github.com/XiaoliChan/impacket.git", branch = "gkdi" } dsinternals = "^1.2.4" xmltodict = "^0.12.0" terminaltables = "^3.1.0" From 823f9cadf26efd1fd83c5503028bfcb09c4b3cbf Mon Sep 17 00:00:00 2001 From: XiaoliChan <2209553467@qq.com> Date: Sat, 9 Sep 2023 22:13:12 +0800 Subject: [PATCH 2/4] [wmi] switch imapcket back to mpgn's forked Signed-off-by: XiaoliChan <2209553467@qq.com> --- poetry.lock | 6 +++--- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index c3d433fd..25c43c42 100644 --- a/poetry.lock +++ b/poetry.lock @@ -853,7 +853,7 @@ files = [ [[package]] name = "impacket" -version = "0.12.0.dev1+20230905.183005.f0a4bf2b" +version = "0.12.0.dev1+20230909.154612.3beeda7c" description = "Network protocols Constructors and Dissectors" optional = false python-versions = "*" @@ -875,9 +875,9 @@ six = "*" [package.source] type = "git" -url = "https://github.com/XiaoliChan/impacket.git" +url = "https://github.com/mpgn/impacket.git" reference = "gkdi" -resolved_reference = "0ccac0aa8e07655678b717debc97696581080d9b" +resolved_reference = "3beeda7c3188936ed20f58c2c169430c2cfdfb1a" [[package]] name = "importlib-metadata" diff --git a/pyproject.toml b/pyproject.toml index cbc915ed..4b6bff24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ neo4j = "^4.1.1" pylnk3 = "^0.4.2" pypsrp = "^0.7.0" paramiko = "^2.7.2" -impacket = { git = "https://github.com/XiaoliChan/impacket.git", branch = "gkdi" } +impacket = { git = "https://github.com/mpgn/impacket.git", branch = "gkdi" } dsinternals = "^1.2.4" xmltodict = "^0.12.0" terminaltables = "^3.1.0" From 20459ef3fda9d1ecc0b394ea70c281012ec055af Mon Sep 17 00:00:00 2001 From: XiaoliChan <2209553467@qq.com> Date: Thu, 14 Sep 2023 11:14:30 +0800 Subject: [PATCH 3/4] [wmi] Revert new check_admin function Signed-off-by: XiaoliChan <2209553467@qq.com> --- cme/connection.py | 6 +----- cme/protocols/wmi.py | 41 ++++++++++++++++++++++++----------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/cme/connection.py b/cme/connection.py index 5c86b196..09aa0ef3 100755 --- a/cme/connection.py +++ b/cme/connection.py @@ -42,7 +42,7 @@ def requires_admin(func): return wraps(func)(_decorator) -def dcom_FirewallChecker(iInterface, timeout=None): +def dcom_FirewallChecker(iInterface, timeout): stringBindings = iInterface.get_cinstance().get_string_bindings() for strBinding in stringBindings: if strBinding['wTowerId'] == 7: @@ -60,10 +60,6 @@ def dcom_FirewallChecker(iInterface, timeout=None): stringBinding = 'ncacn_ip_tcp:%s%s' % (iInterface.get_target(), bindingPort) if "stringBinding" not in locals(): return True, None - - # if not timeout, which means not doing firewall check. - if not timeout: - return True, stringBinding try: rpctransport = transport.DCERPCTransportFactory(stringBinding) rpctransport.set_connect_timeout(timeout) diff --git a/cme/protocols/wmi.py b/cme/protocols/wmi.py index 72e2a5a6..dc38ecac 100644 --- a/cme/protocols/wmi.py +++ b/cme/protocols/wmi.py @@ -164,29 +164,36 @@ class wmi(connection): def check_if_admin(self): 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) - dcom.set_connect_timeout(self.args.rpc_timeout) iInterface = dcom.CoCreateInstanceEx(CLSID_WbemLevel1Login, IID_IWbemLevel1Login) - _, self.stringBinding = dcom_FirewallChecker(iInterface) - iWbemLevel1Login = IWbemLevel1Login(iInterface) - iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) + flag, self.stringBinding = dcom_FirewallChecker(iInterface, self.args.rpc_timeout) except Exception as e: if "dcom" in locals(): dcom.disconnect() - error_msg = str(e).lower() - - if error_msg.find("access_denied") > 0: - pass - else: - if error_msg.find("timed out") > 0 or error_msg.lower().find("connection refused") > 0: - error_msg = f'Check admin error: dcom initialization failed with stringbinding: "{self.stringBinding}", please try "--rpc-timeout" option. (probably is admin)' - elif not self.stringBinding: + if not str(e).lower().find("access_denied") >=0: + self.logger.fail(str(e)) + else: + if not flag or not self.stringBinding: + dcom.disconnect() + error_msg = f'Check admin error: dcom initialization failed with stringbinding: "{self.stringBinding}", please try "--rpc-timeout" option. (probably is admin)' + + if not self.stringBinding: error_msg = "Check admin error: dcom initialization failed: can't get target stringbinding, maybe cause by IPv6 or any other issues, please check your target again" - self.logger.fail(error_msg) - else: - dcom.disconnect() - self.logger.extra['protocol'] = "WMI" - self.admin_privs = True + + self.logger.fail(error_msg) if not flag else self.logger.debug(error_msg) + else: + try: + iWbemLevel1Login = IWbemLevel1Login(iInterface) + iWbemServices = iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL) + except Exception as e: + dcom.disconnect() + + if not str(e).lower().find("access_denied") >=0: + self.logger.fail(str(e)) + else: + 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): From 0eccd0e60d24bba86cb24371d0baaef241776606 Mon Sep 17 00:00:00 2001 From: XiaoliChan <2209553467@qq.com> Date: Thu, 14 Sep 2023 16:32:31 +0800 Subject: [PATCH 4/4] [wmi] Not 'find' anymore Signed-off-by: XiaoliChan <2209553467@qq.com> --- cme/protocols/wmi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cme/protocols/wmi.py b/cme/protocols/wmi.py index dc38ecac..da1b56f4 100644 --- a/cme/protocols/wmi.py +++ b/cme/protocols/wmi.py @@ -170,7 +170,7 @@ class wmi(connection): if "dcom" in locals(): dcom.disconnect() - if not str(e).lower().find("access_denied") >=0: + if "access_denied" not in str(e).lower(): self.logger.fail(str(e)) else: if not flag or not self.stringBinding: @@ -188,7 +188,7 @@ class wmi(connection): except Exception as e: dcom.disconnect() - if not str(e).lower().find("access_denied") >=0: + if "access_denied" not in str(e).lower(): self.logger.fail(str(e)) else: dcom.disconnect()