diff --git a/CHANGELOG b/CHANGELOG
index ac0b3b127..67956d230 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,10 @@
[NOT YET RELEASED]
+o [NSE] nbstat.nse can now look up the MAC prefix vendor string. Other
+ scripts can do the same thing using the datafiles.parse_mac_prefixes
+ function. [Thomas Buchanan]
+
o [NSE] Added the ssl-enum-ciphers script from Mak Kolybabi. This
script lists the ciphers and compressors supported by an SSL/TLS
server.
diff --git a/nselib/datafiles.lua b/nselib/datafiles.lua
index 4748a7cd2..192a4d012 100644
--- a/nselib/datafiles.lua
+++ b/nselib/datafiles.lua
@@ -1,5 +1,6 @@
--- Read and parse some of Nmap's data files: nmap-protocols,
--- nmap-rpc, and nmap-services.
+-- nmap-rpc, nmap-services, and
+-- nmap-mac-prefixes.
--
-- The functions in this module return values appropriate for use with exception
-- handling via nmap.new_try. On success, they return true and
@@ -23,7 +24,8 @@ local common_files = {
["nmap-protocols"] = { [function(ln) return tonumber( ln:match( "^%s*[^%s#]+%s+(%d+)" ) ) end] = "^%s*([^%s#]+)%s+%d+" },
["nmap-services"] = { ["tcp"] = { [function(ln) return tonumber( ln:match( "^%s*[^%s#]+%s+(%d+)/tcp" ) ) end] = "^%s*([^%s#]+)%s+%d+/tcp" },
["udp"] = { [function(ln) return tonumber( ln:match( "^%s*[^%s#]+%s+(%d+)/udp" ) ) end] = "^%s*([^%s#]+)%s+%d+/udp" }
- }
+ },
+ ["nmap-mac-prefixes"] = { [ "^%s*(%w+)%s+[^#]+" ] = "^%s*%w+%s+([^#]+)" }
}
@@ -90,6 +92,23 @@ parse_services = function(protocol)
end
+---
+-- Read and parse nmap-mac-prefixes.
+--
+-- On success, return true and a table mapping 3 byte MAC prefixes to manufacturer names.
+-- @return Status (true or false).
+-- @return Table (if status is true) or error string (if status is false).
+-- @see parse_file
+parse_mac_prefixes = function()
+ local status, mac_prefixes_table = parse_file("nmap-mac-prefixes")
+ if not status then
+ return false, "Error parsing nmap-mac-prefixes"
+ end
+
+ return true, mac_prefixes_table
+end
+
+
---
-- Read and parse a generic data file. The other parse functions are
-- defined in terms of this one.
diff --git a/scripts/nbstat.nse b/scripts/nbstat.nse
index 4e02e3718..5ed58de9b 100644
--- a/scripts/nbstat.nse
+++ b/scripts/nbstat.nse
@@ -12,11 +12,11 @@ owns.
--
-- @output
-- Host script results:
--- |_ nbstat: NetBIOS name: WINDOWS2003, NetBIOS user: , NetBIOS MAC: 00:0c:29:c6:da:f5
+-- |_ nbstat: NetBIOS name: WINDOWS2003, NetBIOS user: , NetBIOS MAC: 00:0c:29:c6:da:f5 (VMware)
--
-- Host script results:
-- | nbstat:
--- | | NetBIOS name: WINDOWS2003, NetBIOS user: , NetBIOS MAC: 00:0c:29:c6:da:f5
+-- | | NetBIOS name: WINDOWS2003, NetBIOS user: , NetBIOS MAC: 00:0c:29:c6:da:f5 (VMware)
-- | | Names
-- | | | WINDOWS2003<00> Flags:
-- | | | WINDOWS2003<20> Flags:
@@ -34,6 +34,7 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "safe"}
require "netbios"
+require "datafiles"
hostrule = function(host)
@@ -67,8 +68,11 @@ action = function(host)
local status
local names, statistics
local server_name, user_name
- local mac
+ local mac, prefix, manuf
local response = {}
+ local catch = function() return end
+ local try = nmap.new_try(catch)
+
-- Get the list of NetBIOS names
status, names, statistics = netbios.do_nbstat(host.ip)
@@ -91,11 +95,24 @@ action = function(host)
return stdnse.format_output(false, user_name)
end
+ -- Build the MAC prefix lookup table
+ if not nmap.registry.nbstat then
+ -- Create the table in the registry so we can share between script instances
+ nmap.registry.nbstat = {}
+ nmap.registry.nbstat.mac_prefixes = try(datafiles.parse_mac_prefixes())
+ end
+
-- Format the Mac address in the standard way
if(#statistics >= 6) then
- mac = string.format("%02x:%02x:%02x:%02x:%02x:%02x", statistics:byte(1), statistics:byte(2), statistics:byte(3), statistics:byte(4), statistics:byte(5), statistics:byte(6))
- -- Samba doesn't set the Mac address
- if(mac == "00:00:00:00:00:00") then
+ -- MAC prefixes are matched on the first three bytes, all uppercase
+ prefix = string.upper(string.format("%02x%02x%02x", statistics:byte(1), statistics:byte(2), statistics:byte(3)))
+ manuf = nmap.registry.nbstat.mac_prefixes[prefix]
+ if manuf == nil then
+ manuf = "unknown"
+ end
+ mac = string.format("%02x:%02x:%02x:%02x:%02x:%02x (%s)", statistics:byte(1), statistics:byte(2), statistics:byte(3), statistics:byte(4), statistics:byte(5), statistics:byte(6), manuf)
+ -- Samba doesn't set the Mac address, and nmap-mac-prefixes shows that as Xerox
+ if(mac == "00:00:00:00:00:00 (Xerox)") then
mac = ""
end
else