Nmap scans are divided into several phases but NSE is only involved in three of them: pre-scanning, script scanning, and post-scanning. The execution rule defined by a function in the NSE script determines whether it runs in any of those phases.
Note
To learn more about the phases of Nmap scans, check out Appendix A, Scan Phases.
NSE scripts can have one of four different types of execution rule:
prerule
postrule
portrule
hostrule
Let's review some examples of these different script rules. This will also help you learn to debug scripts for those times when you run into problems:
prerule()
: The following is a snippet from thetargets-sniffer.nse
NSE script. It illustrates how we can use aprerule
function to check whether Nmap is running in privileged mode and whether it can determine the network interface correctly:prerule = function() return nmap.is_privileged() and (stdnse.get_script_args("targets-sniffer.iface") or nmap.get_interface())
postrule()
: Thessh-hostkey
script uses apostrule
function to detect hosts that share the same SSH public keys:postrule = function() return (nmap.registry.sshhostkey ~= nil) end
portrule(host, port)
: The following is a snippet of theportrule
function of thejdwp-inject
script. Thisportrule
function will match a service detection string and specific port protocol and state:portrule = function(host, port) -- JDWP will close the port if there is no valid handshake within 2 -- seconds, Service detection's NULL probe detects it as tcpwrapped. return port.service == "tcpwrapped" and port.protocol == "tcp" and port.state == "open" and not(shortport.port_is_excluded(port.number,port.protocol)) end
hostrule()
: Thesniffer-detect
script's host rule determines that the script will only execute with local Ethernet hosts:hostrule = function(host) if nmap.address_family() ~= 'inet' then stdnse.print_debug("%s is IPv4 compatible only.", SCRIPT_NAME) return false end if host.directly_connected == true and host.mac_addr ~= nil and host.mac_addr_src ~= nil and host.interface ~= nil then local iface = nmap.get_interface_info(host.interface) if iface and iface.link == 'ethernet' then return true end end return false end