Scanning Windows Deeper With the Nmap Scanning Engine

by Ron Bowes
Nov. 29, 2017 0 comments 18 minute read Pen Testing & Audits microsoft windows nmap
Download PDF


Nmap, a network scanner, is among the best known security tools, and is considered to be one of the best free security tools in existence (Darknet, 2006). The typical use and functionality of Nmap is beyond the scope of this paper, but familiarity will make this paper far easier to be understood. The book Nmap Network Scanning, which is partially available for free, is one of the best information sources (Lyon, 2009).

All scripts and libraries referenced in this paper will be included with Nmap 4.85, which is expected to be released in summer of 2009; they are currently available in Nmap 4.85beta4 and higher.

The Nmap Scripting Engine, or NSE, is an extension to Nmap developed with several purposes in mind, including advanced network discovery, sophisticated version detection, vulnerability detection, backdoor detection, and vulnerability exploitation (Lyon, 2009). After Nmap scans a group of hosts, NSE runs scripts against each host that matches specific criteria (for example, the host has the appropriate ports open). These scripts, which are written in the Lua programming language, can inspect the host in a much deeper and more sophisticated way than Nmap alone. Since Lua is a complete programming language, the possibilities for scripts are great.

In addition to the power of scripts, another important aspect is the development culture. Since scripts can be written by anyone, and Lua is a relatively simple language for programmers to learn, it is not difficult for a programmer to begin developing his or her own script. Due to the fairly small team of core developers, and an active mailing list, getting started in script development is easy.

Server Message Block

The Server Message Block (SMB) protocol, which is commonly called the Common Internet File System (CIFS), is a protocol used by Microsoft services (and implemented by Samba, among others) to communicate with each other. SMB can function directly on TCP port 445 or over NetBIOS on port 139 (Petri, 2009). Although it was originally designed as a protocol to manage files remotely (Leach, 1998), SMB can use named pipes and the Distributed Computing Environment/Remote Procedure Call (DCE/RPC) system to call remote functions (Kenneth, 1999). This opens up great possibilities for foot printing servers.

The SMB protocol is fairly complicated, but, for the purposes of Nmap scripts, only a small subset is used. The implementations of it vary greatly, especially when it is used by printers and other embedded devices. Even the implementations in Samba and Windows are inconsistent with each other. As a result, the Nmap library for handling SMB connections has to be very tolerant of protocol differences, and attempts to communicate with all implementations. For more information on the SMB protocol, Implementing CIFS is a useful resource (Hertel, 2003).

In any implementation of SMB, three packets are sent to establish a session: SMB_COM_NEGOTIATE, SMB_COM_SESSION_SETUP_ANDX, and SMB_COM_TREE_CONNECT_ANDX (see diagram) (Leach, 1998). In its response to all three messages, the server reveals information about itself. If the first three packets are successful, the client usually sends a fourth packet, SMB_COM_NT_CREATE_ANDX, which creates or opens a file or pipe.


The SMB_COM_NEGOTIATE packet is the first one sent by the client, and is the client's opportunity to indicate which protocols, flags, and options it understands. The server responds with its preferred protocol, options, and flags, based on the client’s list. The options and flags reveal certain configuration options to the client, such as whether or not message signatures are supported or required, whether or not the server requires plaintext passwords, and whether share-level or user-level authentication is understood. These options are probed by the script smb-security-mode.nse. The following is an example output against a typical configuration of Windows:

Some of these options are revealing from a penetration tester's perspective. For example, this server does not support message signing; as a result, man-in-the-middle attacks are possible. However, since message signing is not a default option on Windows, this is not a surprising state. If share-level security or plaintext passwords were required, however, that would be an interesting find. Implementing CIFS has more information about the different levels of security supported by SMB. (Hertel, 2003).

In addition to the security information, the response to SMB_COM_NEGOTIATE also reveals the server's time and timezone, as well as the name of the server and its workgroup or domain membership. Revealing the time may be useful to a penetration tester because it is a sign of how well maintained a server is. The name and workgroup of the server can be helpful to a penetration tester when trying to determine the purpose of a server or a network, leading to more targeted attacks for a penetration tester.

The script smb-os-discovery.nse probes for the server’s name and time. The following output is from smb-os-discovery run against a poorly maintained Windows 2000 test server:

