mirror of
https://github.com/fortra/impacket
synced 2026-06-08 14:15:13 +00:00
d7a0d57560
* smbserver.py: add signing support by using computer account with NetLogon * Move kerberos key calculation into impacket.krb5.crypto for portability * smbserver.py: Support Kerberos * smbserver.py: NetLogon only works with sealing * smbserver.py: Adjust fixme * smbserver.py: Fix raw NTLM authentication * smbserver.py: Fix signed computer account authentication in NetLogon * smbserver.py: Add readonly, and options to disable NTLM or Kerberos smbserver.py: More debugging logs * fix missing fileName for logging * fix smbv1 typo * smbserver.py: Add user to logging, simplify log output * fix broken log * fix smbv1 logging * smbserver.py: Adjust cli option descriptions * generate_kerberos_keys: change debug message * smbserver.py: Username logging also for kerberos * smbserver.py: change defaults for signing * smbserver.py: Fallback to no signing if ticket decryption fals or client does not support signing * smbserver.py: provoding computer credentials ONLY authenticates the specified user, netLogon and kerberos are in this case not used * smbserver.py: return STATUS_LOGON_FAILURE if the Kerberos ticket cannot be decrypted * smbserver.py: Return correct error message * smbserver.py: Change -dcip to -dc-ip * smbserver.py: correct -computeraccountdomain argument description * smbrelayserver.py: Disable KerberosSupport in smbserver * smbserver.py: Use getter methods for NTLM/Kerberos support
139 lines
7.5 KiB
Python
Executable File
139 lines
7.5 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Impacket - Collection of Python classes for working with network protocols.
|
|
#
|
|
# Copyright Fortra, LLC and its affiliated companies
|
|
#
|
|
# All rights reserved.
|
|
#
|
|
# This software is provided under a slightly modified version
|
|
# of the Apache Software License. See the accompanying LICENSE file
|
|
# for more information.
|
|
#
|
|
# Description:
|
|
# Simple SMB Server example.
|
|
#
|
|
# Author:
|
|
# Alberto Solino (@agsolino)
|
|
#
|
|
|
|
import sys
|
|
import argparse
|
|
import logging
|
|
|
|
from impacket.examples import logger
|
|
from impacket import smbserver, version
|
|
from impacket.ntlm import compute_lmhash, compute_nthash
|
|
|
|
if __name__ == '__main__':
|
|
|
|
# Init the example's logger theme
|
|
print(version.BANNER)
|
|
|
|
parser = argparse.ArgumentParser(add_help = True, description = "This script will launch a SMB Server and add a "
|
|
"share specified as an argument. Usually, you need to be root in order to bind to port 445. "
|
|
"For optional authentication, it is possible to specify username and password or the NTLM hash. "
|
|
"Example: smbserver.py -comment 'My share' TMP /tmp")
|
|
|
|
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('-computeraccountname', action="store", help='computer account name to authenticate arbitrary clients with signing via NetLogon/Kerberos')
|
|
parser.add_argument('-computeraccounthash', action="store", help='computer account NT hash to authenticate arbitrary clients with signing via NetLogon/Kerberos')
|
|
parser.add_argument('-computeraccountaes', action="store", help='computer account AES key to authenticate arbitrary clients with signing via NetLogon/Kerberos')
|
|
parser.add_argument('-computeraccountpassword', action="store", help='computer account NT hash to authenticate arbitrary clients with signing via NetLogon/Kerberos')
|
|
parser.add_argument('-computeraccountdomain', action="store", help='computer account domain to authenticate arbitrary clients with signing via NetLogon/Kerberos')
|
|
parser.add_argument('-dc-ip', action="store", help='IP of domain controller to authenticate arbitrary clients with signing via NetLogon/Kerberos')
|
|
parser.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes for the Username, format is LMHASH:NTHASH')
|
|
parser.add_argument('-ts', action='store_true', help='Adds timestamp to every logging output')
|
|
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
|
|
parser.add_argument('-ip', '--interface-address', action='store', default=argparse.SUPPRESS, help='ip address of listening interface ("0.0.0.0" or "::" if omitted)')
|
|
parser.add_argument('-readonly', action='store_true', help='Only allow reading of files')
|
|
parser.add_argument('-disablekerberos', action='store_true', help='Do not offer Kerberos authentication')
|
|
parser.add_argument('-disablentlm', action='store_true', help='Do not offer NTLM authentication')
|
|
parser.add_argument('-port', action='store', default='445', help='TCP port for listening incoming connections (default 445)')
|
|
parser.add_argument('-dropssp', action='store_true', default=False, help='Disable NTLM ESS/SSP during negotiation')
|
|
parser.add_argument('-6','--ipv6', action='store_true',help='Listen on IPv6')
|
|
parser.add_argument('-smb2support', action='store_true', default=False, help='SMB2 Support (experimental!)')
|
|
parser.add_argument('-outputfile', action='store', default=None, help='Output file to log smbserver output messages')
|
|
|
|
if len(sys.argv)==1:
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
try:
|
|
options = parser.parse_args()
|
|
except Exception as e:
|
|
logging.critical(str(e))
|
|
sys.exit(1)
|
|
|
|
logger.init(options.ts, options.debug)
|
|
|
|
if options.comment is None:
|
|
comment = ''
|
|
else:
|
|
comment = options.comment
|
|
|
|
if 'interface_address' not in options:
|
|
options.interface_address = '::' if options.ipv6 else '0.0.0.0'
|
|
|
|
server = smbserver.SimpleSMBServer(listenAddress=options.interface_address, listenPort=int(options.port), ipv6=options.ipv6)
|
|
|
|
if options.outputfile:
|
|
logging.info('Switching output to file %s' % options.outputfile)
|
|
server.setLogFile(options.outputfile)
|
|
|
|
server.addShare(options.shareName.upper(), options.sharePath, comment, readOnly="yes" if options.readonly else "no")
|
|
server.setSMB2Support(options.smb2support)
|
|
server.setDropSSP(options.dropssp)
|
|
server.setKerberosSupport(not options.disablekerberos)
|
|
server.setNTLMSupport(not options.disablentlm)
|
|
|
|
# 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)
|
|
|
|
# If we want clients to be able to connect to us which enforce signing, we need a computer account to properly setup the connection
|
|
# Only works with SMB2
|
|
required_secure_server_options = [options.computeraccountname, options.computeraccountdomain, options.dc_ip]
|
|
at_least_one_secure_server_options = [options.computeraccounthash, options.computeraccountaes, options.computeraccountpassword]
|
|
if any(required_secure_server_options):
|
|
if options.username:
|
|
logging.critical("You cannot use account credentials AND computer account credentials at the same time")
|
|
sys.exit(1)
|
|
if not all(required_secure_server_options):
|
|
logging.critical("All of the following options need to be set for accepting signed connections from arbitrary users in the domain: -computeraccountname, -computeraccountdomain, -dc-ip")
|
|
sys.exit(1)
|
|
if not any(at_least_one_secure_server_options):
|
|
logging.critical("At least one of the following options need to be set for accepting signed connections from arbitrary users in the domain: -computeraccounthash, -computeraccountaes, -computeraccountpassword")
|
|
sys.exit(1)
|
|
server.setComputerAccount(options.computeraccountname, options.computeraccounthash, options.computeraccountaes, options.computeraccountpassword, options.computeraccountdomain, options.dc_ip)
|
|
|
|
# Here you can set a custom SMB challenge in hex format
|
|
# If empty defaults to '4141414141414141'
|
|
# (remember: must be 16 hex bytes long)
|
|
# e.g. server.setSMBChallenge('12345678abcdef00')
|
|
server.setSMBChallenge('')
|
|
|
|
# Rock and roll
|
|
try:
|
|
server.start()
|
|
except KeyboardInterrupt:
|
|
print("\nInterrupted, exiting...")
|
|
sys.exit(130)
|