Skip to content

Commit

Permalink
[DCOM] Fix kerberos with remoteHost & add '-target-ip' for wmiexec.py (
Browse files Browse the repository at this point in the history
…#1710)

Signed-off-by: XiaoliChan <[email protected]>
  • Loading branch information
XiaoliChan authored Mar 8, 2024
1 parent 3ee3bb4 commit 4a62f39
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
15 changes: 11 additions & 4 deletions examples/wmiexec.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@

class WMIEXEC:
def __init__(self, command='', username='', password='', domain='', hashes=None, aesKey=None, share=None,
noOutput=False, doKerberos=False, kdcHost=None, shell_type=None):
noOutput=False, doKerberos=False, kdcHost=None, remoteHost="", shell_type=None):
self.__command = command
self.__username = username
self.__password = password
Expand All @@ -61,14 +61,15 @@ def __init__(self, command='', username='', password='', domain='', hashes=None,
self.__noOutput = noOutput
self.__doKerberos = doKerberos
self.__kdcHost = kdcHost
self.__remoteHost = remoteHost
self.__shell_type = shell_type
self.shell = None
if hashes is not None:
self.__lmhash, self.__nthash = hashes.split(':')

def run(self, addr, silentCommand=False):
if self.__noOutput is False and silentCommand is False:
smbConnection = SMBConnection(addr, addr)
smbConnection = SMBConnection(addr, self.__remoteHost)
if self.__doKerberos is False:
smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
else:
Expand All @@ -88,7 +89,7 @@ def run(self, addr, silentCommand=False):
smbConnection = None

dcom = DCOMConnection(addr, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash,
self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost)
self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos, kdcHost=self.__kdcHost, remoteHost=self.__remoteHost)
try:
iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
Expand Down Expand Up @@ -393,6 +394,9 @@ def load_smbclient_auth_file(path):
'(128 or 256 bits)')
group.add_argument('-dc-ip', action='store', metavar="ip address", help='IP Address of the domain controller. If '
'ommited it use the domain part (FQDN) specified in the target parameter')
group.add_argument('-target-ip', action='store', metavar="ip address",
help='IP Address of the target machine. If omitted it will use whatever was specified as target. '
'This is useful when target is the NetBIOS name and you cannot resolve it')
group.add_argument('-A', action="store", metavar="authfile", help="smbclient/mount.cifs-style authentication file. "
"See smbclient man page's -A option.")
group.add_argument('-keytab', action="store", help='Read keys for SPN from keytab file')
Expand Down Expand Up @@ -442,6 +446,9 @@ def load_smbclient_auth_file(path):
logging.debug('loaded smbclient auth file: domain=%s, username=%s, password=%s' % (
repr(domain), repr(username), repr(password)))

if options.target_ip is None:
options.target_ip = address

if domain is None:
domain = ''

Expand All @@ -458,7 +465,7 @@ def load_smbclient_auth_file(path):
options.k = True

executer = WMIEXEC(' '.join(options.command), username, password, domain, options.hashes, options.aesKey,
options.share, options.nooutput, options.k, options.dc_ip, options.shell_type)
options.share, options.nooutput, options.k, options.dc_ip, options.target_ip, options.shell_type)
executer.run(address, options.silentcommand)
except KeyboardInterrupt as e:
logging.error(str(e))
Expand Down
18 changes: 14 additions & 4 deletions impacket/dcerpc/v5/dcomrt.py
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ class DCOMConnection:
PORTMAPS = {}

def __init__(self, target, username='', password='', domain='', lmhash='', nthash='', aesKey='', TGT=None, TGS=None,
authLevel=RPC_C_AUTHN_LEVEL_PKT_PRIVACY, oxidResolver=False, doKerberos=False, kdcHost=None):
authLevel=RPC_C_AUTHN_LEVEL_PKT_PRIVACY, oxidResolver=False, doKerberos=False, kdcHost=None, remoteHost=None):
self.__target = target
self.__userName = username
self.__password = password
Expand All @@ -979,6 +979,7 @@ def __init__(self, target, username='', password='', domain='', lmhash='', nthas
self.__oxidResolver = oxidResolver
self.__doKerberos = doKerberos
self.__kdcHost = kdcHost
self.__remoteHost = remoteHost
self.initConnection()

@classmethod
Expand Down Expand Up @@ -1059,6 +1060,10 @@ def initConnection(self):
stringBinding = r'ncacn_ip_tcp:%s' % self.__target
rpctransport = transport.DCERPCTransportFactory(stringBinding)

if self.__remoteHost:
rpctransport.setRemoteHost(self.__remoteHost)
rpctransport.setRemoteName(self.__target)

if hasattr(rpctransport, 'set_credentials') and len(self.__userName) >=0:
# This method exists only for selected protocol sequences.
rpctransport.set_credentials(self.__userName, self.__password, self.__domain, self.__lmhash, self.__nthash,
Expand Down Expand Up @@ -1286,6 +1291,11 @@ def connect(self, iid = None):
raise Exception('Can\'t find a valid stringBinding to connect')

dcomInterface = transport.DCERPCTransportFactory(stringBinding)

if DCOMConnection.PORTMAPS[self.__target].get_rpc_transport().get_kerberos():
dcomInterface.setRemoteHost(DCOMConnection.PORTMAPS[self.__target].get_rpc_transport().getRemoteHost())
dcomInterface.setRemoteName(DCOMConnection.PORTMAPS[self.__target].get_rpc_transport().getRemoteName())

if hasattr(dcomInterface, 'set_credentials'):
# This method exists only for selected protocol sequences.
dcomInterface.set_credentials(*DCOMConnection.PORTMAPS[self.__target].get_credentials())
Expand Down Expand Up @@ -1584,7 +1594,7 @@ def RemoteActivation(self, clsId, iid):

classInstance = CLASS_INSTANCE(ORPCthis, stringBindings)
return IRemUnknown2(INTERFACE(classInstance, b''.join(resp['ppInterfaceData'][0]['abData']), ipidRemUnknown,
target=self.__portmap.get_rpc_transport().getRemoteHost()))
target=self.__portmap.get_rpc_transport().getRemoteName()))


# 3.1.2.5.2.2 IRemoteSCMActivator Methods
Expand Down Expand Up @@ -1750,7 +1760,7 @@ def RemoteGetClassObject(self, clsId, iid):
classInstance.set_auth_level(scmr['remoteReply']['authnHint'])
classInstance.set_auth_type(self.__portmap.get_auth_type())
return IRemUnknown2(INTERFACE(classInstance, b''.join(propsOut['ppIntfData'][0]['abData']), ipidRemUnknown,
target=self.__portmap.get_rpc_transport().getRemoteHost()))
target=self.__portmap.get_rpc_transport().getRemoteName()))

def RemoteCreateInstance(self, clsId, iid):
# Only supports one interface at a time
Expand Down Expand Up @@ -1914,4 +1924,4 @@ def RemoteCreateInstance(self, clsId, iid):
classInstance.set_auth_level(scmr['remoteReply']['authnHint'])
classInstance.set_auth_type(self.__portmap.get_auth_type())
return IRemUnknown2(INTERFACE(classInstance, b''.join(propsOut['ppIntfData'][0]['abData']), ipidRemUnknown,
target=self.__portmap.get_rpc_transport().getRemoteHost()))
target=self.__portmap.get_rpc_transport().getRemoteName()))

0 comments on commit 4a62f39

Please sign in to comment.