Skip to main content

Overview

The smbserver module provides a complete SMB server implementation that allows you to create custom SMB file servers. This is useful for penetration testing, creating honeypots, or implementing custom file sharing services.

Key Classes

SimpleSMBServer

Easy-to-use SMB server with minimal configuration.
from impacket import smbserver

server = smbserver.SimpleSMBServer(listenAddress='0.0.0.0', 
                                    listenPort=445)
server.addShare('SHARE', '/tmp/share', 'Share description')
server.setSMB2Support(True)
server.start()
listenAddress
str
default:"'0.0.0.0'"
IP address to bind the server to
listenPort
int
default:"445"
Port to listen on (445 for SMB, 139 for NetBIOS)

SMBSERVER

Advanced SMB server class with full control over configuration.
from impacket import smbserver
import configparser

config = configparser.ConfigParser()
config.add_section('global')
config.set('global', 'server_name', 'FILESERVER')
config.set('global', 'server_os', 'Windows 10')
config.set('global', 'log_file', '/var/log/smb.log')

server = smbserver.SMBSERVER(('0.0.0.0', 445), config_parser=config)
server.processConfigFile()
server.serve_forever()
address
tuple
required
Tuple of (host, port) to bind to
config_parser
ConfigParser
required
Configuration object defining server behavior and shares

Server Configuration

Global Settings

The global section defines server-wide settings:
import configparser

config = configparser.ConfigParser()
config.add_section('global')

# Server identification
config.set('global', 'server_name', 'FILESERVER')
config.set('global', 'server_os', 'Windows 10 Pro')
config.set('global', 'server_domain', 'WORKGROUP')

# Authentication
config.set('global', 'challenge', '4141414141414141')  # 8-byte hex

# Logging
config.set('global', 'log_file', '/var/log/smb.log')
config.set('global', 'credentials_file', '/tmp/hashes.txt')

# SMB2 support
config.set('global', 'SMB2Support', 'True')
server_name
str
NetBIOS name of the server
server_os
str
Operating system string returned to clients
server_domain
str
Domain or workgroup name
challenge
str
NTLM challenge (16-character hex string)
log_file
str
Path to log file for server activity
credentials_file
str
Path to file where captured credentials are written
SMB2Support
str
Enable SMB2/SMB3 support (‘True’ or ‘False’)

Share Configuration

Define shared directories:
config.add_section('SHARE')
config.set('SHARE', 'comment', 'Public share')
config.set('SHARE', 'read only', 'no')
config.set('SHARE', 'share type', '0')  # Disk share
config.set('SHARE', 'path', '/tmp/share')
comment
str
Description of the share
read only
str
Whether the share is read-only (‘yes’ or ‘no’)
share type
str
Share type:
  • '0' - Disk share (SHARED_DISK)
  • '1' - Print queue (SHARED_PRINT_QUEUE)
  • '3' - IPC (SHARED_IPC)
path
str
required
Local filesystem path to share

SimpleSMBServer Methods

addShare()

Add a new share to the server.
server.addShare(name, path, comment='', readOnly=False)
name
str
required
Share name (e.g., ‘SHARE’, ‘C$’)
path
str
required
Local filesystem path
comment
str
default:"''"
Share description
readOnly
bool
default:"False"
Whether share is read-only

removeShare()

Remove a share from the server.
server.removeShare(name)
name
str
required
Name of share to remove

setSMB2Support()

Enable or disable SMB2/SMB3 support.
server.setSMB2Support(enabled)
enabled
bool
required
True to enable SMB2/SMB3, False for SMB1 only

setLogFile()

Set the log file path.
server.setLogFile(filename)
filename
str
required
Path to log file

addCredential()

Add authentication credentials.
server.addCredential(username, password, domain='', 
                      lmhash='', nthash='')
username
str
required
Username to accept
password
str
required
Password to accept
domain
str
default:"''"
Domain name
lmhash
str
default:"''"
LM hash
nthash
str
default:"''"
NT hash

