SMB enumeration is surprisingly not about listing files.
Let’s see it in action. Imagine you’re on a network and want to know what Windows shares are available on a target machine, say 192.168.1.100. You’d run Nmap like this:
nmap -p 445 --script smb-enum-shares -oN nmap_smb_shares.txt 192.168.1.100
The output might look something like this, showing us accessible shares and their permissions:
Starting Nmap 7.92 ( https://nmap.org ) at 2023-10-27 10:00 EDT
Nmap scan report for 192.168.1.100
Host is up (0.0050s latency).
PORT STATE SERVICE
445/tcp open microsoft-ds
| smb-enum-shares:
| account_user:
| Type: FILE
| Path: C:\Users\account_user\Documents
| ACL: Everyone:READ
| Users:
| Type: FILE
| Path: C:\Users\Public
| ACL: Everyone:READ
| IPC$:
| Type: PIPE
| Path: \pipe\srvsvc
| ACL: Everyone:READ
| ADMIN$:
| Type: FILE
| Path: C:\Windows
| ACL: BUILTIN\Administrators:FULL
| C$:
| Type: FILE
| Path: C:\
| ACL: BUILTIN\Administrators:FULL
| SharedDocs:
| Type: FILE
| Path: D:\Shared
| ACL: Everyone:READ
|
| Total shares found: 5
WARNING: Host scripting engine is disabled, results may be incomplete.
Nmap done: 1 IP address (1 host up) scanned in 12.34 seconds
This Nmap script smb-enum-shares targets the SMB (Server Message Block) protocol, specifically port 445, which is the standard port for SMB over TCP/IP. Its goal is to discover and list the network shares exposed by a Windows machine. It doesn’t just blindly ask "what shares do you have?"; it interacts with the SMB service using specific commands to elicit information about available resources, whether they are file shares (like C$ or SharedDocs) or named pipes (like IPC$).
The core problem this solves is network reconnaissance. Before you can interact with files on a remote Windows machine, or even understand its potential attack surface, you need to know what’s being shared. SMB enumeration allows you to identify these shared resources, understand their types (file shares, printer shares, IPC shares), and crucially, see what access controls (ACLs) are in place for each. This helps in mapping out the network, identifying sensitive data locations, and understanding potential pivoting points.
Internally, the smb-enum-shares script uses the SMB TRANS2_FIND_FIRST2 and TRANS2_FIND_NEXT2 subcommands. These are used to enumerate directory contents and file information. When querying for shares, Nmap crafts requests to the server’s SRVSVC (Server Service) and браузер (Browser) services. The SRVSVC is the primary service responsible for managing and listing shares. The script essentially asks the server to list all available "resume keys" (which represent shares) and then queries for details about each. It then parses the responses, which are structured SMB packets, to extract share names, types, and path information.
The script also attempts to query the security descriptor (ACL) for each share if it can authenticate with sufficient privileges. This is why you might see different results depending on whether you run it anonymously or as a user with specific permissions. For instance, ADMIN$ and C$ are typically only accessible by administrators.
A key lever you control is the --script-args option. You can pass specific arguments to the smb-enum-shares script. For example, to attempt to enumerate shares using a specific username and password (if you have them), you’d use:
nmap -p 445 --script smb-enum-shares --script-args smbusername='user',smbpassword='password' -oN nmap_smb_shares_auth.txt 192.168.1.100
This allows you to discover shares that might not be visible to anonymous users, providing a more complete picture of the accessible resources.
Most people understand that enumeration scripts find things. What’s less obvious is that the smb-enum-shares script, by default, performs a null session enumeration. This means it attempts to get information without providing any credentials at all. This is incredibly powerful because it relies on Windows’ default behavior of allowing anonymous users to query certain service information. If a share is configured with overly permissive ACLs (like Everyone:READ), even a null session might reveal its contents or at least its existence and path. The script also tries to determine share types (FILE, DISK, PIPE) based on the data returned in the SMB packets.
After discovering shares, the next logical step is to try and list the contents of those file shares.