mirror of
https://github.com/nmap/nmap.git
synced 2025-12-15 20:29:03 +00:00
[NSE] cccam-version.nse makes use of the new 'formulas' library.
This commit is contained in:
@@ -2,6 +2,7 @@ local bin = require "bin"
|
|||||||
local nmap = require "nmap"
|
local nmap = require "nmap"
|
||||||
local shortport = require "shortport"
|
local shortport = require "shortport"
|
||||||
local string = require "string"
|
local string = require "string"
|
||||||
|
local formulas = require "formulas"
|
||||||
|
|
||||||
description = [[
|
description = [[
|
||||||
Detects the CCcam service (software for sharing subscription TV among
|
Detects the CCcam service (software for sharing subscription TV among
|
||||||
@@ -19,81 +20,6 @@ categories = {"version"}
|
|||||||
|
|
||||||
author = "David Fifield"
|
author = "David Fifield"
|
||||||
|
|
||||||
|
|
||||||
-- A chi-square test for the null hypothesis that the members of data are drawn
|
|
||||||
-- from a uniform distribution over num_cats categories.
|
|
||||||
local function chi2(data, num_cats)
|
|
||||||
local bins = {}
|
|
||||||
local x2, delta, expected
|
|
||||||
|
|
||||||
for _, x in ipairs(data) do
|
|
||||||
bins[x] = bins[x] or 0
|
|
||||||
bins[x] = bins[x] + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
expected = #data / num_cats
|
|
||||||
x2 = 0.0
|
|
||||||
for _, n in pairs(bins) do
|
|
||||||
delta = n - expected
|
|
||||||
x2 = x2 + delta * delta
|
|
||||||
end
|
|
||||||
x2 = x2 / expected
|
|
||||||
|
|
||||||
return x2
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Split a string into a sequence of bit strings of the given length.
|
|
||||||
-- splitbits("abc", 5) --> {"01100", "00101", "10001", "00110"}
|
|
||||||
-- Any short final group is omitted.
|
|
||||||
local function splitbits(s, n)
|
|
||||||
local seq
|
|
||||||
|
|
||||||
local _, bits = bin.unpack("B" .. #s, s)
|
|
||||||
seq = {}
|
|
||||||
for i = 1, #bits - n, n do
|
|
||||||
seq[#seq + 1] = bits:sub(i, i + n - 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
return seq
|
|
||||||
end
|
|
||||||
|
|
||||||
-- chi-square cdf table at 0.95 confidence for different degrees of freedom.
|
|
||||||
-- >>> import scipy.stats, scipy.optimize
|
|
||||||
-- >>> scipy.optimize.newton(lambda x: scipy.stats.chi2(dof).cdf(x) - 0.95, dof)
|
|
||||||
local CHI2_CDF = {
|
|
||||||
[3] = 7.8147279032511738,
|
|
||||||
[15] = 24.99579013972863,
|
|
||||||
[255] = 293.2478350807001,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function looks_random(data)
|
|
||||||
local x2
|
|
||||||
|
|
||||||
-- Because our sample is so small (only 16 bytes), do a chi-square
|
|
||||||
-- goodness of fit test across groups of 2, 4, and 8 bits. If using only
|
|
||||||
-- 8 bits, for example, any sample whose bytes are all different would
|
|
||||||
-- pass the test. Using 2 bits will tend to catch things like pure
|
|
||||||
-- ASCII, where one out of every four samples never has its high bit
|
|
||||||
-- set.
|
|
||||||
|
|
||||||
x2 = chi2(splitbits(data, 2), 4)
|
|
||||||
if x2 > CHI2_CDF[3] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
x2 = chi2(splitbits(data, 4), 16)
|
|
||||||
if x2 > CHI2_CDF[15] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
x2 = chi2({string.byte(data, 1, -1)}, 256)
|
|
||||||
if x2 > CHI2_CDF[255] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local NUM_TRIALS = 2
|
local NUM_TRIALS = 2
|
||||||
|
|
||||||
local function trial(host, port)
|
local function trial(host, port)
|
||||||
@@ -127,7 +53,7 @@ function action(host, port)
|
|||||||
local data
|
local data
|
||||||
|
|
||||||
data = trial(host, port)
|
data = trial(host, port)
|
||||||
if not data or seen[data] or #data ~= 16 or not looks_random(data) then
|
if not data or seen[data] or #data ~= 16 or not formulas.looksRandom(data) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
seen[data] = true
|
seen[data] = true
|
||||||
|
|||||||
Reference in New Issue
Block a user