diff --git a/scripts/cccam-version.nse b/scripts/cccam-version.nse index 78f549cb1..a0f5fe69a 100644 --- a/scripts/cccam-version.nse +++ b/scripts/cccam-version.nse @@ -2,6 +2,7 @@ local bin = require "bin" local nmap = require "nmap" local shortport = require "shortport" local string = require "string" +local formulas = require "formulas" description = [[ Detects the CCcam service (software for sharing subscription TV among @@ -19,81 +20,6 @@ categories = {"version"} 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 function trial(host, port) @@ -127,7 +53,7 @@ function action(host, port) local data 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 end seen[data] = true