diff --git a/nselib/lpeg-utility.lua b/nselib/lpeg-utility.lua index 3c6a39c94..b9313d7ad 100644 --- a/nselib/lpeg-utility.lua +++ b/nselib/lpeg-utility.lua @@ -10,6 +10,8 @@ local assert = assert local lpeg = require "lpeg" local stdnse = require "stdnse" local pairs = pairs +local string = require "string" +local tonumber = tonumber _ENV = {} @@ -118,4 +120,34 @@ function debug (grammar, printer) return grammar end +do + -- Cache the returned pattern + local getquote = escaped_quote() + + -- Substitution pattern to unescape a string + local unescape = lpeg.P { + -- Substitute captures + lpeg.Cs((lpeg.V "simple_char" + lpeg.V "unesc")^0), + -- Escape char is '\' + esc = lpeg.P "\\", + -- Simple char is anything but escape char + simple_char = lpeg.P(1) - lpeg.V "esc", + -- If we hit an escape, process specials or hex code, otherwise remove the escape + unesc = (lpeg.V "esc" * lpeg.Cs( lpeg.V "specials" + lpeg.V "code" + lpeg.P(1) ))/"%1", + -- single-char escapes. These are the only ones service_scan uses + specials = lpeg.S "trn0" / {t="\t", r="\r", n="\n", ["0"]="\0"}, + -- hex escape: convert to char + code = (lpeg.P "x" * lpeg.C(lpeg.S "0123456789abcdefABCDEF"^-2))/function(c) + return string.char(tonumber(c,16)) end, + } + + --- Turn the service fingerprint reply to a probe into a binary blob + function get_response (fp, probe) + fp = string.gsub(fp, "\nSF:", "") + local i, e = string.find(fp, string.format("%s,%%x+,", probe)) + if i == nil then return nil end + return unescape:match(getquote:match(fp, e+1)) + end +end + return _ENV diff --git a/scripts/http-server-header.nse b/scripts/http-server-header.nse index f109dc4c7..75332fa57 100644 --- a/scripts/http-server-header.nse +++ b/scripts/http-server-header.nse @@ -4,7 +4,6 @@ local table = require "table" local shortport = require "shortport" local nmap = require "nmap" local stdnse = require "stdnse" -local lpeg = require "lpeg" local U = require "lpeg-utility" description = [[ @@ -37,43 +36,15 @@ portrule = function(host, port) return (shortport.http(host,port) and nmap.version_intensity() >= 7) end --- Cache the returned pattern -local getquote = U.escaped_quote() - --- Substitution pattern to unescape a string -local unescape = lpeg.P { - -- Substitute captures - lpeg.Cs((lpeg.V "simple_char" + lpeg.V "unesc")^0), - -- Escape char is '\' - esc = lpeg.P "\\", - -- Simple char is anything but escape char - simple_char = lpeg.P(1) - lpeg.V "esc", - -- If we hit an escape, process specials or hex code, otherwise remove the escape - unesc = (lpeg.V "esc" * lpeg.Cs( lpeg.V "specials" + lpeg.V "code" + lpeg.P(1) ))/"%1", - -- single-char escapes. These are the only ones service_scan uses - specials = lpeg.S "trn0" / {t="\t", r="\r", n="\n", ["0"]="\0"}, - -- hex escape: convert to char - code = (lpeg.P "x" * lpeg.C(lpeg.S "0123456789abcdefABCDEF"^-2))/function(c) - return string.char(tonumber(c,16)) end, -} - --- Turn the service fingerprint reply to a probe into a binary blob -local function get_response (fp, probe) - local i, e = string.find(fp, string.format("%s,%%x+,", probe)) - if i == nil then return nil end - return unescape:match(getquote:match(fp, e+1)) -end - action = function(host, port) local responses = {} -- Did the service engine already do the hard work? if port.version and port.version.service_fp then - -- Probes sent, replies received, but no match. Unwrap the fingerprint: - local fp = string.gsub(port.version.service_fp, "\nSF:", "") + -- Probes sent, replies received, but no match. -- Loop through the probes most likely to receive HTTP responses for _, p in ipairs({"GetRequest", "GenericLines", "HTTPOptions", "FourOhFourRequest", "NULL", "RTSPRequest", "Help", "SIPOptions"}) do - responses[#responses+1] = get_response(fp, p) + responses[#responses+1] = U.get_response(port.version.service_fp, p) end end if #responses == 0 then diff --git a/scripts/snmp-info.nse b/scripts/snmp-info.nse index 294a28067..b273c1629 100644 --- a/scripts/snmp-info.nse +++ b/scripts/snmp-info.nse @@ -5,8 +5,6 @@ local nmap = require "nmap" local shortport = require "shortport" local snmp = require "snmp" local stdnse = require "stdnse" -local string = require "string" -local lpeg = require "lpeg" local U = require "lpeg-utility" local comm = require "comm" @@ -40,36 +38,6 @@ categories = {"default", "version", "safe"} portrule = shortport.version_port_or_service(161, "snmp", "udp") --- XXX This section copied from http-server-header. Should be moved to a library. --- Cache the returned pattern -local getquote = U.escaped_quote() - --- Substitution pattern to unescape a string -local unescape = lpeg.P { - -- Substitute captures - lpeg.Cs((lpeg.V "simple_char" + lpeg.V "unesc")^0), - -- Escape char is '\' - esc = lpeg.P "\\", - -- Simple char is anything but escape char - simple_char = lpeg.P(1) - lpeg.V "esc", - -- If we hit an escape, process specials or hex code, otherwise remove the escape - unesc = (lpeg.V "esc" * lpeg.Cs( lpeg.V "specials" + lpeg.V "code" + lpeg.P(1) ))/"%1", - -- single-char escapes. These are the only ones service_scan uses - specials = lpeg.S "trn0" / {t="\t", r="\r", n="\n", ["0"]="\0"}, - -- hex escape: convert to char - code = (lpeg.P "x" * lpeg.C(lpeg.S "0123456789abcdefABCDEF"^-2))/function(c) - return string.char(tonumber(c,16)) end, -} - --- Turn the service fingerprint reply to a probe into a binary blob -local function get_response (fp, probe) - local i, e = string.find(fp, string.format("%s,%%x+,", probe)) - if i == nil then return nil end - return unescape:match(getquote:match(fp, e+1)) -end - --- XXX End copy-paste. - local ENTERPRISE_NUMS do local status @@ -91,9 +59,8 @@ action = function (host, port) local response -- Did the service engine already do the hard work? if port.version and port.version.service_fp then - -- Probes sent, replies received, but no match. Unwrap the fingerprint: - local fp = string.gsub(port.version.service_fp, "\nSF:", "") - response = get_response(fp, "SNMPv3GetRequest") + -- Probes sent, replies received, but no match. + response = U.get_response(port.version.service_fp, "SNMPv3GetRequest") end if not response then