Nmap Development mailing list archives
Re: [NSE] Simple Banner Grabbing, Banner Grabber and Grabber of Banners - banner.nse
From: jah <jah () zadkiel plus com>
Date: Sat, 01 Nov 2008 14:08:37 +0000
On 01/11/2008 05:04, Kris Katterjohn wrote:
On 10/31/2008 11:41 PM, jah wrote:Hi folks,I was looking at Nmap's TODO list and saw mention of a banner grabbing script, so for some light relief I tidied-up a script I had for just such a purpose.I guess my idea wasn't so bad after all[1] :)
Hi Kris, Certainly not a bad idea. Even with --version-intensity 0 it's not possible to do pure banner grabbing without sending any probes and so using a script such as this is a good way to get maximum information without going as far as version scanning. And it's often helpful to know when a service blurts something out, without having to trawl through a --version-trace (which can be large with many targets or high intensity). The odd thing is that I did a search of nmap-dev after I saw banner grabbing mentioned in the TODO list to make sure the script wasn't already floating around. I saw a thread from 2006 where it was suggested to use Amap and some stuff from 2002 which I didn't even look at. Where was your cleverly titled post [1] in these results? I guess my search term should have been "banner grabber" rather than "banner grabbing"...
It doesn't do anything clever, just connects a socket and returns anything presented to it- From a quick glance, I see that you use a grab_banner() function of your own for this. I wrote banner-grabbing functionality into the Comm library; does it not suffice for you here? If not, maybe it can be updated a little to support your use somehow.
Good point. The Comm library already does what the script needs so attached is an updated version of the script. Cheers for the input, jah
[1] http://seclists.org/nmap-dev/2007/q2/0372.html
id = "Banner" description = [[ A simple banner grabber. Connects to an open or open|filtered port and prints out anything issued by a listening service. The banner will be truncated to fit into a single line, but an extra line may be printed for every increase in the level of verbosity requested on the command line. ]] author = "jah <jah at zadkiel.plus.com>" license = "See Nmap License: http://nmap.org/book/man-legal.html" runlevel = 1 categories = {"discovery", "safe"} local nmap = require "nmap" local comm = require "comm" local stdnse = require "stdnse" -- The width of your screen. You must choose, but choose wisely. -- For as the true number will bring you pretty output, -- the false number will take it from you. local line_len = 75 --- -- Always returns true. portrule = function( host, port ) return true end --- -- Grabs a banner and outputs it nicely formatted. action = function( host, port ) local out = grab_banner(host, port) return output( out ) end --- -- Connects to the target on the given port and returns any data issued by a listening service. -- @param host Host Table. -- @param port Port Table. -- @return String or nil if data was not recieved. function grab_banner(host, port) local opts = {} opts.timeout = get_timeout() opts.protocol = port.protocol local status, response = comm.get_banner(host.ip, port.number, opts) if not status then stdnse.print_debug(((response == "EOF" or response == "TIMEOUT") and 3) or nil, "%s No Banner from %s on %s %s: %s", id, host.ip, port.number, port.protocol, response or "No Error." ) return nil end return response end --- -- Returns a number of milliseconds for use as a socket timeout value. The number is based on nmap's timing level: -- * T0 = 15000 ms -- * T1 = 10000 ms -- * T2 = 7000 ms -- * T3 = 5000 ms -- * T4 = 5000 ms -- * T5 = 5000 ms -- @return Number of milliseconds. function get_timeout() local timeout = {[0] = 15000, 10000, 7000} return timeout[nmap.timing_level()] or 5000 end --- -- Formats the banner for printing to the port script result. Non-printable characters are hex encoded and the banner is -- then truncated to fit into the number of lines of output desired. -- @param out String banner issued by a listening service. -- @return String formatted for output. function output( out ) if type(out) ~= "string" or out == "" then return nil end local fline_offset = 5 -- number of chars excluding script id not available to the script on the first line local fline_len = line_len -1 -id:len() -fline_offset -- number of chars allowed on first line local sline_len = line_len -1 -(fline_offset-2) -- number of chars allowed on subsequent lines local total_out_chars = fline_len + ( extra_output()*sline_len ) -- replace non-printable ascii chars - no need to do the whole string out = replace_nonprint(out, 1+total_out_chars) -- 1 extra char so we can truncate below. -- truncate banner to total_out_chars ensuring we remove whole hex encoded chars if out:len() > total_out_chars then while out:len() > total_out_chars do if (out:sub(-4,-1)):match("\\x%x%x") then out = out:sub(1,-1-4) else out = out:sub(1,-1-1) end end out = ("%s..."):format(out:sub(1,total_out_chars-3)) -- -3 for ellipsis end -- break into lines - this will look shit if line_len is more than the actual space available on a line... local ptr = fline_len local t = {} while true do if out:len() >= ptr then t[#t+1] = out:sub(1,ptr) out = out:sub(ptr+1,-1) ptr = sline_len else t[#t+1] = out break end end return table.concat(t,"\n") end --- -- Replaces characters with ASCII values outside of the range of standard printable -- characters (decimal 32 to 126 inclusive) with hex encoded equivalents. -- The second paramater dictates the number of characters to return, however, if the -- last character before the number is reached is one that needs replacing then up to -- three characters more than this number may be returned. -- If the second parameter is nil, no limit is applied to the number of characters -- that may be returned. -- @param s String on which to perform substitutions. -- @param len Number of characters to return. -- @return String. function replace_nonprint( s, len ) local t = {} local count = 0 for c in s:gmatch(".") do if c:byte() < 32 or c:byte() > 126 then t[#t+1] = ("\\x%s"):format( ("0%s"):format( ( (stdnse.tohex( c:byte() )):upper() ) ):sub(-2,-1) ) -- capiche count = count+4 else t[#t+1] = c count = count+1 end if type(len) == "number" and count >= len then break end end return table.concat(t) end --- -- Returns a number for each level of verbosity specified on the command line. -- Ignores level increases resulting from debugging level. -- @return Number function extra_output() return (nmap.verbosity()-nmap.debugging()>0 and nmap.verbosity()-nmap.debugging()) or 0 end
_______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://SecLists.Org
Current thread:
- [NSE] Simple Banner Grabbingbanner.nse jah (Oct 31)
- Re: [NSE] Simple Banner Grabbingbanner.nse Kris Katterjohn (Oct 31)
- Re: [NSE] Simple Banner Grabbing, Banner Grabber and Grabber of Banners - banner.nse jah (Nov 01)
- Re: [NSE] Simple Banner Grabbingbanner.nse Kris Katterjohn (Oct 31)
- Re: [NSE] Simple Banner Grabbingbanner.nse Fyodor (Nov 03)