From the name and time alone, it can be determined that the operating system is Windows 2000 ("RON-WIN2K-TEST"), that it is a test machine, and that the time is off by about an hour (the current time is 11:03, but the server returns 11:59). One may conclude that it is a test server running on an outdated operating system, and that it is poorly maintained or infrequently used. This information could be valuable to a penetration tester when choosing a target, since the chances that this server has unpatched vulnerabilities are high. On a large network, this can quickly give a sense of a network's composition and purpose.


The SMB_COM_SESSION_SETUP_ANDX packet is sent by the client immediately after the negotiate response is received. The packet’s primary purpose is authentication, and contains the client’s username, domain, and password. Unless plaintext authentication was requested in the negotiate packet, the password is hashed with one of Microsoft's hashing algorithms (both Lanman and NT Lanman (NTLM) are used by default). Recovering the password from one these hashes is supposed to be difficult (although in practice it is usually straight forward). Instead of sending a username and password, the client may also establish a null (or anonymous) session by sending a blank username and a blank password.

For the purposes of these scripts, four account types are defined. Anonymous accounts, commonly called a “null session,” offer little access to the system, except on Windows 2000. Guest accounts offer slightly more access, and can find some interesting information; the guest account typically has no password and is disabled by default on many Windows versions. Under certain configurations, such as Windows XP’s default settings, all user accounts, including administrators, are treated as guests (Microsoft, 2005). User-level accounts are common, and are able to perform most checks. User-level accounts are defined as any account on a system that is not in the “Administrators” group. And finally, administrator-level accounts are accounts in the “Administrators” group. Administrative accounts can run every test against Windows 2003 and earlier, but are essentially the same as user-level accounts on Windows Vista and higher unless user account control (UAC) is disabled.

The server's response to the SMB_COM_SESSION_SETUP_ANDX packet contains a true/false value indicating whether or not the username/password combination was accepted. If it was accepted, which is always the case when an anonymous (null) session is requested, the server also includes its operating system and LAN manager version in the reply.

The smb-os-discovery.nse script will authenticate anonymously and display the operating system information. The following examples show the smb-os-discovery.nse script being run against Windows 2000 and Windows 2003:

If the login fails, the session setup can be sent again, without reconnecting. The smb-brute.nse script takes advantage of this behaviour to run a very fast bruteforce attack against targets. The smb-brute.nse script will be discussed in detail in a later section.


The SMB_COM_TREE_CONNECT_ANDX and SMB_COM_NT_CREATE_ANDX packets are less interesting, and do not reveal much useful information. The tree-connect packet connects to a Windows share (for example, 'C$' for a file share or 'IPC$' for making remote procedure calls). This packet can be used to verify whether or not a share exists. If a share exists, either "NT_STATUS_OK" or "NT_STATUS_ACCESS_DENIED" will be returned when a connection is attempted, and if the share does not exist then "NT_STATUS_BAD_NETWORK_NAME" is returned.

The file-create packet creates or opens a file within the share. The file can be an actual file like "\boot.ini" or a named pipe like "\PIPE\srvsvc". For making Microsoft RPC calls, the 'IPC$' share is used and an appropriate named pipe is opened.

Microsoft RPC

Microsoft RPC, or MSRPC, is Microsoft's protocol for performing remote function calls. MSRPC is also called Distributed Computing Environment Remote Procedure Call, or DCERPC. For the purposes of this paper, MSRPC calls are made over a SMB connection; while there are other interfaces for MSRPC calls, SMB is the most common one.

Before making MSRPC calls, an appropriate pipe (or interface) has to be opened. There are several commonly used interfaces, and the following are used by Nmap scripts:

    • SAMR ‐‐ Security account management
    • LSA ‐‐ Local security authority
    • SRVSVC ‐‐ Server service
    • WINREG ‐‐ Windows registry
    • SVCCTL ‐‐ Service control

Each of those interfaces has a number of associated functions. For example, the SRVSVC interface contains these functions, among others (the names used here are the names used by Samba, not Microsoft):

    • NetShareEnumAll()
    • NetShareGetInfo()
    • NetServerStatisticsGet()
    • NetPathCanonicalize()

These functions can be called by an Nmap script, and many will provide useful information about the server. For example, NetShareEnumAll() returns a list of shares on a system, and NetShareGetInfo() retrieves information on a share. NetShareEnumAll() is used by the smb-enum-shares.nse script to generate the following list:

Whereas NetShareGetInfo() can retrieve deeper information about each of the shares, as demonstrated by the verbose version of the smb-enum-shares.nse script:

The functions used for each script will be discussed when the script itself is discussed.


