Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DCOM] Fix kerberos with remoteHost & add '-target-ip' for wmiexec.py #8

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -966,7 +966,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 @@ -981,6 +981,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 @@ -1061,6 +1062,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 @@ -1293,6 +1298,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 @@ -1591,7 +1601,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 @@ -1757,7 +1767,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 @@ -1921,4 +1931,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()))