#!/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)