Skip to content

Commit

Permalink
Merge branch 'master' into relay-experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
asolino committed Feb 27, 2018
2 parents 8cfdf01 + 7ca67ee commit cbb7914
Show file tree
Hide file tree
Showing 37 changed files with 1,320 additions and 371 deletions.
8 changes: 4 additions & 4 deletions README.md
Expand Up @@ -37,8 +37,7 @@ Setup
Quick start
-----------

Grab the latest stable release, unpack it and run `python setup.py
install` from the directory where you placed it. Isn't that easy?
Grab the latest stable release, unpack it and run `pip install .` from the directory where you placed it. Isn't that easy?


Requirements
Expand All @@ -58,14 +57,15 @@ Installing
----------

In order to install the source execute the following command from the
directory where the Impacket's distribution has been unpacked: `python
setup.py install`. This will install the classes into the default
directory where the Impacket's distribution has been unpacked: `pip install .`
This will install the classes into the default
Python modules path; note that you might need special permissions to
write there. For more information on what commands and options are
available from setup.py, run `python setup.py --help-commands`.

To install the dependencies for the examples, use either `pip install -r requirements_examples.txt` or use `pip install .[examples]` from the location you unpacked Impacket.


Licensing
=========

Expand Down
7 changes: 4 additions & 3 deletions examples/GetADUsers.py
Expand Up @@ -91,9 +91,10 @@ def getMachineName(self):
try:
s.login('', '')
except Exception:
logging.debug('Error while anonymous logging into %s' % self.__domain)

s.logoff()
if s.getServerName() == '':
raise('Error while anonymous logging into %s' % self.__domain)
else:
s.logoff()
return s.getServerName()

@staticmethod
Expand Down
31 changes: 26 additions & 5 deletions examples/GetUserSPNs.py
Expand Up @@ -47,6 +47,7 @@
from impacket.krb5.types import Principal
from impacket.ldap import ldap, ldapasn1
from impacket.smbconnection import SMBConnection
from impacket.ntlm import compute_lmhash, compute_nthash


class GetUserSPNs:
Expand Down Expand Up @@ -101,9 +102,10 @@ def getMachineName(self):
try:
s.login('', '')
except Exception:
logging.debug('Error while anonymous logging into %s' % self.__domain)

s.logoff()
if s.getServerName() == '':
raise('Error while anonymous logging into %s' % self.__domain)
else:
s.logoff()
return s.getServerName()

@staticmethod
Expand Down Expand Up @@ -136,7 +138,26 @@ def getTGT(self):

# No TGT in cache, request it
userName = Principal(self.__username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, self.__password, self.__domain,

# In order to maximize the probability of getting session tickets with RC4 etype, we will convert the
# password to ntlm hashes (that will force to use RC4 for the TGT). If that doesn't work, we use the
# cleartext password.
# If no clear text password is provided, we just go with the defaults.
if self.__password != '' and (self.__lmhash == '' and self.__nthash == ''):
try:
tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, '', self.__domain,
compute_lmhash(password),
compute_nthash(password), self.__aesKey,
kdcHost=self.__kdcHost)
except Exception, e:
logging.debug('TGT: %s' % str(e))
tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, self.__password, self.__domain,
unhexlify(self.__lmhash),
unhexlify(self.__nthash), self.__aesKey,
kdcHost=self.__kdcHost)

else:
tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, self.__password, self.__domain,
unhexlify(self.__lmhash),
unhexlify(self.__nthash), self.__aesKey,
kdcHost=self.__kdcHost)
Expand Down Expand Up @@ -336,7 +357,7 @@ def run(self):
TGT['sessionKey'])
self.outputTGS(tgs, oldSessionKey, sessionKey, user, SPN, fd)
except Exception , e:
logging.error(str(e))
logging.error('SPN: %s - %s' % (SPN,str(e)))
if fd is not None:
fd.close()

Expand Down
11 changes: 6 additions & 5 deletions examples/getPac.py
Expand Up @@ -27,6 +27,7 @@
import sys

from pyasn1.codec.der import decoder, encoder
from pyasn1.type.univ import noValue

from impacket import version
from impacket.dcerpc.v5.rpcrt import TypeSerialization1
Expand Down Expand Up @@ -155,7 +156,7 @@ def dump(self, addr):
# key (Section 5.5.1)
encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 7, encodedAuthenticator, None)

apReq['authenticator'] = None
apReq['authenticator'] = noValue
apReq['authenticator']['etype'] = cipher.enctype
apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator

Expand All @@ -166,8 +167,8 @@ def dump(self, addr):
tgsReq['pvno'] = 5
tgsReq['msg-type'] = int(constants.ApplicationTagNumbers.TGS_REQ.value)

tgsReq['padata'] = None
tgsReq['padata'][0] = None
tgsReq['padata'] = noValue
tgsReq['padata'][0] = noValue
tgsReq['padata'][0]['padata-type'] = int(constants.PreAuthenticationDataTypes.PA_TGS_REQ.value)
tgsReq['padata'][0]['padata-value'] = encodedApReq

Expand Down Expand Up @@ -196,7 +197,7 @@ def dump(self, addr):
paForUserEnc = PA_FOR_USER_ENC()
seq_set(paForUserEnc, 'userName', clientName.components_to_asn1)
paForUserEnc['userRealm'] = self.__domain
paForUserEnc['cksum'] = None
paForUserEnc['cksum'] = noValue
paForUserEnc['cksum']['cksumtype'] = int(constants.ChecksumTypes.hmac_md5.value)
paForUserEnc['cksum']['checksum'] = checkSum
paForUserEnc['auth-package'] = 'Kerberos'
Expand All @@ -207,7 +208,7 @@ def dump(self, addr):

encodedPaForUserEnc = encoder.encode(paForUserEnc)

tgsReq['padata'][1] = None
tgsReq['padata'][1] = noValue
tgsReq['padata'][1]['padata-type'] = int(constants.PreAuthenticationDataTypes.PA_FOR_USER.value)
tgsReq['padata'][1]['padata-value'] = encodedPaForUserEnc

Expand Down
15 changes: 8 additions & 7 deletions examples/goldenPac.py
Expand Up @@ -659,7 +659,7 @@ def getGoldenPAC(self, authTime):
pacType['Buffers'] = buffers + buffersTail

authorizationData = AuthorizationData()
authorizationData[0] = None
authorizationData[0] = noValue
authorizationData[0]['ad-type'] = int(constants.AuthorizationDataType.AD_WIN2K_PAC.value)
authorizationData[0]['ad-data'] = str(pacType)
return encoder.encode(authorizationData)
Expand All @@ -676,7 +676,7 @@ def getKerberosTGS(self, serverName, domain, kdcHost, tgt, cipher, sessionKey, a

# Now put the goldenPac inside the AuthorizationData AD_IF_RELEVANT
ifRelevant = AD_IF_RELEVANT()
ifRelevant[0] = None
ifRelevant[0] = noValue
ifRelevant[0]['ad-type'] = int(constants.AuthorizationDataType.AD_IF_RELEVANT.value)
ifRelevant[0]['ad-data'] = goldenPAC

Expand Down Expand Up @@ -704,7 +704,7 @@ def getKerberosTGS(self, serverName, domain, kdcHost, tgt, cipher, sessionKey, a
reqBody['till'] = KerberosTime.to_asn1(now)
reqBody['nonce'] = random.SystemRandom().getrandbits(31)
seq_set_iter(reqBody, 'etype', (cipher.enctype,))
reqBody['enc-authorization-data'] = None
reqBody['enc-authorization-data'] = noValue
reqBody['enc-authorization-data']['etype'] = int(cipher.enctype)
reqBody['enc-authorization-data']['cipher'] = encryptedEncodedIfRelevant

Expand Down Expand Up @@ -737,24 +737,24 @@ def getKerberosTGS(self, serverName, domain, kdcHost, tgt, cipher, sessionKey, a
# key (Section 5.5.1)
encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 7, encodedAuthenticator, None)

apReq['authenticator'] = None
apReq['authenticator'] = noValue
apReq['authenticator']['etype'] = cipher.enctype
apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator

encodedApReq = encoder.encode(apReq)

tgsReq['pvno'] = 5
tgsReq['msg-type'] = int(constants.ApplicationTagNumbers.TGS_REQ.value)
tgsReq['padata'] = None
tgsReq['padata'][0] = None
tgsReq['padata'] = noValue
tgsReq['padata'][0] = noValue
tgsReq['padata'][0]['padata-type'] = int(constants.PreAuthenticationDataTypes.PA_TGS_REQ.value)
tgsReq['padata'][0]['padata-value'] = encodedApReq

pacRequest = KERB_PA_PAC_REQUEST()
pacRequest['include-pac'] = False
encodedPacRequest = encoder.encode(pacRequest)

tgsReq['padata'][1] = None
tgsReq['padata'][1] = noValue
tgsReq['padata'][1]['padata-type'] = int(constants.PreAuthenticationDataTypes.PA_PAC_REQUEST.value)
tgsReq['padata'][1]['padata-value'] = encodedPacRequest

Expand Down Expand Up @@ -1028,6 +1028,7 @@ def exploit(self):
import sys
try:
import pyasn1
from pyasn1.type.univ import noValue
except ImportError:
logging.critical('This module needs pyasn1 installed')
logging.critical('You can get it from https://pypi.python.org/pypi/pyasn1')
Expand Down
2 changes: 2 additions & 0 deletions examples/lookupsid.py
Expand Up @@ -95,6 +95,8 @@ def __bruteForce(self, rpctransport, maxRid):
resp = lsad.hLsarQueryInformationPolicy2(dce, policyHandle, lsad.POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation)
domainSid = resp['PolicyInformation']['PolicyAccountDomainInfo']['DomainSid'].formatCanonical()

logging.info('Domain SID is: %s' % domainSid)

soFar = 0
SIMULTANEOUS = 1000
for j in range(maxRid/SIMULTANEOUS+1):
Expand Down
16 changes: 16 additions & 0 deletions examples/mssqlclient.py
Expand Up @@ -41,6 +41,7 @@ def do_help(self, line):
enable_xp_cmdshell - you know what it means
disable_xp_cmdshell - you know what it means
xp_cmdshell {cmd} - executes cmd using xp_cmdshell
sp_start_job {cmd} - executes cmd using the sql server agent (blind)
! {cmd} - executes a local shell cmd
"""

Expand All @@ -56,6 +57,21 @@ def do_xp_cmdshell(self, s):
except:
pass

def sp_start_job(self, s):
try:
self.sql.sql_query("DECLARE @job NVARCHAR(100);"
"SET @job='IdxDefrag'+CONVERT(NVARCHAR(36),NEWID());"
"EXEC msdb..sp_add_job @job_name=@job,@description='INDEXDEFRAG',"
"@owner_login_name='sa',@delete_level=3;"
"EXEC msdb..sp_add_jobstep @job_name=@job,@step_id=1,@step_name='Defragmentation',"
"@subsystem='CMDEXEC',@command='%s',@on_success_action=1;"
"EXEC msdb..sp_add_jobserver @job_name=@job;"
"EXEC msdb..sp_start_job @job_name=@job;" % s)
self.sql.printReplies()
self.sql.printRows()
except:
pass

def do_lcd(self, s):
if s == '':
print os.getcwd()
Expand Down
9 changes: 8 additions & 1 deletion examples/ntlmrelayx.py
Expand Up @@ -243,7 +243,6 @@ def run(self):
data1 = r1.read()
print data1


#Remove protocol from target name
#safeTargetName = self.client.target.replace('http://','').replace('https://','')

Expand Down Expand Up @@ -401,6 +400,7 @@ def do_exit(self, line):
RELAY_SERVERS = ( SMBRelayServer, HTTPRelayServer )
ATTACKS = {'SMB': SMBAttack, 'LDAP': LDAPAttack, 'LDAPS': LDAPAttack, 'HTTP': HTTPAttack, 'HTTPS': HTTPAttack,
'MSSQL': MSSQLAttack, 'IMAP': IMAPAttack, 'IMAPS': IMAPAttack}

# Init the example's logger theme
logger.init()
print version.BANNER
Expand All @@ -421,6 +421,11 @@ def do_exit(self, line):
parser.add_argument('-i','--interactive', action='store_true',help='Launch an smbclient/mssqlclient console instead'
'of executing a command after a successful relay. This console will listen locally on a '
' tcp port and can be reached with for example netcat.')

# Interface address specification
parser.add_argument('-ip','--interface-ip', action='store', metavar='INTERFACE_IP', help='IP address of interface to '
'bind SMB and HTTP servers',default='')

parser.add_argument('-ra','--random', action='store_true', help='Randomize target selection (HTTP server only)')
parser.add_argument('-r', action='store', metavar = 'SMBSERVER', help='Redirect HTTP requests to a file:// path on SMBSERVER')
parser.add_argument('-l','--lootdir', action='store', type=str, required=False, metavar = 'LOOTDIR',default='.', help='Loot '
Expand Down Expand Up @@ -544,6 +549,8 @@ def do_exit(self, line):
c.setIPv6(options.ipv6)
c.setWpadOptions(options.wpad_host, options.wpad_auth_num)
c.setSMB2Support(options.smb2support)
c.setInterfaceIp(options.interface_ip)


#If the redirect option is set, configure the HTTP server to redirect targets to SMB
if server is HTTPRelayServer and options.r is not None:
Expand Down
3 changes: 2 additions & 1 deletion examples/raiseChild.py
Expand Up @@ -79,6 +79,7 @@
from impacket.dcerpc.v5.ndr import NDRULONG
from impacket.dcerpc.v5.samr import NULL, GROUP_MEMBERSHIP, SE_GROUP_MANDATORY, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_ENABLED
from pyasn1.codec.der import decoder, encoder
from pyasn1.type.univ import noValue
from impacket.examples import logger
from impacket.ntlm import LMOWFv1, NTOWFv1
from impacket.dcerpc.v5.dtypes import RPC_SID, MAXIMUM_ALLOWED
Expand Down Expand Up @@ -1038,7 +1039,7 @@ def makeGolden(tgt, originalCipher, sessionKey, ntHash, aesKey, extraSid):
pacType['Buffers'] = buffers + buffersTail

authorizationData = AuthorizationData()
authorizationData[0] = None
authorizationData[0] = noValue
authorizationData[0]['ad-type'] = int(constants.AuthorizationDataType.AD_WIN2K_PAC.value)
authorizationData[0]['ad-data'] = str(pacType)
authorizationData = encoder.encode(authorizationData)
Expand Down
8 changes: 6 additions & 2 deletions examples/secretsdump.py
Expand Up @@ -165,14 +165,18 @@ def dump(self):
else:
SECURITYFileName = self.__securityHive

self.__LSASecrets = LSASecrets(SECURITYFileName, bootKey, self.__remoteOps, isRemote=self.__isRemote)
self.__LSASecrets = LSASecrets(SECURITYFileName, bootKey, self.__remoteOps,
isRemote=self.__isRemote, history=self.__history)
self.__LSASecrets.dumpCachedHashes()
if self.__outputFileName is not None:
self.__LSASecrets.exportCached(self.__outputFileName)
self.__LSASecrets.dumpSecrets()
if self.__outputFileName is not None:
self.__LSASecrets.exportSecrets(self.__outputFileName)
except Exception, e:
if logging.getLogger().level == logging.DEBUG:
import traceback
print traceback.print_exc()
logging.error('LSA hashes extraction failed: %s' % str(e))

# NTDS Extraction we can try regardless of RemoteOperations failing. It might still work
Expand Down Expand Up @@ -291,7 +295,7 @@ def cleanup(self):
help='Shows pwdLastSet attribute for each NTDS.DIT account. Doesn\'t apply to -outputfile data')
group.add_argument('-user-status', action='store_true', default=False,
help='Display whether or not the user is disabled')
group.add_argument('-history', action='store_true', help='Dump password history')
group.add_argument('-history', action='store_true', help='Dump password history, and LSA secrets OldVal')
group = parser.add_argument_group('authentication')

group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
Expand Down
27 changes: 25 additions & 2 deletions examples/smbserver.py
Expand Up @@ -17,6 +17,7 @@

from impacket.examples import logger
from impacket import smbserver, version
from impacket.ntlm import compute_lmhash, compute_nthash

if __name__ == '__main__':

Expand All @@ -32,7 +33,11 @@
parser.add_argument('shareName', action='store', help='name of the share to add')
parser.add_argument('sharePath', action='store', help='path of the share to add')
parser.add_argument('-comment', action='store', help='share\'s comment to display when asked for shares')
parser.add_argument('-username', action="store", help='Username to authenticate clients')
parser.add_argument('-password', action="store", help='Password for the Username')
parser.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes for the Username, format is LMHASH:NTHASH')
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
parser.add_argument('-ip', '--interface-address', action='store', default='0.0.0.0', help='ip address of listening interface')
parser.add_argument('-smb2support', action='store_true', default=False, help='SMB2 Support (experimental!)')

if len(sys.argv)==1:
Expand All @@ -55,11 +60,29 @@
else:
comment = options.comment

server = smbserver.SimpleSMBServer()
server = smbserver.SimpleSMBServer(listenAddress=options.interface_address)

server.addShare(options.shareName.upper(), options.sharePath, comment)
server.setSMB2Support(options.smb2support)


# If a user was specified, let's add it to the credentials for the SMBServer. If no user is specified, anonymous
# connections will be allowed
if options.username is not None:
# we either need a password or hashes, if not, ask
if options.password is None and options.hashes is None:
from getpass import getpass
password = getpass("Password:")
# Let's convert to hashes
lmhash = compute_lmhash(password)
nthash = compute_nthash(password)
elif options.password is not None:
lmhash = compute_lmhash(options.password)
nthash = compute_nthash(options.password)
else:
lmhash, nthash = options.hashes.split(':')

server.addCredential(options.username, 0, lmhash, nthash)

# Here you can set a custom SMB challenge in hex format
# If empty defaults to '4141414141414141'
# (remember: must be 16 hex bytes long)
Expand Down

0 comments on commit cbb7914

Please sign in to comment.