Two main types of MSRPC checks are used by the NSE scripts: anonymous and authenticated. Anonymous checks use a null session, whereas authenticated checks use a known user account (a username and password). Authenticated checks can be further broken down into three types: guest, user, and administrator. The guest account, which usually requires no password, can only access a minimal amount of information (although more information than anonymous). User-level accounts (user accounts on the system that aren't part of the "administrators" group) can access nearly all information, but are unable to check certain registry keys and cannot access certain interfaces (such as SVCCTL (service control)). Administrator-level accounts (user accounts in the "Administrators" group) can access all functions on Windows systems up to Windows 2003. Windows Vista and above give administrator-level accounts the same access as a user-level account, unless user access control (UAC) is disabled. Several methods exist for performing authenticated scans from Nmap.

A user account and password can be given on the command line when running the scan (this assumes that the account is known to the penetration tester, which isn't always the case). The smbuser and smbpass parameters are used, as shown here:

Instead of a username and password, a username and a hash of the user’s password can be given instead. The password hash can be taken from "fgdump" or "pwdump6" password dumps, decrypted from the SAM file (Erugor, 2004), dumped with the “smb-pwdump.nse” script, or read using Meterpreter's "priv" module (Skape, 2004). The advantage to using this technique, commonly known as "passing the hash", is that password hashes dumped from one server can be directly used to access other servers, without cracking them. The hash can be used directly by passing a "smbhash" argument instead of "smbpass":

Third, the smb-brute.nse script can be used to bruteforce account passwords. Those passwords will automatically be used to perform further checks. When smb-brute.nse is run with other smb scripts, it is guaranteed to run first. Accounts discovered by smb-brute.nse are automatically used in all other scripts. Here is an example of how it is used:


One of the initial goals when developing the SMB suite of scripts was user enumeration. This script is intended to enhance and replace the functionality of enum.exe (Blake, 2003) and sid2user.exe/user2sid.exe (Gates, 2006).

Several methods exist for remotely enumerating users, and smb-enum-users.nse implements two of them: a straight enumeration using SAMR functions, and a bruteforce using LSA functions. SAMR enumeration, which uses functions defined in the Security Accounts Manager, returns all user accounts defined by the system. LSA Bruteforcing, which uses Local Security Authority functions, tries to guess users based on their unique (and sequential) identifiers. By default, both are used by the smb-enum-users.nse script. Optionally, a script argument can disable either scan type, but there is rarely a compelling reason for disabling this functionality.

SAMR enumeration uses a technique similar to the enum.exe program. The QueryDisplayInfo() function returns a detailed list of users, along with descriptions, user types, and full names. SAMR enumeration can be performed anonymously against Windows 2000 systems, and with a user-level account or better on later Windows versions.

The following SAMR functions are called, in this order, to obtain the user list:

    • Connect4(): obtain a connect_handle.
    • EnumDomains(): obtain a list of the domains.
    • QueryDomain(): obtain the security identifier (SID) for the domain.
    • OpenDomain(): obtain a handle for each domain.
    • QueryDisplayInfo(): obtain the list of users in the domain.
    • Close(): close the domain handle.
    • Close(): close the connect handle.

The advantage of this technique is that detailed information is returned, including the full name and description; the disadvantage is that it requires a user-level account on every Windows version newer than Windows 2000.

LSA bruteforcing uses a different technique, modeled after the user2sid and sid2user programs. LSA bruteforcing can be performed anonymously against Windows 2000, and requires a guest account or better on newer Windows versions. The primary disadvantage is that it returns less information (only the username). Additionally, due to the nature of bruteforcing, this technique can miss accounts and it generates significantly more traffic than SAMR enumeration.

Although LSA bruteforcing uses a brute-force check to find accounts, it is not a brute force in the sense that it tries every possible account name; instead, it is a brute force of the users' RIDs. A user's RID is a value (generally 500, 501, or 1000+) that uniquely identifies that user on a system or domain. An LSA function is available that converts an RID (like 1000) to the username (like "Ron"). So, the technique will essentially try converting 1000 to a name, then 1001, 1002, and so on, until a termination condition is reached.

The implementation used by smb-enum-users.nse breaks the scan into groups of RIDs. If too many RIDs are chosen, packet fragmentation occurs and slows down the check; if too few are chosen, more traffic is generated, also slowing down the scan. smb-enum-users.nse uses groups of 20 users, a number chosen by trial and error. All members in each group are checked simultaneously, and the responses are recorded (1000 - 1019, 1020 - 1039, 1040 - 1069, and so on). Normally, some RIDs will convert to names and others will not be found, due to deleted accounts. A completely empty group may indicate the end of the active RIDs, but it is possible to have an empty group with non-empty groups after it. For that reason, smb-enum-users.nse requires a series of 10 empty groups (or 200 blank RIDs) before terminating the scan.

Before attempting this conversion, the security identifier (SID) of the server is required. The SID is determined by doing the reverse operation; that is, by converting a name into its equivalent SID. So, if RID 1000 represents "Ron", then "Ron" would convert to "[SID]-1000". The name looked up by the script can be any user on the server, including the server's name itself. smb-enum-users.nse uses a list of common names:

    • The computer name and domain name, returned in the
    • Currently logged in user from an nbstat query; and
    • Default or common usernames: "administrator", "guest", and "test".

In most cases the computer name is sufficient, but the overhead of looking up a few extra names is insignificant. The sequence of calls used by smb-enum-users.nse is:

    • OpenPolicy2(): Gets a policy handle.
    • LookupNames2(): Converts names to SID.
    • LookupSids2(): Converts SIDs back to names.
    • Close(): Close the policy handle.

Here is sample output for smb-enum-users.nse, using both SAMR and LSA enumeration, running anonymously against Windows 2000:

And here is the output with the verbose option enabled:


Enumerating file shares on a remote system is one of the simplest scripts, and was the first one written. A single function is used to enumerate the shares (NetShareEnumAll() in SRVSVC) and another function is used to probe for information about the share (NetShareGetInfo() in SRVSVC). Additionally, a standard SMB packet, SMB_COM_TREE_CONNECT_ANDX, is used to determine whether or not the share is accessible anonymously by attempting to use it.

NetShareEnumAll() will run anonymously against Windows 2000, and requires a guest account for newer Windows versions. NetShareGetInfo(), however, requires an administrator-level account on every version of Windows, even Windows 2000.

If access to NetShareEnumAll() is denied, the script uses a bruteforce check by sending a series of SMB_COM_TREE_CONNECT_ANDX packets. A list of common shares is used, and each one is checked. A response of "NT_STATUS_ACCESS_DENIED" or "NT_STATUS_OK" means that the share exists, and any other error, such as "NT_STATUS_BAD_NETWORK_NAME", means it does not exist. The list of shares is based on the Windows 2000 machines at the University of California San Diego (thanks to Brandon Enright from the Nmap team), and includes:

If any of those shares exist, they will be discovered anonymously against any version of Windows.

Here is an example output of smb-enum-shares.nse being run anonymously against a Windows 2000 system:

And here is the output of smb-enum-shares.nse being run against a Windows 2000 system with administrator credentials and verbose enabled:


smb-enum-sessions.nse, which is based on the concept (but not the code) of PsLoggedOn (Russinovich, 2006), attempts to enumerate two different types of sessions:

    1. Users logged in interactively, either through terminal services or locally on the machine’s console 
    2. Users connected to file shares

These two enumerations are implemented completely differently, but are kept together due to similar functionality.

Checking which users are logged in interactively is a combination of WINREG checks and LSA lookups. First, a WINREG function is used to enumerate the keys in the HKEY_USERS hive, which is a list of the logged in users' SIDs. Those SIDs are converted to names using the LookupSids2() function, similar to how LSA bruteforcing is performed in smb-enum-users.nse.

Checking which users are connected to file shares requires a call to the NetSessEnum() function in SRVSVC. NetSessEnum() can be called by the guest account on Windows 2000, and a user-level account or higher on newer versions of Windows.

Here is the output for a sample run against Windows 2000 using the guest account:


smb-enum-processes.nse, as its name suggests, enumerates the processes running on a remote machine. This script, which requires administrative privileges on all versions of Windows, reads the hidden HKEY_PERFORMANCE_DATA registry hive, and parses the data found therein. The encoding of the data is complicated, but the output is fairly simple (this is against Windows 2000 with administrative credentials):

Here's the output with verbose enabled:

And finally, here’s the output with extra verbose enabled:

This script is based on the idea behind (but not the code for) the PsList tool (Russinovich (2), 2006) from SysInternals.


smb-system-info.nse is a relatively simple script in comparison to the others; it simply queries the Windows registry for a variety of information. Windows 2000 will allow the guest user to query for limited information, while other Windows versions require a user account or higher. In all versions of Windows, a more privileged account will have access to more information.

Here is the output of smb-system-info.nse running against Windows 2000 with guest-level access:

When the script is given administrator access, it produces the following output:

Like several other scripts, the concept behind this is from a PsTools program, PsInfo (Russinovich, 2007).


smb-check-vulns.nse was originally designed to help administrators (or penetration testers) find machines missing Microsoft’s MS08-067 patch. MS08-067 was a critical vulnerability in Windows published by Microsoft in October of 2008 (Microsoft, 2008). The script gained significant popularity in March and April of 2009, when detection for the Conficker worm was added (Lyon, 2009).

smb-check-vulns.nse works similarly to Nessus, sending attack-like traffic to a port and checking the reaction. The MS08-067 check is based on a public scanner, and uses the NetPathCompare() function in the server service. NetPathCompare() indirectly calls NetPathCanonicalize(), which is the target of MS08-067. Without applying MS08-067, NetPathCanonicalize() will accept invalid parameters (and, potentially, crash), but after applying MS08-067, NetPathCanonicalize() recognizes invalid parameters and returns an error. By calling the NetPathCompare() or NetPathCananicalize() with invalid parameters, and checking whether or not an error is returned, the presence of the patch can be accurately determined.

Instability is a major drawback of checks such as MS08-067; because the traffic is similar to an attack, crashing a machine is possible. In tests, the check for MS08-067 crashed over half of all vulnerable systems.

Detection for the Conficker worm uses a technique based on work by Felix Leder and Tillmann Werner (Leder & Werner, 2009). The deployment of this check in Nmap and other network scanners was coordinated by the Conficker Working Group. The researchers discovered that Conficker applies its own patch to MS08-067, but that the patch was different from Microsoft’s official patch. Instead of returning the standard Microsoft error (“INVALID_NAME”), another error code is returned (the number is 0x00000057, a non-standard error code). By calling NetPathCanonicalize() with a dangerous-looking parameter, Conficker will reveal its presence. This is very useful to network administrators who need to scan their networks quickly.

Here is the output from a scan against an infected machine:

Although MS08-067 has been patched, the scan has detected that the patch was performed by Conficker, not by Microsoft. This output is from another scan, this time the system is vulnerable but is not infected:


smb-brute.nse will attempt to log into a SMB account by guessing usernames and passwords. The code and algorithms are designed to take advantage of the SMB protocol in a variety of ways in order to discover which users exist and whether or not it is possible to determine their passwords.

Initially, this script uses the same techniques as smb-enum-users.nse to determine which usernames exist on the system. If that fails, a list of well known usernames is used. If a valid account is discovered during the scan, that account will be used to obtain a proper list of user accounts.

Before the bruteforce starts, an attempt is made to log into each account with a known invalid password. In certain configurations, the responses will reveal whether or not the username exists on the system; if it is confirmed that the user does not exist, it is skipped.

When a valid username/password combination is discovered, it is displayed to the user. Additionally, the SMB module has the opportunity to store the account. If this is the first account discovered on the system, the account is stored; otherwise, the account’s privileges are checked, and it’s only stored if it has administrative privileges. This check is done by calling GetShareInfo(), a function that can only be called by an administrator. Once the SMB module saves this information, all further scripts will use these credentials to perform checks; in other words, the rest of the scan is effectively authenticated.

The major downside to smb-brute.nse is that it can lock out accounts. This downside is somewhat mitigated by Windows' default settings, since account lockout is disabled by default. Even if lockout is enabled, the Administrator account can't be locked out unless the system is specifically configured to do so. Even so, this script can create a dangerous denial-of-service condition. Additionally, if smb-brute.nse detects an account lockout, it will stop scanning that host to prevent further lockouts. When that happens, a warning is displayed in the results, which may allow the tester to inform the proper person. smb-brute.nse also uses a technique called a “canary account,” where it attempts to lock out the first account intentionally, to check if a server has lockouts configured. If it does, the scan stops immediately.

Here is the output of a successful smb-brute.nse run:

Although the functionality of smb-brute.nse is similar to other tools, such as thc-hydra, it isn't based on any specific tool or implementation. The purpose of smb-brute.nse is to perform fast checks for common passwords, not to launch a full bruteforce. Much of its power comes from a deep understanding of the SMB protocol.


smb-pwdump.nse is a powerful script that is also invasive and somewhat dangerous. It implements the functionality found in pwdump6,[9] written by the Foofus group, to obtain a list of password hashes from the remote system. Due to the potential risks of using it, and also due to the risk of being labeled as malware, required library files from pwdump6 (servpw.exe and lsremora.dll) are not included in Nmap and have to be downloaded separately.

The steps taken by the script are as follows:

    • Establish a connection to the target system
    • Upload servpw.exe and lsremora.dll to a file share using SMB (currently, the
    C$ share is used, but in the future it will use fgdump's method of searching
    for an open share)
    • Create and start a service (servpw.exe) using SVCCTL functions
    • Read and decrypt the data from the service (servpw.exe writes to a named
    pipe using Blowfish encryption, which can be read remotely ‐‐ this
    encryption is used for obfuscation, not security, since the key exchange is not
    • Stop the service and remove the files

Obviously, this script is very intrusive (and requires administrative privileges on all Windows versions). To accomplish its goal, this script runs a SYSTEM-level service on the remote machine, and the service injects itself into the LSASS process to determine the password hashes. Despite the invasiveness, one of the primary goals of this script was to clean up thoroughly. Unless the system crashes, the service will be removed and the files deleted.

This script was written mostly as an academic exercise, and to highlight Nmap's growing potential as a penetration testing tool. It compliments the smb-brute.nse script because smb-brute.nse can find weak administrator passwords, then smb-pwdump.nse can use those passwords to dump hashes. Those hashes can then be cracked (either manually or automatically – smb-pwdump.nse can integrate with Rainbow Crack) and added to the password list for more brute forcing. The hashes themselves can also be added to Nmap's password list, since smb-brute.nse understands how to use hashes. Future plans include automatically using discovered hashes against other systems.


Preventing these attacks is actually quite simple. The following steps can be taken:

    • Block access to Windows' ports (137, 139, and 445 in particular)
    • Disable Windows services (for example, disabling the server service, remote
    registry service, and service control service will render these scripts
    significantly less effective)
    • Use newer versions of Windows (each version of Windows gives less
    information and has less running by default)
    • Disable null sessions (Microsoft), especially on Windows 2000


This example penetration test will explore a sample network, made up of four hosts. Three hosts are Windows systems of various versions, and the final one is Linux. The goal of this penetration test is to gain access to the Linux server using only Nmap and Rainbow crack. In the interest of saving space, only quick excerpts from Nmap will be shown.

Step 1: discovery

The first step is network discovery – that is, determining which hosts are active and which operating systems they are running.

First, the active IP addresses are determined using a standard Nmap ping sweep (“-sP”).

Then, the smb-os-discovery.nse script is used to determine the remote operating systems and computer names.

This output reveals that “JIM-PROD” is Windows 2003, ”JIM-TEST” is Windows XP, and ”MARY-PROD” is Windows 2000.

Step 2: Generate user list

Next, smb-enum-users.nse is run across the network, and, in the interest of saving space, grep is used to determine the interesting information.

The interesting user accounts are “Administrator”, “Guest”, “jim”, “mary”, and “test”. Those usernames are added to usernames.txt, for use in smb-brute.nse.

Step 3: Brute force known user accounts

Next, smb-brute.nse is run with the username file generated in the previous step. The default password file is used.

From these results, the “guest” and “test” accounts had guessable passwords. The “guest” account can rarely perform interesting scans, but the “test” account may have higher access.

Step 4: Dump hashes and try cracking

Using the newly determined “test” login, run the smb-pwdump.nse script (with Rainbow Tables) to see if “test” has access to the password file.

The “test” account successfully dumped the password hash for “mary”. Further, although it successfully cracked the previously known password for “test”, it could only determine half of the “mary” password.

Step 5: Try using discovered hashes

Next, the downloaded hashes (“administrator”, “mary”, and “test”) are saved in a file called “password.txt” and smb-brute.nse is re-run using the hashes instead of the default password file.

According to these results, the “mary” password hash also worked on

Step 6: Dump hashes and try cracking (again)

pwdump and Rainbow Crack are now run against with the “mary” credentials, which will download the password database from that system if “mary” has sufficient access.

Not only was this check able to determine the “jim” hash, the Rainbow Crack successfully cracked the “jim” password, too: “cornflakes”.

Step 7: Log into Financial

Using this password, a successful login is made to “Financial”.

Using nothing more than Nmap with built-in Rainbow Crack, the penetration test was successful.


The Nmap scripting engine is a powerful tool for user-created scripts. This power is demonstrated in the suite of scripts designed to inspect Windows over the SMB protocol. Many footprinting tasks can be performed, including finding user accounts, open shares, and weak passwords. All these tasks are under a common framework, and share authentication libraries, which gives users a common and familiar interface.

Published with the express permission of the author.