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