diff --git a/README.md b/README.md index fc9dba1871..718ba9cb5b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,31 @@ Impacket ======== +Ntlm Relay Hash Dump Branch +---------------- + +This branch adds the option to dump ntlm hashes to the console +during runtime in ntlmrelayx using `-dh` or `--dump-hashes`. + +**Examples Updated:** + + * ntlmrelayx.py + * dnstool.py + * printerbug.py + * krbrelayx.py + +**Modified Libraries:** + + * smbserver.py + * httprelayserver.py + * rawrelayserver.py + * smbrelayserver.py + * wcfrelayserver.py + * config.py + +Original README +--- + [![Latest Version](https://img.shields.io/pypi/v/impacket.svg)](https://pypi.python.org/pypi/impacket/) [![Build and test Impacket](https://github.com/fortra/impacket/actions/workflows/build_and_test.yml/badge.svg)](https://github.com/fortra/impacket/actions/workflows/build_and_test.yml) diff --git a/examples/ntlmrelayx.py b/examples/ntlmrelayx.py index 1400f2123b..3c94d5c604 100644 --- a/examples/ntlmrelayx.py +++ b/examples/ntlmrelayx.py @@ -192,6 +192,7 @@ def start_servers(options, threads): c.setAttacks(PROTOCOL_ATTACKS) c.setLootdir(options.lootdir) c.setOutputFile(options.output_file) + c.setdumpHashes(options.dump_hashes) c.setLDAPOptions(options.no_dump, options.no_da, options.no_acl, options.no_validate_privs, options.escalate_user, options.add_computer, options.delegate_access, options.dump_laps, options.dump_gmsa, options.dump_adcs, options.sid, options.add_dns_record) c.setRPCOptions(options.rpc_mode, options.rpc_use_smb, options.auth_smb, options.hashes_smb, options.rpc_smb_port) c.setMSSQLOptions(options.query) @@ -306,6 +307,7 @@ def stop_servers(threads): 'directory in which gathered loot such as SAM dumps will be stored (default: current directory).') parser.add_argument('-of','--output-file', action='store',help='base output filename for encrypted hashes. Suffixes ' 'will be added for ntlm and ntlmv2') + parser.add_argument('-dh','--dump-hashes', action='store_true', default=False, help='show encrypted hashes in the console') parser.add_argument('-codec', action='store', help='Sets encoding used (codec) from the target\'s output (default ' '"%s"). If errors are detected, run chcp.com at the target, ' 'map the result with ' diff --git a/impacket/examples/ntlmrelayx/servers/httprelayserver.py b/impacket/examples/ntlmrelayx/servers/httprelayserver.py index e3d43b4cf0..dfea62da35 100644 --- a/impacket/examples/ntlmrelayx/servers/httprelayserver.py +++ b/impacket/examples/ntlmrelayx/servers/httprelayserver.py @@ -480,6 +480,10 @@ def do_relay(self, messageType, token, proxy, content = None): authenticateMessage['lanman'], authenticateMessage['ntlm']) self.client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data + if self.server.config.dumpHashes is True: + LOG.info("Dumping hash for %s \n%s", self.authUser, ntlm_hash_data['hash_string']) + LOG.info("Done dumping hash") + if self.server.config.outputFile is not None: writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.config.outputFile) diff --git a/impacket/examples/ntlmrelayx/servers/rawrelayserver.py b/impacket/examples/ntlmrelayx/servers/rawrelayserver.py index f8c61159ab..2c010b778f 100644 --- a/impacket/examples/ntlmrelayx/servers/rawrelayserver.py +++ b/impacket/examples/ntlmrelayx/servers/rawrelayserver.py @@ -130,6 +130,10 @@ def handle(self): authenticateMessage['lanman'], authenticateMessage['ntlm']) self.client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data + if self.server.config.dumpHashes is True: + LOG.info("Dumping hash for %s \n%s", self.authUser, ntlm_hash_data['hash_string']) + LOG.info("Done dumping hash") + if self.server.config.outputFile is not None: writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.config.outputFile) diff --git a/impacket/examples/ntlmrelayx/servers/smbrelayserver.py b/impacket/examples/ntlmrelayx/servers/smbrelayserver.py index f40637b2a0..67696c9fda 100644 --- a/impacket/examples/ntlmrelayx/servers/smbrelayserver.py +++ b/impacket/examples/ntlmrelayx/servers/smbrelayserver.py @@ -91,6 +91,11 @@ def __init__(self,config): if self.config.outputFile is not None: smbConfig.set('global','jtr_dump_path',self.config.outputFile) + if self.config.dumpHashes is True: + smbConfig.set("global", "dump_hashes", "True") + else: + smbConfig.set("global", "dump_hashes", "False") + if self.config.SMBServerChallenge is not None: smbConfig.set('global', 'challenge', self.config.SMBServerChallenge) @@ -373,6 +378,10 @@ def SmbSessionSetup(self, connId, smbServer, recvPacket): authenticateMessage['ntlm']) client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data + if self.server.getDumpHashes(): + LOG.info("Dumping hash for %s \n%s", self.authUser, ntlm_hash_data['hash_string']) + LOG.info("Done dumping hash") + if self.server.getJTRdumpPath() != '': writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.getJTRdumpPath()) @@ -667,6 +676,10 @@ def SmbSessionSetupAndX(self, connId, smbServer, SMBCommand, recvPacket): authenticateMessage['lanman'], authenticateMessage['ntlm']) client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data + if self.server.getDumpHashes(): + LOG.info("Dumping hash for %s \n%s", self.authUser, ntlm_hash_data['hash_string']) + LOG.info("Done dumping hash") + if self.server.getJTRdumpPath() != '': writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.getJTRdumpPath()) @@ -742,6 +755,10 @@ def SmbSessionSetupAndX(self, connId, smbServer, SMBCommand, recvPacket): sessionSetupData['AnsiPwd'], sessionSetupData['UnicodePwd']) client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data + if self.server.getDumpHashes(): + LOG.info("Dumping hash for %s \n%s", self.authUser, ntlm_hash_data['hash_string']) + LOG.info("Done dumping hash") + if self.server.getJTRdumpPath() != '': writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.getJTRdumpPath()) diff --git a/impacket/examples/ntlmrelayx/servers/wcfrelayserver.py b/impacket/examples/ntlmrelayx/servers/wcfrelayserver.py index cc56aa879a..4d8888e1b6 100644 --- a/impacket/examples/ntlmrelayx/servers/wcfrelayserver.py +++ b/impacket/examples/ntlmrelayx/servers/wcfrelayserver.py @@ -270,6 +270,10 @@ def handle(self): authenticateMessage['lanman'], authenticateMessage['ntlm']) self.client.sessionData['JOHN_OUTPUT'] = ntlm_hash_data + if self.server.config.dumpHashes is True: + LOG.info("Dumping hash for %s \n%s", self.authUser, ntlm_hash_data['hash_string']) + LOG.info("Done dumping hash") + if self.server.config.outputFile is not None: writeJohnOutputToFile(ntlm_hash_data['hash_string'], ntlm_hash_data['hash_version'], self.server.config.outputFile) diff --git a/impacket/examples/ntlmrelayx/utils/config.py b/impacket/examples/ntlmrelayx/utils/config.py index 176ac9de7e..53dc945c5e 100644 --- a/impacket/examples/ntlmrelayx/utils/config.py +++ b/impacket/examples/ntlmrelayx/utils/config.py @@ -38,6 +38,7 @@ def __init__(self): self.mode = None self.redirecthost = None self.outputFile = None + self.dumpHashes = False self.attacks = None self.lootdir = None self.randomtargets = False @@ -133,6 +134,9 @@ def setRunSocks(self, socks, server): def setOutputFile(self, outputFile): self.outputFile = outputFile + def setdumpHashes(self, dumpHashes): + self.dumpHashes = dumpHashes + def setTargets(self, target): self.target = target diff --git a/impacket/smbserver.py b/impacket/smbserver.py index 968cb91964..a4956b5d55 100644 --- a/impacket/smbserver.py +++ b/impacket/smbserver.py @@ -4358,6 +4358,9 @@ def setServerConfig(self, config): def getJTRdumpPath(self): return self.__jtr_dump_path + def getDumpHashes(self): + return self.__dump_hashes + def getAuthCallback(self): return self.auth_callback @@ -4674,12 +4677,16 @@ def processConfigFile(self, configFile=None): if self.__serverConfig.has_option("global", "jtr_dump_path"): self.__jtr_dump_path = self.__serverConfig.get("global", "jtr_dump_path") + if self.__serverConfig.has_option("global", "dump_hashes"): + self.__dump_hashes = self.__serverConfig.getboolean("global", "dump_hashes") + else: + self.__dump_hashes = False + if self.__serverConfig.has_option("global", "SMB2Support"): self.__SMB2Support = self.__serverConfig.getboolean("global", "SMB2Support") else: self.__SMB2Support = False - if self.__serverConfig.has_option("global", "anonymous_logon"): self.__anonymousLogon = self.__serverConfig.getboolean("global", "anonymous_logon") else: