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

Add the Option to Dump Ntlm Hashes in Ntlmrelayx #1904

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)

Expand Down
2 changes: 2 additions & 0 deletions examples/ntlmrelayx.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 '
Expand Down
4 changes: 4 additions & 0 deletions impacket/examples/ntlmrelayx/servers/httprelayserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions impacket/examples/ntlmrelayx/servers/rawrelayserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
17 changes: 17 additions & 0 deletions impacket/examples/ntlmrelayx/servers/smbrelayserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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())
Expand Down
4 changes: 4 additions & 0 deletions impacket/examples/ntlmrelayx/servers/wcfrelayserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions impacket/examples/ntlmrelayx/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
9 changes: 8 additions & 1 deletion impacket/smbserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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:
Expand Down