start()

Start the SMB server (blocking).
server.start()

stop()

Stop the SMB server.
server.stop()

Callback Hooks

Customize server behavior by registering callback functions.

registerNamedPipe()

Register a handler for named pipe operations.
def pipe_handler(tid, user, data):
    print(f"Pipe accessed by {user}: {data}")
    return b"Response data"

server.registerNamedPipe('srvsvc', pipe_handler)
pipeName
str
required
Name of the pipe (without \\PIPE\\ prefix)
callback
callable
required
Function with signature (tid, user, data) -> bytes

setSMBChallenge()

Set a custom NTLM challenge.
server.setSMBChallenge('4141414141414141')  # 8-byte hex
challenge
str
required
16-character hex string representing 8 bytes

Usage Examples

Simple File Server

from impacket import smbserver
import os

# Create share directory
os.makedirs('/tmp/myshare', exist_ok=True)

# Create and configure server
server = smbserver.SimpleSMBServer(listenAddress='0.0.0.0',
                                    listenPort=445)

# Add shares
server.addShare('SHARE', '/tmp/myshare', 'Public Files')
server.addShare('READONLY', '/tmp/readonly', 'Read-Only Files',
                 readOnly=True)

# Enable SMB2
server.setSMB2Support(True)

# Set log file
server.setLogFile('/var/log/smbserver.log')

print("SMB Server started on 0.0.0.0:445")
try:
    server.start()
except KeyboardInterrupt:
    print("\nShutting down...")
    server.stop()

Authenticated Server

from impacket import smbserver

server = smbserver.SimpleSMBServer()

# Add valid credentials
server.addCredential('admin', 'P@ssw0rd', 'WORKGROUP')
server.addCredential('user', 'password123', 'WORKGROUP')

# Add share
server.addShare('FILES', '/tmp/files')

try:
    server.start()
except KeyboardInterrupt:
    server.stop()

Credential Harvesting Server

from impacket import smbserver
import threading

def start_smb_server():
    server = smbserver.SimpleSMBServer()
    
    # Set custom challenge for consistency
    server.setSMBChallenge('1122334455667788')
    
    # Log credentials to file
    server.setLogFile('/tmp/smb_hashes.txt')
    
    # Add a honey share
    server.addShare('ADMIN$', '/tmp/fake_admin', 'Admin Share')
    server.addShare('C$', '/tmp/fake_c', 'C Drive')
    
    # Enable SMB2 for modern clients
    server.setSMB2Support(True)
    
    print("[*] SMB Server listening...")
    print("[*] Captured hashes will be written to /tmp/smb_hashes.txt")
    
    try:
        server.start()
    except KeyboardInterrupt:
        print("\n[*] Stopping server...")
        server.stop()

# Run in separate thread if needed
server_thread = threading.Thread(target=start_smb_server)
server_thread.daemon = True
server_thread.start()

# Keep main thread alive
try:
    server_thread.join()
except KeyboardInterrupt:
    pass

Advanced Configuration

from impacket import smbserver
import configparser
import socket

# Create configuration
config = configparser.ConfigParser()

# Global settings
config.add_section('global')
config.set('global', 'server_name', 'FILESERVER')
config.set('global', 'server_os', 'Windows Server 2019')
config.set('global', 'server_domain', 'CORP')
config.set('global', 'log_file', '/var/log/smbserver.log')
config.set('global', 'credentials_file', '/var/log/smb_creds.txt')
config.set('global', 'SMB2Support', 'True')
config.set('global', 'challenge', 'A'*16)  # Fixed challenge

# Public share
config.add_section('PUBLIC')
config.set('PUBLIC', 'comment', 'Public file share')
config.set('PUBLIC', 'read only', 'no')
config.set('PUBLIC', 'share type', '0')
config.set('PUBLIC', 'path', '/srv/samba/public')

