Merge remote-tracking branch 'upstream/master' into wmi

This commit is contained in:
XiaoliChan
2023-08-26 11:07:19 +08:00
13 changed files with 411 additions and 104 deletions
+27 -1
View File
@@ -15,6 +15,8 @@ from cme.helpers.logger import highlight
from cme.logger import cme_logger, CMEAdapter
from cme.context import Context
from impacket.dcerpc.v5 import transport
sem = BoundedSemaphore(1)
global_failed_logins = 0
user_failed_logins = {}
@@ -31,7 +33,6 @@ def gethost_addrinfo(hostname):
return sa[0]
return canonname
def requires_admin(func):
def _decorator(self, *args, **kwargs):
if self.admin_privs is False:
@@ -40,6 +41,31 @@ def requires_admin(func):
return wraps(func)(_decorator)
def dcom_FirewallChecker(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
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)
try:
rpctransport = transport.DCERPCTransportFactory(stringBinding)
rpctransport.set_connect_timeout(timeout)
rpctransport.connect()
rpctransport.disconnect()
except:
return False, stringBinding
else:
return True, stringBinding
class connection(object):
def __init__(self, args, db, host):
+29 -1
View File
@@ -518,8 +518,36 @@ conf = {
{
"name": "exploitProtectionIPC",
"processes": ["AVKWCtlx64.exe"],
}
},
],
},
{
"name": "Panda Adaptive Defense 360",
"services": [
{
"name": "PandaAetherAgent",
"description": "Panda Endpoint Agent",
},
{
"name": "PSUAService",
"description": "Panda Product Service"
},
{
"name": "NanoServiceMain",
"description": "Panda Cloud Antivirus Service",
},
],
"pipes": [
{
"name": "NNS_API_IPC_SRV_ENDPOINT",
"processes": ["PSANHost.exe"],
},
{
"name": "PSANMSrvcPpal",
"processes": ["PSUAService.exe"],
},
],
}
]
}
+5 -4
View File
@@ -28,11 +28,12 @@ class CMEModule:
def on_admin_login(self, context, connection):
data = []
cards = connection.wmi(f"select DNSDomainSuffixSearchOrder, IPAddress from win32_networkadapterconfiguration")
for c in cards:
if c["IPAddress"].get("value"):
context.log.success(f"IP Address: {c['IPAddress']['value']}\tSearch Domain: {c['DNSDomainSuffixSearchOrder']['value']}")
if cards:
for c in cards:
if c["IPAddress"].get("value"):
context.log.success(f"IP Address: {c['IPAddress']['value']}\tSearch Domain: {c['DNSDomainSuffixSearchOrder']['value']}")
data.append(cards)
data.append(cards)
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)
+254 -22
View File
@@ -3,14 +3,21 @@
from sys import exit
from cme.connection import dcom_FirewallChecker
from impacket.dcerpc.v5 import rrp
from impacket.examples.secretsdump import RemoteOperations
from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom import wmi
from impacket.dcerpc.v5.dtypes import NULL
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"]
supported_protocols = ["smb" ,"wmi"]
opsec_safe = True
multiple_hosts = True
@@ -21,26 +28,99 @@ class CMEModule:
def options(self, context, module_options):
"""
ACTION Enable/Disable RDP (choices: enable, disable)
ACTION Enable/Disable RDP (choices: enable, disable, enable-ram, disable-ram)
METHOD wmi(ncacn_ip_tcp)/smb(ncacn_np) (choices: wmi, smb, default is wmi)
OLD For old version system (under NT6, like: server 2003)
DCOM-TIMEOUT Set the Dcom connection timeout for WMI method (Default is 10 seconds)
cme smb 192.168.1.1 -u {user} -p {password} -M rdp -o ACTION={enable, disable, enable-ram, disable-ram} {OLD=true} {DCOM-TIMEOUT=5}
cme smb 192.168.1.1 -u {user} -p {password} -M rdp -o METHOD=smb ACTION={enable, disable, enable-ram, disable-ram}
cme smb 192.168.1.1 -u {user} -p {password} -M rdp -o METHOD=wmi ACTION={enable, disable, enable-ram, disable-ram} {OLD=true} {DCOM-TIMEOUT=5}
"""
if not "ACTION" in module_options:
context.log.fail("ACTION option not specified!")
exit(1)
if module_options["ACTION"].lower() not in ["enable", "disable"]:
if module_options["ACTION"].lower() not in ["enable", "disable", "enable-ram", "disable-ram"]:
context.log.fail("Invalid value for ACTION option!")
exit(1)
self.action = module_options["ACTION"].lower()
if not "METHOD" in module_options:
self.method = "wmi"
else:
self.method = module_options['METHOD'].lower()
if context.protocol != "smb" and self.method == "smb":
context.log.fail(f"Protocol: {context.protocol} not support this method")
exit(1)
if not "DCOM-TIMEOUT" in module_options:
self.dcom_timeout = 10
else:
try:
self.dcom_timeout = int(module_options['DCOM-TIMEOUT'])
except:
context.log.fail("Wrong DCOM timeout value!")
exit(1)
if not "OLD" in module_options:
self.oldSystem = False
else:
self.oldSystem = True
def on_admin_login(self, context, connection):
if self.action == "enable":
self.rdp_enable(context, connection.conn)
elif self.action == "disable":
self.rdp_disable(context, connection.conn)
# Preparation for wmi protocol
if self.method == "smb":
context.log.info("Executing over SMB(ncacn_np)")
try:
smb_rdp = rdp_SMB(context, connection)
if "ram" in self.action:
smb_rdp.rdp_RAMWrapper(self.action)
else:
smb_rdp.rdp_Wrapper(self.action)
except Exception as e:
context.log.fail(f"Enable RDP via smb error: {str(e)}")
elif self.method == "wmi":
context.log.info("Executing over WMI(ncacn_ip_tcp)")
try:
wmi_rdp = rdp_WMI(context, connection, self.dcom_timeout)
except Exception as e:
context.log.fail(f"Unexpected wmi error: {str(e)}")
wmi_rdp._rdp_WMI__dcom.disconnect()
def rdp_enable(self, context, smbconnection):
remoteOps = RemoteOperations(smbconnection, False)
if hasattr(wmi_rdp, '_rdp_WMI__iWbemLevel1Login'):
if "ram" in self.action:
# Nt version under 6 not support RAM.
try:
wmi_rdp.rdp_RAMWrapper(self.action)
except Exception as e:
if "WBEM_E_NOT_FOUND" in str(e):
context.log.fail("System version under NT6 not support restricted admin mode")
else:
context.log.fail(str(e))
pass
wmi_rdp._rdp_WMI__dcom.disconnect()
else:
try:
wmi_rdp.rdp_Wrapper(self.action, self.oldSystem)
except Exception as e:
if "WBEM_E_INVALID_NAMESPACE" in str(e):
context.log.fail('Looks like target system version is under NT6, please add "OLD=true" in module options.')
else:
context.log.fail(str(e))
pass
wmi_rdp._rdp_WMI__dcom.disconnect()
class rdp_SMB:
def __init__(self, context, connection):
self.context = context
self.__smbconnection = connection.conn
self.__execute = connection.execute
self.logger = context.log
def rdp_Wrapper(self, action):
remoteOps = RemoteOperations(self.__smbconnection, False)
remoteOps.enableRegistry()
if remoteOps._RemoteOperations__rrp:
@@ -54,26 +134,32 @@ class CMEModule:
)
keyHandle = ans["phkResult"]
rrp.hBaseRegSetValue(
ans = rrp.hBaseRegSetValue(
remoteOps._RemoteOperations__rrp,
keyHandle,
"fDenyTSConnections\x00",
"fDenyTSConnections",
rrp.REG_DWORD,
0,
0 if action == "enable" else 1,
)
rtype, data = rrp.hBaseRegQueryValue(remoteOps._RemoteOperations__rrp, keyHandle, "fDenyTSConnections\x00")
rtype, data = rrp.hBaseRegQueryValue(remoteOps._RemoteOperations__rrp, keyHandle, "fDenyTSConnections")
if int(data) == 0:
context.log.success("RDP enabled successfully")
self.logger.success("Enable RDP via SMB(ncacn_np) successfully")
elif int(data) == 1:
self.logger.success("Disable RDP via SMB(ncacn_np) successfully")
self.firewall_CMD(action)
if action == "enable":
self.query_RDPPort(remoteOps, regHandle)
try:
remoteOps.finish()
except:
pass
def rdp_disable(self, context, smbconnection):
remoteOps = RemoteOperations(smbconnection, False)
def rdp_RAMWrapper(self, action):
remoteOps = RemoteOperations(self.__smbconnection, False)
remoteOps.enableRegistry()
if remoteOps._RemoteOperations__rrp:
@@ -83,24 +169,170 @@ class CMEModule:
ans = rrp.hBaseRegOpenKey(
remoteOps._RemoteOperations__rrp,
regHandle,
"SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
"System\\CurrentControlSet\\Control\\Lsa",
)
keyHandle = ans["phkResult"]
rrp.hBaseRegSetValue(
remoteOps._RemoteOperations__rrp,
keyHandle,
"fDenyTSConnections\x00",
"DisableRestrictedAdmin",
rrp.REG_DWORD,
1,
0 if action == "enable-ram" else 1,
)
rtype, data = rrp.hBaseRegQueryValue(remoteOps._RemoteOperations__rrp, keyHandle, "fDenyTSConnections\x00")
rtype, data = rrp.hBaseRegQueryValue(remoteOps._RemoteOperations__rrp, keyHandle, "DisableRestrictedAdmin")
if int(data) == 1:
context.log.success("RDP disabled successfully")
if int(data) == 0:
self.logger.success("Enable RDP Restricted Admin Mode via SMB(ncacn_np) succeed")
elif int(data) == 1:
self.logger.success("Disable RDP Restricted Admin Mode via SMB(ncacn_np) succeed")
try:
remoteOps.finish()
except:
pass
def query_RDPPort(self, remoteOps, regHandle):
if remoteOps:
ans = rrp.hBaseRegOpenKey(
remoteOps._RemoteOperations__rrp,
regHandle,
"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",
)
keyHandle = ans["phkResult"]
rtype, data = rrp.hBaseRegQueryValue(remoteOps._RemoteOperations__rrp, keyHandle, "PortNumber")
self.logger.success(f"RDP Port: {str(data)}")
# https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/manage/enable_rdp.rb
def firewall_CMD(self, action):
cmd = f"netsh firewall set service type = remotedesktop mode = {action}"
self.logger.info("Configure firewall via execute command.")
output = self.__execute(cmd, True)
if output:
self.logger.success(f"{action.capitalize()} RDP firewall rules via cmd succeed")
else:
self.logger.fail(f"{action.capitalize()} RDP firewall rules via cmd failed, maybe got detected by AV software.")
class rdp_WMI:
def __init__(self, context, connection, timeout):
self.logger = context.log
self.__currentprotocol = context.protocol
# From dfscoerce.py
self.__username=connection.username
self.__password=connection.password
self.__domain=connection.domain
self.__lmhash=connection.lmhash
self.__nthash=connection.nthash
self.__target=connection.host if not connection.kerberos else connection.hostname + "." + connection.domain
self.__doKerberos=connection.kerberos
self.__kdcHost=connection.kdcHost
self.__aesKey=connection.aesKey
self.__timeout = timeout
self.__dcom = DCOMConnection(
self.__target,
self.__username,
self.__password,
self.__domain,
self.__lmhash,
self.__nthash,
self.__aesKey,
oxidResolver=True,
doKerberos=self.__doKerberos,
kdcHost=self.__kdcHost,
)
iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
if self.__currentprotocol == "smb":
flag, self.__stringBinding = dcom_FirewallChecker(iInterface, self.__timeout)
if not flag:
self.logger.fail(f'WMIEXEC: Dcom initialization failed on connection with stringbinding: "{self.__stringBinding}", please increase the timeout with the module option "DCOM-TIMEOUT=10". If it\'s still failing maybe something is blocking the RPC connection, try "METHOD=smb"')
# Make it force break function
self.__dcom.disconnect()
return
self.__iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
def rdp_Wrapper(self, action, old=False):
if old == False:
# According to this document: https://learn.microsoft.com/en-us/windows/win32/termserv/win32-tslogonsetting
# Authentication level must set to RPC_C_AUTHN_LEVEL_PKT_PRIVACY when accessing namespace "//./root/cimv2/TerminalServices"
iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/cimv2/TerminalServices', NULL, NULL)
iWbemServices.get_dce_rpc().set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
self.__iWbemLevel1Login.RemRelease()
iEnumWbemClassObject = iWbemServices.ExecQuery("SELECT * FROM Win32_TerminalServiceSetting")
iWbemClassObject = iEnumWbemClassObject.Next(0xffffffff,1)[0]
if action == 'enable':
self.logger.info("Enabled RDP services and setting up firewall.")
iWbemClassObject.SetAllowTSConnections(1,1)
elif action == 'disable':
self.logger.info("Disabled RDP services and setting up firewall.")
iWbemClassObject.SetAllowTSConnections(0,0)
else:
iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
self.__iWbemLevel1Login.RemRelease()
iEnumWbemClassObject = iWbemServices.ExecQuery("SELECT * FROM Win32_TerminalServiceSetting")
iWbemClassObject = iEnumWbemClassObject.Next(0xffffffff,1)[0]
if action == 'enable':
self.logger.info("Enabling RDP services (old system not support setting up firewall)")
iWbemClassObject.SetAllowTSConnections(1)
elif action == 'disable':
self.logger.info("Disabling RDP services (old system not support setting up firewall)")
iWbemClassObject.SetAllowTSConnections(0)
self.query_RDPResult(old)
if action == 'enable':
self.query_RDPPort()
# Need to create new iWbemServices interface in order to flush results
def query_RDPResult(self, old=False):
if old == False:
iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/cimv2/TerminalServices', NULL, NULL)
iWbemServices.get_dce_rpc().set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
self.__iWbemLevel1Login.RemRelease()
iEnumWbemClassObject = iWbemServices.ExecQuery("SELECT * FROM Win32_TerminalServiceSetting")
iWbemClassObject = iEnumWbemClassObject.Next(0xffffffff,1)[0]
result = dict(iWbemClassObject.getProperties())
result = result['AllowTSConnections']['value']
if result == 0:
self.logger.success("Disable RDP via WMI(ncacn_ip_tcp) successfully")
else:
self.logger.success("Enable RDP via WMI(ncacn_ip_tcp) successfully")
else:
iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
self.__iWbemLevel1Login.RemRelease()
iEnumWbemClassObject = iWbemServices.ExecQuery("SELECT * FROM Win32_TerminalServiceSetting")
iWbemClassObject = iEnumWbemClassObject.Next(0xffffffff,1)[0]
result = dict(iWbemClassObject.getProperties())
result = result['AllowTSConnections']['value']
if result == 0:
self.logger.success("Disable RDP via WMI(ncacn_ip_tcp) successfully (old system)")
else:
self.logger.success("Enable RDP via WMI(ncacn_ip_tcp) successfully (old system)")
def query_RDPPort(self):
iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/DEFAULT', NULL, NULL)
self.__iWbemLevel1Login.RemRelease()
StdRegProv, resp = iWbemServices.GetObject("StdRegProv")
out = StdRegProv.GetDWORDValue(2147483650, 'SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp', 'PortNumber')
self.logger.success(f"RDP Port: {str(out.uValue)}")
# Nt version under 6 not support RAM.
def rdp_RAMWrapper(self, action):
iWbemServices = self.__iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
self.__iWbemLevel1Login.RemRelease()
StdRegProv, resp = iWbemServices.GetObject("StdRegProv")
if action == 'enable-ram':
self.logger.info("Enabling Restricted Admin Mode.")
StdRegProv.SetDWORDValue(2147483650, 'System\\CurrentControlSet\\Control\\Lsa', 'DisableRestrictedAdmin', 0)
elif action == 'disable-ram':
self.logger.info("Disabling Restricted Admin Mode (Clear).")
StdRegProv.DeleteValue(2147483650, 'System\\CurrentControlSet\\Control\\Lsa', 'DisableRestrictedAdmin')
out = StdRegProv.GetDWORDValue(2147483650, 'System\\CurrentControlSet\\Control\\Lsa', 'DisableRestrictedAdmin')
if out.uValue == 0:
self.logger.success("Enable RDP Restricted Admin Mode via WMI(ncacn_ip_tcp) successfully")
elif out.uValue == None:
self.logger.success("Disable RDP Restricted Admin Mode via WMI(ncacn_ip_tcp) successfully")
+1 -1
View File
@@ -503,7 +503,7 @@ class HostChecker:
def check_last_successful_update(self):
records = self.connection.wmi(wmi_query='Select TimeGenerated FROM Win32_ReliabilityRecords Where EventIdentifier=19', namespace='root\\cimv2')
if len(records) == 0:
if isinstance(records, bool) or len(records) == 0:
return False, ['No update found']
most_recent_update_date = records[0]['TimeGenerated']['value']
most_recent_update_date = most_recent_update_date.split('.')[0]
+50 -29
View File
@@ -21,11 +21,13 @@ from impacket.dcerpc.v5.rpcrt import DCERPCException
from impacket.dcerpc.v5.transport import DCERPCTransportFactory, SMBTransport
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
from impacket.dcerpc.v5.epm import MSRPC_UUID_PORTMAP
from impacket.dcerpc.v5.dcom.wmi import WBEM_FLAG_FORWARD_ONLY
from impacket.dcerpc.v5.samr import SID_NAME_USE
from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED
from impacket.krb5.kerberosv5 import SessionKeyDecryptionError
from impacket.krb5.types import KerberosException
from impacket.dcerpc.v5.dtypes import NULL
from impacket.dcerpc.v5.dcomrt import DCOMConnection
from impacket.dcerpc.v5.dcom.wmi import CLSID_WbemLevel1Login, IID_IWbemLevel1Login, WBEM_FLAG_FORWARD_ONLY, IWbemLevel1Login
from cme.config import process_secret, host_info_colors
from cme.connection import *
@@ -56,7 +58,6 @@ from dploot.lib.target import Target
from dploot.lib.smb import DPLootSMBConnection
from pywerview.cli.helpers import *
from pywerview.requester import RPCRequester
from time import time
from datetime import datetime
@@ -690,7 +691,7 @@ class smb(connection):
self.hash,
self.args.share,
logger=self.logger,
timeout=self.args.wmiexec_timeout,
timeout=self.args.dcom_timeout,
tries=self.args.get_output_tries
)
self.logger.info("Executed command via wmiexec")
@@ -711,7 +712,8 @@ class smb(connection):
self.args.share,
self.hash,
self.logger,
self.args.get_output_tries
self.args.get_output_tries,
self.args.dcom_timeout
)
self.logger.info("Executed command via mmcexec")
break
@@ -1207,45 +1209,64 @@ class smb(connection):
def pass_pol(self):
return PassPolDump(self).dump()
@requires_admin
def wmi(self, wmi_query=None, namespace=None):
records = []
if not wmi_query:
wmi_query = self.args.wmi.strip('\n')
if not namespace:
namespace = self.args.wmi_namespace
try:
rpc = RPCRequester(
self.host,
self.domain,
dcom = DCOMConnection(
self.host if not self.kerberos else self.hostname + "." + self.domain,
self.username,
self.password,
self.domain,
self.lmhash,
self.nthash,
oxidResolver=True,
doKerberos=self.kerberos,
kdcHost=self.kdcHost,
aesKey=self.aesKey
)
rpc._create_wmi_connection(namespace=namespace)
if wmi_query:
query = rpc._wmi_connection.ExecQuery(wmi_query, lFlags=WBEM_FLAG_FORWARD_ONLY)
else:
query = rpc._wmi_connection.ExecQuery(self.args.wmi, lFlags=WBEM_FLAG_FORWARD_ONLY)
iInterface = dcom.CoCreateInstanceEx(CLSID_WbemLevel1Login,IID_IWbemLevel1Login)
flag, stringBinding = dcom_FirewallChecker(iInterface, self.args.dcom_timeout)
if not flag:
self.logger.fail(f'WMI Query: Dcom initialization failed on connection with stringbinding: "{stringBinding}", please increase the timeout with the option "--dcom-timeout". If it\'s still failing maybe something is blocking the RPC connection')
# Make it force break function
dcom.disconnect()
return False
iWbemLevel1Login = IWbemLevel1Login(iInterface)
iWbemServices= iWbemLevel1Login.NTLMLogin(namespace , NULL, NULL)
iWbemLevel1Login.RemRelease()
iEnumWbemClassObject = iWbemServices.ExecQuery(wmi_query)
except Exception as e:
self.logger.fail(f"Error creating WMI connection: {e}")
return records
while True:
self.logger.fail('Execute WQL error: {}'.format(e))
dcom.disconnect()
return False
else:
self.logger.info(f"Executing WQL syntax: {wmi_query}")
while True:
try:
wmi_results = iEnumWbemClassObject.Next(0xffffffff, 1)[0]
record = wmi_results.getProperties()
records.append(record)
for k,v in record.items():
self.logger.highlight(f"{k} => {v['value']}")
except Exception as e:
if str(e).find('S_FALSE') < 0:
raise e
else:
break
try:
wmi_results = query.Next(0xFFFFFFFF, 1)[0]
record = wmi_results.getProperties()
records.append(record)
for k, v in record.items():
self.logger.highlight(f"{k} => {v['value']}")
self.logger.highlight("")
except Exception as e:
if str(e).find("S_FALSE") < 0:
raise e
else:
break
iEnumWbemClassObject.RemRelease()
dcom.disconnect()
except:
pass
return records
return records
def spider(
self,
+10 -4
View File
@@ -141,8 +141,7 @@ class TSCH_EXEC:
dce.set_credentials(*self.__rpctransport.get_credentials())
dce.connect()
# dce.set_auth_level(ntlm.NTLM_AUTH_PKT_PRIVACY)
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
dce.bind(tsch.MSRPC_UUID_TSCHS)
tmpName = gen_random_string(8)
tmpFileName = tmpName + ".tmp"
@@ -152,11 +151,18 @@ class TSCH_EXEC:
taskCreated = False
self.logger.info(f"Creating task \\{tmpName}")
try:
# windows server 2003 has no MSRPC_UUID_TSCHS, if it bind, it will return abstract_syntax_not_supported
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
dce.bind(tsch.MSRPC_UUID_TSCHS)
tsch.hSchRpcRegisterTask(dce, f"\\{tmpName}", xml, tsch.TASK_CREATE, NULL, tsch.TASK_LOGON_NONE)
except Exception as e:
self.logger.fail(str(e))
if hex(e.error_code) == "0x80070005":
self.logger.fail("ATEXEC: Create schedule task got blocked.")
else:
self.logger.fail(str(e))
return
taskCreated = True
else:
taskCreated = True
self.logger.info(f"Running task \\{tmpName}")
tsch.hSchRpcRun(dce, f"\\{tmpName}")
+8 -1
View File
@@ -29,6 +29,7 @@
from os.path import join as path_join
from time import sleep
from cme.connection import dcom_FirewallChecker
from cme.helpers.misc import gen_random_string
from impacket.dcerpc.v5.dcom.oaut import (
@@ -59,7 +60,7 @@ from impacket.dcerpc.v5.dtypes import NULL
class MMCEXEC:
def __init__(self, host, share_name, username, password, domain, smbconnection, share, hashes=None, logger=None, tries=None):
def __init__(self, host, share_name, username, password, domain, smbconnection, share, hashes=None, logger=None, tries=None, timeout=None):
self.__host = host
self.__username = username
self.__password = password
@@ -78,6 +79,7 @@ class MMCEXEC:
self.__share = share
self.__dcom = None
self.__tries = tries
self.__timeout = timeout
self.logger = logger
if hashes is not None:
@@ -98,6 +100,11 @@ class MMCEXEC:
)
try:
iInterface = self.__dcom.CoCreateInstanceEx(string_to_bin("49B2791A-B1AE-4C90-9B8E-E860BA07F889"), IID_IDispatch)
flag, self.__stringBinding = dcom_FirewallChecker(iInterface, self.__timeout)
if flag is False:
self.logger.fail(f'MMCEXEC: Dcom initialization failed on connection with stringbinding: "{self.__stringBinding}", please increase the timeout with the option "--dcom-timeout". If it\'s still failing maybe something is blocking the RPC connection, try another exec method')
# Make it force break function
self.__dcom.disconnect()
iMMC = IDispatch(iInterface)
resp = iMMC.GetIDsOfNames(("Document",))
+1 -1
View File
@@ -79,7 +79,7 @@ def proto_args(parser, std_parser, module_parser):
cgroup = smb_parser.add_argument_group("Command Execution", "Options for executing commands")
cgroup.add_argument("--exec-method", choices={"wmiexec", "mmcexec", "smbexec", "atexec"}, default=None,
help="method to execute the command. Ignored if in MSSQL mode (default: wmiexec)")
cgroup.add_argument("--wmiexec-timeout", help="WMIEXEC connection timeout, default is 5 secondes", type=int, default=5)
cgroup.add_argument("--dcom-timeout", help="DCOM connection timeout, default is 5 secondes", type=int, default=5)
cgroup.add_argument("--get-output-tries", help="Number of times atexec/smbexec/mmcexec tries to get results, default is 5", type=int, default=5)
cgroup.add_argument("--codec", default="utf-8",
help="Set encoding used (codec) from the target's output (default "
+9 -6
View File
@@ -141,18 +141,21 @@ class SMBEXEC:
except Exception as e:
if "rpc_s_access_denied" in str(e):
self.logger.fail("SMBEXEC: Create services got blocked.")
return self.__outputBuffer
else:
pass
self.logger.fail(str(e))
return self.__outputBuffer
try:
self.logger.debug(f"Remote service {self.__serviceName} started.")
scmr.hRStartServiceW(self.__scmr, service)
except:
self.logger.debug(f"Remote service {self.__serviceName} deleted.")
scmr.hRDeleteService(self.__scmr, service)
scmr.hRCloseServiceHandle(self.__scmr, service)
except Exception as e:
pass
self.logger.debug(f"Remote service {self.__serviceName} deleted.")
scmr.hRDeleteService(self.__scmr, service)
scmr.hRCloseServiceHandle(self.__scmr, service)
self.get_output_remote()
def get_output_remote(self):
+5 -27
View File
@@ -4,6 +4,7 @@
import ntpath
import os
from time import sleep
from cme.connection import dcom_FirewallChecker
from cme.helpers.misc import gen_random_string
from impacket.dcerpc.v5 import transport
from impacket.dcerpc.v5.dcomrt import DCOMConnection
@@ -73,39 +74,16 @@ class WMIEXEC:
kdcHost=self.__kdcHost,
)
iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
try:
self.firewall_check(iInterface, self.__timeout)
except:
self.logger.fail(f'WMIEXEC: Dcom initialization failed on connection with stringbinding: "{self.__stringBinding}", please increase the timeout with the option "--wmiexec-timeout". If it\'s still failing maybe something is blocking the RPC connection, try another exec method')
flag, self.__stringBinding = dcom_FirewallChecker(iInterface, self.__timeout)
if flag is False:
self.logger.fail(f'WMIEXEC: Dcom initialization failed on connection with stringbinding: "{self.__stringBinding}", please increase the timeout with the option "--dcom-timeout". If it\'s still failing maybe something is blocking the RPC connection, try another exec method')
# Make it force break function
self.__dcom.disconnect()
iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
iWbemServices = iWbemLevel1Login.NTLMLogin("//./root/cimv2", NULL, NULL)
iWbemLevel1Login.RemRelease()
self.__win32Process, _ = iWbemServices.GetObject("Win32_Process")
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
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()
def execute(self, command, output=False):
self.__retOutput = output
if self.__retOutput:
Generated
+11 -7
View File
@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry and should not be changed by hand.
# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
[[package]]
name = "aardwolf"
@@ -1517,18 +1517,22 @@ files = [
[[package]]
name = "oscrypto"
version = "1.3.0"
description = "TLS (SSL) sockets, key generation, encryption, decryption, signing, verification and KDFs using the OS crypto libraries. Does not require a compiler, and relies on the OS for patching. Works on Windows, OS X and Linux/BSD."
description = ""
category = "main"
optional = false
python-versions = "*"
files = [
{file = "oscrypto-1.3.0-py2.py3-none-any.whl", hash = "sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085"},
{file = "oscrypto-1.3.0.tar.gz", hash = "sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4"},
]
files = []
develop = false
[package.dependencies]
asn1crypto = ">=1.5.1"
[package.source]
type = "git"
url = "https://github.com/NeffIsBack/oscrypto"
reference = "HEAD"
resolved_reference = "d5f3437ed24257895ae1edd9e503cfb352e635a8"
[[package]]
name = "packaging"
version = "23.1"
@@ -2825,4 +2829,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
[metadata]
lock-version = "2.0"
python-versions = "^3.7.0"
content-hash = "08ee44e127854163d05ae0473213bc2ce67f52fde734c7dde21f1c4a6535e124"
content-hash = "9dc5181178139fe742c1b9d18de9613e544a11e221b30299aabc8ab04b68cc09"
+1
View File
@@ -54,6 +54,7 @@ pyasn1-modules = "^0.3.0"
rich = "^13.3.5"
python-libnmap = "^0.7.3"
resource = "^0.2.1"
oscrypto = { git = "https://github.com/NeffIsBack/oscrypto" }
[tool.poetry.group.dev.dependencies]
flake8 = "*"