mirror of
https://github.com/nmap/nmap.git
synced 2025-12-10 09:49:05 +00:00
Move service fingerprint unwrapping code from scripts to lpeg-utility
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user