# Private share
config.add_section('PRIVATE')
config.set('PRIVATE', 'comment', 'Private files')
config.set('PRIVATE', 'read only', 'yes')
config.set('PRIVATE', 'share type', '0')
config.set('PRIVATE', 'path', '/srv/samba/private')

# IPC share for RPC
config.add_section('IPC$')
config.set('IPC$', 'comment', 'IPC Service')
config.set('IPC$', 'read only', 'yes')
config.set('IPC$', 'share type', '3')
config.set('IPC$', 'path', '')

# Create and start server
server = smbserver.SMBSERVER(('0.0.0.0', 445), 
                              config_parser=config)
server.processConfigFile()

print(f"SMB Server started on {socket.gethostname()}")
print("Available shares: PUBLIC, PRIVATE, IPC$")

try:
    server.serve_forever()
except KeyboardInterrupt:
    print("\nShutting down...")
    server.shutdown()

Custom Named Pipe Handler

from impacket import smbserver
import struct

def handle_srvsvc_pipe(tid, user, data):
    """
    Custom handler for srvsvc pipe (Server Service)
    """
    print(f"[*] SRVSVC pipe accessed by {user}")
    print(f"[*] Data received ({len(data)} bytes)")
    
    # Parse DCE/RPC header if needed
    # Return response or empty bytes
    return b''

def handle_custom_pipe(tid, user, data):
    """
    Handler for custom named pipe
    """
    print(f"[*] Custom pipe accessed by {user}")
    
    # Echo back the data
    return data

# Create server
server = smbserver.SimpleSMBServer()

# Register pipe handlers
server.registerNamedPipe('srvsvc', handle_srvsvc_pipe)
server.registerNamedPipe('custom', handle_custom_pipe)

# Add IPC$ share for pipes
server.addShare('IPC$', '', 'IPC Service')

server.start()

Multi-threaded Server

from impacket import smbserver
import threading
import time

class ManagedSMBServer:
    def __init__(self, address='0.0.0.0', port=445):
        self.server = smbserver.SimpleSMBServer(
            listenAddress=address,
            listenPort=port
        )
        self.thread = None
        self.running = False
    
    def add_share(self, name, path, comment='', read_only=False):
        self.server.addShare(name, path, comment, read_only)
    
    def start(self):
        """Start server in background thread"""
        if self.running:
            return
        
        self.running = True
        self.thread = threading.Thread(target=self._run)
        self.thread.daemon = True
        self.thread.start()
        print("[+] SMB Server started")
    
    def _run(self):
        try:
            self.server.start()
        except Exception as e:
            print(f"[-] Server error: {e}")
            self.running = False
    
    def stop(self):
        """Stop the server"""
        if not self.running:
            return
        
        print("[*] Stopping SMB Server...")
        self.server.stop()
        self.running = False
        if self.thread:
            self.thread.join(timeout=5)
        print("[+] Server stopped")

# Usage
managed_server = ManagedSMBServer()
managed_server.add_share('FILES', '/tmp/files')
managed_server.start()

try:
    # Do other work while server runs
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    managed_server.stop()

Security Considerations

Running an SMB server requires root/administrator privileges to bind to port 445. Always run with appropriate security measures.
The credential harvesting capabilities should only be used for authorized security testing. Capturing credentials without permission is illegal.

Best Practices

  1. Use authentication - Always configure credentials unless running a public share
  2. Limit share access - Only share necessary directories
  3. Monitor logs - Regularly check log files for suspicious activity
  4. Set read-only where possible - Minimize write access to prevent abuse
  5. Use SMB2/SMB3 - Enable modern protocol support for better security

Helper Functions

getShares()

Get list of configured shares.
from impacket.smbserver import getShares

shares = getShares(connId, smbServer)

searchShare()

Find a specific share by name.
from impacket.smbserver import searchShare

share_config = searchShare(connId, 'SHARE', smbServer)
if share_config:
    print(f"Path: {share_config['path']}")

See Also

Build docs developers (and LLMs) love