mirror of
https://github.com/nmap/nmap.git
synced 2025-12-10 17:59:04 +00:00
I hope this will recover nselib history
This commit is contained in:
27
nselib/Makefile.in
Normal file
27
nselib/Makefile.in
Normal file
@@ -0,0 +1,27 @@
|
||||
PLATFORM=@host@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
CCOPT =
|
||||
DBGFLAGS =
|
||||
|
||||
|
||||
SHTOOL = ../shtool
|
||||
INSTALL = $(SHTOOL) install
|
||||
|
||||
LIBTOOL= ./libtool
|
||||
LTFLAGS = --tag=CC --silent
|
||||
|
||||
all: bit.so
|
||||
|
||||
bit.so: bit.c @LIBTOOL_DEPS@
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) @LUAINCLUDE@ $(CFLAGS) -c bit.c
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) -avoid-version -module -rpath /usr/local/lib -o bit.la bit.lo
|
||||
mv .libs/bit.so bit.so
|
||||
|
||||
clean:
|
||||
rm -f bit.so *.la *.lo
|
||||
rm -rf .libs
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.log config.status libtool
|
||||
6389
nselib/aclocal.m4
vendored
Normal file
6389
nselib/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
70
nselib/bit.c
Normal file
70
nselib/bit.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/* Bitwise operations library
|
||||
* by Reuben Thomas (rrt@sc3d.org)
|
||||
* bitlib is a C library for Lua 5.x that provides bitwise operations
|
||||
* It is copyright Reuben Thomas 2000-2006, and is released under the
|
||||
* MIT license, like Lua (see http://www.lua.org/copyright.html for the
|
||||
* full license; it's basically the same as the BSD license). There is no
|
||||
* warranty.
|
||||
* the most recent copy can be found at http://rrt.sc3d.org/Software/Lua/
|
||||
**/
|
||||
|
||||
#include "bit.h"
|
||||
|
||||
typedef long long Integer;
|
||||
typedef unsigned long long UInteger;
|
||||
|
||||
#define luaL_checkbit(L, n) ((Integer)luaL_checknumber(L, n))
|
||||
#define luaL_checkubit(L, n) ((UInteger)luaL_checkbit(L, n))
|
||||
|
||||
#define TDYADIC(name, op, checkbit1, checkbit2) \
|
||||
static int bit_ ## name(lua_State* L) { \
|
||||
lua_pushnumber(L, \
|
||||
(lua_Number)(checkbit1(L, 1) op checkbit2(L, 2))); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define DYADIC(name, op) \
|
||||
TDYADIC(name, op, luaL_checkbit, luaL_checkbit)
|
||||
|
||||
#define MONADIC(name, op) \
|
||||
static int bit_ ## name(lua_State* L) { \
|
||||
lua_pushnumber(L, (lua_Number)(op luaL_checkbit(L, 1))); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define VARIADIC(name, op) \
|
||||
static int bit_ ## name(lua_State *L) { \
|
||||
int n = lua_gettop(L), i; \
|
||||
Integer w = luaL_checkbit(L, 1); \
|
||||
for (i = 2; i <= n; i++) \
|
||||
w op luaL_checkbit(L, i); \
|
||||
lua_pushnumber(L, (lua_Number)w); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
MONADIC(bnot, ~)
|
||||
VARIADIC(band, &=)
|
||||
VARIADIC(bor, |=)
|
||||
VARIADIC(bxor, ^=)
|
||||
TDYADIC(lshift, <<, luaL_checkbit, luaL_checkubit)
|
||||
TDYADIC(rshift, >>, luaL_checkubit, luaL_checkubit)
|
||||
TDYADIC(arshift, >>, luaL_checkbit, luaL_checkubit)
|
||||
DYADIC(mod, %)
|
||||
|
||||
static const struct luaL_reg bitlib[] = {
|
||||
{"bnot", bit_bnot},
|
||||
{"band", bit_band},
|
||||
{"bor", bit_bor},
|
||||
{"bxor", bit_bxor},
|
||||
{"lshift", bit_lshift},
|
||||
{"rshift", bit_rshift},
|
||||
{"arshift", bit_arshift},
|
||||
{"mod", bit_mod},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
LUALIB_API int luaopen_bit(lua_State *L) {
|
||||
luaL_openlib(L, BITLIBNAME, bitlib, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
12
nselib/bit.h
Normal file
12
nselib/bit.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef BITLIB
|
||||
#define BITLIB
|
||||
|
||||
#define BITLIBNAME "bit"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lua.h"
|
||||
|
||||
LUALIB_API int luaopen_bit(lua_State *L);
|
||||
|
||||
#endif
|
||||
|
||||
19557
nselib/configure
vendored
Executable file
19557
nselib/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
23
nselib/configure.ac
Normal file
23
nselib/configure.ac
Normal file
@@ -0,0 +1,23 @@
|
||||
AC_PREREQ(2.13)
|
||||
AC_INIT([nselib.h])
|
||||
|
||||
AC_PROG_CC
|
||||
|
||||
# we want to compile lua modules written in C - which are shared libraries
|
||||
# therefore disable building static libs - we shouldn't need them
|
||||
AC_DISABLE_STATIC
|
||||
AC_LIBTOOL_DLOPEN
|
||||
AC_PROG_LIBTOOL
|
||||
AC_SUBST(LIBTOOL)
|
||||
|
||||
AC_SUBST(LIBTOOL_DEPS)
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
# needed for lua-includes
|
||||
AC_CHECK_HEADER([lua.h],,[AC_MSG_NOTICE(using lua-includefiles provided with nmap);[LUAINCLUDE=-I../liblua/]],)
|
||||
AC_SUBST(LUAINCLUDE)
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
32
nselib/ipOps.lua
Normal file
32
nselib/ipOps.lua
Normal file
@@ -0,0 +1,32 @@
|
||||
-- See nmaps COPYING for licence
|
||||
module(...,package.seeall)
|
||||
|
||||
|
||||
-- check to see if ip is part of RFC 1918 address space
|
||||
isPrivate = function(ip)
|
||||
local a, b
|
||||
a, b = get_parts_as_number(ip)
|
||||
if a == 10 then
|
||||
return true
|
||||
elseif a == 172 and (b>15 and b<32) then
|
||||
return true
|
||||
elseif a == 192 and b == 168 then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
todword = function(ip)
|
||||
local a, b, c, d
|
||||
a,b,c,d = get_parts_as_number(ip)
|
||||
return (((a*256+b))*256+c)*256+d
|
||||
end
|
||||
|
||||
get_parts_as_number = function(ip)
|
||||
local a,b,c,d = string.match(ip, "(%d+)%.(%d+)%.(%d+)%.(%d+)")
|
||||
a = tonumber(a);
|
||||
b = tonumber(b);
|
||||
c = tonumber(c);
|
||||
d = tonumber(d);
|
||||
return a,b,c,d
|
||||
end
|
||||
134
nselib/listop.lua
Normal file
134
nselib/listop.lua
Normal file
@@ -0,0 +1,134 @@
|
||||
-- See nmaps COPYING for licence
|
||||
module(..., package.seeall)
|
||||
|
||||
--[[
|
||||
--
|
||||
Functional programming style 'list' operations
|
||||
|
||||
bool is_empty(list)
|
||||
bool is_list(value)
|
||||
|
||||
value apply(function, list)
|
||||
list map(function, list)
|
||||
list filter(function, list)
|
||||
list flatten(list)
|
||||
list append(list1, list2)
|
||||
list cons(value1, value2)
|
||||
list reverse(list)
|
||||
|
||||
value car(list)
|
||||
value ncar(list, x)
|
||||
list cdr(list)
|
||||
list ncdr(list, x)
|
||||
|
||||
where 'list' is an indexed table
|
||||
where 'value' is an lua datatype
|
||||
--]]
|
||||
|
||||
-- true if l is empty
|
||||
function is_empty(l)
|
||||
return table.getn(l) == 0 and true or false
|
||||
end
|
||||
|
||||
-- true if l is a list
|
||||
function is_list(l)
|
||||
return type(l) == 'table' and true or false
|
||||
end
|
||||
|
||||
-- Pass each elements of l to a function f which takes a single
|
||||
-- argument. All the results are returned in an list
|
||||
function map(f, l)
|
||||
local results = {}
|
||||
for i, v in ipairs(l) do
|
||||
table.insert(results, f(v))
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
-- Pass all elements of l to function f which takes a variable
|
||||
-- number of arguments or a number of arguments equal to the
|
||||
-- size of l. The result of f is returned
|
||||
function apply(f, l)
|
||||
return f(unpack(l))
|
||||
end
|
||||
|
||||
-- Pass all elements of l to a predicate function f which takes a single
|
||||
-- argument. All elements where f(l[x]) is true are returned in an
|
||||
-- indexed list
|
||||
function filter(f, l)
|
||||
local results = {}
|
||||
for i, v in ipairs(l) do
|
||||
if(f(v)) then
|
||||
table.insert(results, v)
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
-- return first element of a list
|
||||
function car(l)
|
||||
return l[1]
|
||||
end
|
||||
|
||||
-- return everything but the first element of a list
|
||||
function cdr(l)
|
||||
return ncdr(l)
|
||||
end
|
||||
|
||||
-- same as car but start at element x
|
||||
function ncar(l, x)
|
||||
x = x or 1
|
||||
return l[x]
|
||||
end
|
||||
|
||||
-- same as cdr but start at element x
|
||||
function ncdr(l, x)
|
||||
local results = {}
|
||||
x = x or 2
|
||||
for i = x, table.getn(l) do
|
||||
results[i-1] = l[i]
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
-- prepend a value or list to another value or list
|
||||
function cons(v1, v2)
|
||||
return{ is_list(v1) and {unpack(v1)} or v1, is_list(v2) and {unpack(v2)} or v2}
|
||||
end
|
||||
|
||||
-- concatenate two lists and return the result
|
||||
function append(l1, l2)
|
||||
local results = {}
|
||||
for i, v in ipairs(l1) do
|
||||
table.insert(results, v)
|
||||
end
|
||||
|
||||
for i, v in ipairs(l2) do
|
||||
table.insert(results, v)
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
-- returned l in reverse order
|
||||
function reverse(l)
|
||||
local results = {}
|
||||
for i=table.getn(l), 1, -1 do
|
||||
table.insert(results, l[i])
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
-- return a flat version of nested list l
|
||||
function flatten(l)
|
||||
local function flat(r, t)
|
||||
for i, v in ipairs(t) do
|
||||
if(type(v) == 'table') then
|
||||
flat(r, v)
|
||||
else
|
||||
table.insert(r, v)
|
||||
end
|
||||
end
|
||||
return r
|
||||
end
|
||||
return flat({}, l)
|
||||
end
|
||||
31
nselib/match.lua
Normal file
31
nselib/match.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
-- See nmaps COPYING for licence
|
||||
module(..., package.seeall)
|
||||
require "pcre"
|
||||
|
||||
--various functions for use with nse's nsock:receive_buf - function
|
||||
|
||||
-- e.g.
|
||||
-- sock:receivebuf(regex("myregexpattern")) - does a match using pcre- regular-
|
||||
-- - expressions
|
||||
-- sock:receivebuf(numbytes(80)) - is the buffered version of
|
||||
-- sock:receive_bytes(80) - i.e. it returns
|
||||
-- exactly 80 bytes and no more
|
||||
regex = function(pattern)
|
||||
local r = pcre.new(pattern, 0,"C")
|
||||
|
||||
return function(buf)
|
||||
s,e = r:exec(buf, 0,0);
|
||||
return s,e
|
||||
end
|
||||
end
|
||||
|
||||
numbytes = function(num)
|
||||
local n = num
|
||||
return function(buf)
|
||||
if(string.len(buf) >=n) then
|
||||
return n, n
|
||||
end
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
205
nselib/nse_bitlib.vcproj
Normal file
205
nselib/nse_bitlib.vcproj
Normal file
@@ -0,0 +1,205 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="nse_bitlib"
|
||||
ProjectGUID="{FB7F6FD2-A39D-40A1-86DD-9B08370BDEA6}"
|
||||
RootNamespace="nse_bitlib"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\liblua"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;NSE_BITLIB_EXPORTS;WIN32;LUA_BUILD_AS_DLL;LUA_LIB"
|
||||
MinimalRebuild="false"
|
||||
ExceptionHandling="0"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="2"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="0"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="liblua.lib"
|
||||
OutputFile=".\bit.dll"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="..\liblua"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="xcopy "$(SolutionDir)..\nselib\*.lua" "$(SolutionDir)\$(ConfigurationName)\nselib\" /y && xcopy "$(SolutionDir)..\nselib\*.dll" "$(SolutionDir)\$(ConfigurationName)\nselib\" /y"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\liblua"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;NSE_BITLIB_EXPORTS;WIN32;LUA_BUILD_AS_DLL;LUA_LIB"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
CompileAs="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="liblua.lib"
|
||||
OutputFile=".\bit.dll"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="..\liblua"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
CommandLine="xcopy "$(SolutionDir)..\nselib\*.lua" "$(SolutionDir)\$(ConfigurationName)\nselib\" /y && xcopy "$(SolutionDir)..\nselib\*.dll" "$(SolutionDir)\$(ConfigurationName)\nselib\" /y"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\bit.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\bit.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
8
nselib/nselib.h
Normal file
8
nselib/nselib.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef NSE_LIB
|
||||
#define NSE_LIB
|
||||
|
||||
#define NSE_BITLIBNAME "bit"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
559
nselib/packet.lua
Normal file
559
nselib/packet.lua
Normal file
@@ -0,0 +1,559 @@
|
||||
-- license = "See nmaps COPYING for license"
|
||||
module("packet" ,package.seeall)
|
||||
|
||||
-- Raw package parsing functions. Used with raw sockets
|
||||
-- in nse.
|
||||
-- Author: Marek Majkowski <majek04+nse@gmail.com>
|
||||
|
||||
--[[
|
||||
--]]
|
||||
|
||||
|
||||
require "bit"
|
||||
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
-- extract number from binary string
|
||||
function u8(b, i)
|
||||
return string.byte(b, i+1)
|
||||
end
|
||||
function u16(b, i)
|
||||
local b1,b2
|
||||
b1, b2 = string.byte(b, i+1), string.byte(b, i+2)
|
||||
-- 2^8 2^0
|
||||
return b1*256 + b2
|
||||
end
|
||||
function u32(b,i)
|
||||
local b1,b2,b3,b4
|
||||
b1, b2 = string.byte(b, i+1), string.byte(b, i+2)
|
||||
b3, b4 = string.byte(b, i+3), string.byte(b, i+4)
|
||||
-- 2^24 2^16 2^8 2^0
|
||||
return b1*16777216 + b2*65536 + b3*256 + b4
|
||||
end
|
||||
|
||||
-- insert number to binary string
|
||||
function set_u8(b, i, num)
|
||||
local s = string.char(bit.band(num, 0xff))
|
||||
return b:sub(0+1, i+1-1) .. s .. b:sub(i+1+1)
|
||||
end
|
||||
function set_u16(b, i, num)
|
||||
local s = string.char(bit.band(bit.rshift(num, 8), 0xff)) .. string.char(bit.band(num, 0xff))
|
||||
return b:sub(0+1, i+1-1) .. s .. b:sub(i+1+2)
|
||||
end
|
||||
function set_u32(b,i, num)
|
||||
local s = string.char(bit.band(bit.rshift(num,24), 0xff)) ..
|
||||
string.char(bit.band(bit.rshift(num,16), 0xff)) ..
|
||||
string.char(bit.band(bit.rshift(num,8), 0xff)) ..
|
||||
string.char(bit.band(num, 0xff))
|
||||
return b:sub(0+1, i+1-1) .. s .. b:sub(i+1+4)
|
||||
end
|
||||
|
||||
|
||||
-- Checksum
|
||||
---- Standard BSD internet checksum routine check nmap/tcpip.cc
|
||||
function in_cksum(b)
|
||||
local sum = 0
|
||||
local c
|
||||
local x = b
|
||||
|
||||
while x:len() > 1 do
|
||||
c = x:sub(1,2)
|
||||
x = x:sub(3)
|
||||
sum = sum + u16(c, 0)
|
||||
end
|
||||
|
||||
sum = bit.rshift(sum, 16) + bit.band(sum, 0xffff)
|
||||
sum = sum + bit.rshift(sum, 16)
|
||||
sum = bit.bnot(sum)
|
||||
sum = bit.band(sum, 0xffff) -- trunctate to 16 bits
|
||||
return sum
|
||||
end
|
||||
|
||||
-- ip protocol field
|
||||
IPPROTO_IP = 0 -- Dummy protocol for TCP
|
||||
IPPROTO_ICMP = 1 -- Internet Control Message Protocol
|
||||
IPPROTO_IGMP = 2 -- Internet Group Management Protocol
|
||||
IPPROTO_IPIP = 4 -- IPIP tunnels (older KA9Q tunnels use 94)
|
||||
IPPROTO_TCP = 6 -- Transmission Control Protocol
|
||||
IPPROTO_EGP = 8 -- Exterior Gateway Protocol
|
||||
IPPROTO_PUP = 12 -- PUP protocol
|
||||
IPPROTO_UDP = 17 -- User Datagram Protocol
|
||||
IPPROTO_IDP = 22 -- XNS IDP protocol
|
||||
IPPROTO_DCCP = 33 -- Datagram Congestion Control Protocol
|
||||
IPPROTO_RSVP = 46 -- RSVP protocol
|
||||
IPPROTO_GRE = 47 -- Cisco GRE tunnels (rfc 1701,1702)
|
||||
IPPROTO_IPV6 = 41 -- IPv6-in-IPv4 tunnelling
|
||||
|
||||
IPPROTO_ESP = 50 -- Encapsulation Security Payload protocol
|
||||
IPPROTO_AH = 51 -- Authentication Header protocol
|
||||
IPPROTO_BEETPH = 94 -- IP option pseudo header for BEET
|
||||
IPPROTO_PIM = 103 -- Protocol Independent Multicast
|
||||
|
||||
IPPROTO_COMP = 108 -- Compression Header protocol
|
||||
IPPROTO_SCTP = 132 -- Stream Control Transport Protocol
|
||||
IPPROTO_UDPLITE = 136 -- UDP-Lite (RFC 3828)
|
||||
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
-- Packet is a class
|
||||
Packet = {}
|
||||
-- Constructor
|
||||
-- packet - binary string with packet data
|
||||
-- packet_len - packet length, it could be more than string.len(packet)
|
||||
-- force_continue - whether error in parsing headers should be fatal or not.
|
||||
-- especially usefull at parsing icmp packets, where on small icmp payload
|
||||
-- could be tcp header. The problem is that parsing this payload normally
|
||||
-- would fail (broken packet, because tcp header is too small)
|
||||
-- The basic question is if too short tcp header should be treated as fatal error.
|
||||
function Packet:new(packet, packet_len, force_continue)
|
||||
local o = setmetatable({}, {__index = Packet})
|
||||
o.buf = packet
|
||||
o.packet_len = packet_len
|
||||
if not o:ip_parse(force_continue) then
|
||||
return nil
|
||||
end
|
||||
if o.ip_p == IPPROTO_TCP then
|
||||
if not o:tcp_parse(force_continue) then
|
||||
io.write("Error while parsing TCP packet\n")
|
||||
end
|
||||
elseif o.ip_p == IPPROTO_ICMP then
|
||||
if not o:icmp_parse(force_continue) then
|
||||
io.write("Error while parsing ICMP packet\n")
|
||||
end
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
-- Helpers
|
||||
|
||||
|
||||
-- from ip notation as string (like 1.2.3.4) to raw_string(4 bytes long)
|
||||
function iptobin(str)
|
||||
local ret = ""
|
||||
for c in string.gmatch(str, "[0-9]+") do
|
||||
ret = ret .. string.char(c+0) -- automatic conversion to int
|
||||
end
|
||||
return ret
|
||||
end
|
||||
-- from raw_ip (four bytes string) to dot-notation (like 1.2.3.4)
|
||||
function toip(raw_ip_addr)
|
||||
if not raw_ip_addr then
|
||||
return "?.?.?.?"
|
||||
end
|
||||
return string.format("%i.%i.%i.%i", string.byte(raw_ip_addr,1,4))
|
||||
end
|
||||
-- get unsigned byte
|
||||
function Packet:u8(index)
|
||||
return u8(self.buf, index)
|
||||
end
|
||||
function Packet:u16(index)
|
||||
return u16(self.buf, index)
|
||||
end
|
||||
function Packet:u32(index)
|
||||
return u32(self.buf, index)
|
||||
end
|
||||
function Packet:raw(index, length)
|
||||
return string.char(string.byte(self.buf, index+1, index+1+length-1))
|
||||
end
|
||||
|
||||
function Packet:set_u8(index, num)
|
||||
self.buf = set_u8(self.buf, index, num)
|
||||
return self.buf
|
||||
end
|
||||
function Packet:set_u16(index, num)
|
||||
self.buf = set_u16(self.buf, index, num)
|
||||
return self.buf
|
||||
end
|
||||
function Packet:set_u32(index, num)
|
||||
self.buf = set_u32(self.buf, index, num)
|
||||
return self.buf
|
||||
end
|
||||
|
||||
-- PARSE IP PACKET HEADER
|
||||
function Packet:ip_parse(force_continue)
|
||||
self.ip_offset = 0
|
||||
if string.len(self.buf) < 20 then -- too short
|
||||
return false
|
||||
end
|
||||
self.ip_v = bit.rshift(bit.band(self:u8(self.ip_offset + 0), 0xF0), 4)
|
||||
self.ip_hl = bit.band(self:u8(self.ip_offset + 0), 0x0F) -- header_length or data_offset
|
||||
if self.ip_v ~= 4 then -- not ip
|
||||
return false
|
||||
end
|
||||
self.ip = true
|
||||
self.ip_tos = self:u8(self.ip_offset + 1)
|
||||
self.ip_len = self:u16(self.ip_offset + 2)
|
||||
self.ip_id = self:u16(self.ip_offset + 4)
|
||||
self.ip_off = self:u16(self.ip_offset + 6)
|
||||
self.ip_rf = bit.band(self.ip_off, 0x8000)~=0 -- true/false
|
||||
self.ip_df = bit.band(self.ip_off, 0x4000)~=0
|
||||
self.ip_mf = bit.band(self.ip_off, 0x2000)~=0
|
||||
self.ip_off = bit.band(self.ip_off, 0x1FFF) -- fragment offset
|
||||
self.ip_ttl = self:u8(self.ip_offset + 8)
|
||||
self.ip_p = self:u8(self.ip_offset + 9)
|
||||
self.ip_sum = self:u16(self.ip_offset + 10)
|
||||
self.ip_bin_src = self:raw(self.ip_offset + 12,4) -- raw 4-bytes string
|
||||
self.ip_bin_dst = self:raw(self.ip_offset + 16,4)
|
||||
self.ip_src = toip(self.ip_bin_src) -- formatted string
|
||||
self.ip_dst = toip(self.ip_bin_dst)
|
||||
self.ip_opt_offset = self.ip_offset + 20
|
||||
self.ip_options = self:parse_options(self.ip_opt_offset, ((self.ip_hl*4)-20))
|
||||
self.ip_data_offset = self.ip_offset + self.ip_hl*4
|
||||
return true
|
||||
end
|
||||
-- set header length field
|
||||
function Packet:ip_set_hl(len)
|
||||
self:set_u8(self.ip_offset + 0, bit.bor(bit.lshift(self.ip_v, 4), bit.band(len, 0x0F)))
|
||||
self.ip_v = bit.rshift(bit.band(self:u8(self.ip_offset + 0), 0xF0), 4)
|
||||
self.ip_hl = bit.band(self:u8(self.ip_offset + 0), 0x0F) -- header_length or data_offset
|
||||
end
|
||||
-- set packet length field
|
||||
function Packet:ip_set_len(len)
|
||||
self:set_u16(self.ip_offset + 2, len)
|
||||
end
|
||||
-- set ttl
|
||||
function Packet:ip_set_ttl(ttl)
|
||||
self:set_u8(self.ip_offset + 8, ttl)
|
||||
end
|
||||
-- set checksum
|
||||
function Packet:ip_set_checksum(checksum)
|
||||
self:set_u16(self.ip_offset + 10, checksum)
|
||||
end
|
||||
-- count checksum for packet and save it
|
||||
function Packet:ip_count_checksum()
|
||||
self:ip_set_checksum(0)
|
||||
local csum = in_cksum( self.buf:sub(0, self.ip_offset + self.ip_hl*4) )
|
||||
self:ip_set_checksum(csum)
|
||||
end
|
||||
-- set source ip
|
||||
function Packet:ip_set_bin_src(binip)
|
||||
nrip = u32(binip, 0)
|
||||
self:set_u32(self.ip_offset + 12, nrip)
|
||||
self.ip_bin_src = self:raw(self.ip_offset + 12,4) -- raw 4-bytes string
|
||||
end
|
||||
-- set destination ip
|
||||
function Packet:ip_set_bin_dst(binip)
|
||||
nrip = u32(binip, 0)
|
||||
self:set_u32(self.ip_offset + 16, nrip)
|
||||
self.ip_bin_dst = self:raw(self.ip_offset + 16,4)
|
||||
end
|
||||
-- set ip options field (and move the data, count new length etc)
|
||||
function Packet:ip_set_options(ipoptions)
|
||||
-- packet = <ip header> + ipoptions + <payload>
|
||||
local buf = self.buf:sub(0+1,self.ip_offset + 20) .. ipoptions .. self.buf:sub(self.ip_data_offset+1)
|
||||
self.buf = buf
|
||||
-- set ip_len
|
||||
self:ip_set_len(self.buf:len())
|
||||
-- set ip_hl
|
||||
self:ip_set_hl(5 + ipoptions:len()/4)
|
||||
-- set data offset correctly
|
||||
self.ip_options = self:parse_options(self.ip_opt_offset, ((self.ip_hl*4)-20))
|
||||
self.ip_data_offset = self.ip_offset + self.ip_hl*4
|
||||
if self.tcp then
|
||||
self.tcp_offset = self.ip_data_offset
|
||||
elseif self.icmp then
|
||||
self.icmp_offset = self.ip_data_offset
|
||||
end
|
||||
end
|
||||
|
||||
-- return short information about ip header
|
||||
function Packet:ip_tostring()
|
||||
return string.format(
|
||||
"IP %s -> %s",
|
||||
self.ip_src,
|
||||
self.ip_dst)
|
||||
end
|
||||
|
||||
-- parse ip/tcp options to dict structure
|
||||
function Packet:parse_options(offset, length)
|
||||
local options = {}
|
||||
local op = 1
|
||||
local opt_ptr = 0
|
||||
while opt_ptr < length do
|
||||
local t, l, d
|
||||
options[op] = {}
|
||||
|
||||
t = self:u8(offset + opt_ptr)
|
||||
options[op].type = t
|
||||
if t==0 or t==1 then
|
||||
l = 1
|
||||
d = nil
|
||||
else
|
||||
l = self:u8(offset + opt_ptr + 1)
|
||||
if l > 2 then
|
||||
d = self:raw(offset + opt_ptr + 2, l-2)
|
||||
end
|
||||
end
|
||||
options[op].len = l
|
||||
options[op].data = d
|
||||
opt_ptr = opt_ptr + l
|
||||
op = op + 1
|
||||
end
|
||||
return options
|
||||
end
|
||||
|
||||
-- print short information about current packet
|
||||
function Packet:tostring()
|
||||
if self.tcp then
|
||||
return self:tcp_tostring()
|
||||
elseif self.icmp then
|
||||
return self:icmp_tostring()
|
||||
elseif self.ip then
|
||||
return self:ip_tostring()
|
||||
end
|
||||
return "<no tostring!>"
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
-- PARSE ICMP PACKET HEADER
|
||||
function Packet:icmp_parse(force_continue)
|
||||
self.icmp_offset = self.ip_data_offset
|
||||
if string.len(self.buf) < self.icmp_offset + 8 then -- let's say 8 bytes minimum
|
||||
return false
|
||||
end
|
||||
self.icmp = true
|
||||
self.icmp_type = self:u8(self.icmp_offset + 0)
|
||||
self.icmp_code = self:u8(self.icmp_offset + 1)
|
||||
self.icmp_sum = self:u16(self.icmp_offset + 2)
|
||||
|
||||
if self.icmp_type == 3 or self.icmp_type == 4 or self.icmp_type == 11 or self.icmp_type == 12 then
|
||||
self.icmp_payload = true
|
||||
self.icmp_r0 = self:u32(self.icmp_offset + 4)
|
||||
self.icmp_payload_offset = self.icmp_offset + 8
|
||||
if string.len(self.buf) < self.icmp_payload_offset + 24 then
|
||||
return false
|
||||
end
|
||||
self.icmp_payload = Packet:new(self.buf:sub(self.icmp_payload_offset+1), self.packet_len - self.icmp_payload_offset, true)
|
||||
end
|
||||
return true
|
||||
end
|
||||
-- return short information about icmp header
|
||||
function Packet:icmp_tostring()
|
||||
return self:ip_tostring() .. " ICMP(" .. self.icmp_payload:tostring() .. ")"
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
-- PARSE TCP HEADER FROM PACKET
|
||||
function Packet:tcp_parse(force_continue)
|
||||
self.tcp = true
|
||||
self.tcp_offset = self.ip_data_offset
|
||||
if string.len(self.buf) < self.tcp_offset + 4 then
|
||||
return false
|
||||
end
|
||||
self.tcp_sport = self:u16(self.tcp_offset + 0)
|
||||
self.tcp_dport = self:u16(self.tcp_offset + 2)
|
||||
if string.len(self.buf) < self.tcp_offset + 20 then
|
||||
if force_continue then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
self.tcp_seq = self:u32(self.tcp_offset + 4)
|
||||
self.tcp_ack = self:u32(self.tcp_offset + 8)
|
||||
self.tcp_hl = bit.rshift(bit.band(self:u8(self.tcp_offset+12), 0xF0), 4) -- header_length or data_offset
|
||||
self.tcp_x2 = bit.band(self:u8(self.tcp_offset+12), 0x0F)
|
||||
self.tcp_flags = self:u8(self.tcp_offset + 13)
|
||||
self.tcp_th_fin = bit.band(self.tcp_flags, 0x01)~=0 -- true/false
|
||||
self.tcp_th_syn = bit.band(self.tcp_flags, 0x02)~=0
|
||||
self.tcp_th_rst = bit.band(self.tcp_flags, 0x04)~=0
|
||||
self.tcp_th_push = bit.band(self.tcp_flags, 0x08)~=0
|
||||
self.tcp_th_ack = bit.band(self.tcp_flags, 0x10)~=0
|
||||
self.tcp_th_urg = bit.band(self.tcp_flags, 0x20)~=0
|
||||
self.tcp_th_ece = bit.band(self.tcp_flags, 0x40)~=0
|
||||
self.tcp_th_cwr = bit.band(self.tcp_flags, 0x80)~=0
|
||||
self.tcp_win = self:u16(self.tcp_offset + 14)
|
||||
self.tcp_sum = self:u16(self.tcp_offset + 16)
|
||||
self.tcp_urp = self:u16(self.tcp_offset + 18)
|
||||
self.tcp_opt_offset = self.tcp_offset + 20
|
||||
self.tcp_options = self:parse_options(self.tcp_opt_offset, ((self.tcp_hl*4)-20))
|
||||
self.tcp_data_offset = self.tcp_offset + self.tcp_hl*4
|
||||
self.tcp_data_length = self.ip_len - self.tcp_offset - self.tcp_hl*4
|
||||
self:tcp_parse_options()
|
||||
return true
|
||||
end
|
||||
|
||||
-- return short information about tcp packet
|
||||
function Packet:tcp_tostring()
|
||||
return string.format(
|
||||
"TCP %s:%i -> %s:%i",
|
||||
self.ip_src, self.tcp_sport,
|
||||
self.ip_dst, self.tcp_dport
|
||||
)
|
||||
end
|
||||
|
||||
-- parse options for tcp header
|
||||
function Packet:tcp_parse_options()
|
||||
local eoo = false
|
||||
for _,opt in ipairs(self.tcp_options) do
|
||||
if eoo then
|
||||
self.tcp_opt_after_eol = true
|
||||
end
|
||||
|
||||
if opt.type == 0 then -- end of options
|
||||
eoo = true
|
||||
elseif opt.type == 2 then -- MSS
|
||||
self.tcp_opt_mss = u16(opt.data, 0)
|
||||
self.tcp_opt_mtu = self.tcp_opt_mss + 40
|
||||
elseif opt.type == 3 then -- widow scaling
|
||||
self.tcp_opt_ws = u8(opt.data, 0)
|
||||
elseif opt.type == 8 then -- timestamp
|
||||
self.tcp_opt_t1 = u32(opt.data, 0)
|
||||
self.tcp_opt_t2 = u32(opt.data, 4)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Packet:tcp_set_sport(port)
|
||||
self:set_u16(self.tcp_offset + 0, port)
|
||||
end
|
||||
function Packet:tcp_set_dport(port)
|
||||
self:set_u16(self.tcp_offset + 2, port)
|
||||
end
|
||||
-- set tcp sequence field
|
||||
function Packet:tcp_set_seq(new_seq)
|
||||
self:set_u32(self.tcp_offset + 4, new_seq)
|
||||
end
|
||||
-- set tcp flags field (like syn, ack, rst)
|
||||
function Packet:tcp_set_flags(new_flags)
|
||||
self:set_u8(self.tcp_offset + 13, new_flags)
|
||||
end
|
||||
-- set urgent pointer field
|
||||
function Packet:tcp_set_urp(urg_ptr)
|
||||
self:set_u16(self.tcp_offset + 18, urg_ptr)
|
||||
end
|
||||
-- set tcp checksum field
|
||||
function Packet:tcp_set_checksum(checksum)
|
||||
self:set_u16(self.tcp_offset + 16, checksum)
|
||||
end
|
||||
-- count and save tcp checksum field
|
||||
function Packet:tcp_count_checksum()
|
||||
self:tcp_set_checksum(0)
|
||||
local proto = self.ip_p
|
||||
local length = self.buf:len() - self.tcp_offset
|
||||
local b = self.ip_bin_src ..
|
||||
self.ip_bin_dst ..
|
||||
string.char(0) ..
|
||||
string.char(proto) ..
|
||||
set_u16("..", 0, length) ..
|
||||
self.buf:sub(self.tcp_offset+1)
|
||||
|
||||
self:tcp_set_checksum(in_cksum(b))
|
||||
end
|
||||
|
||||
-- small database, mtu to link type string. Stolen from p0f.
|
||||
function Packet:tcp_lookup_link()
|
||||
local mtu_def = {
|
||||
{["mtu"]=256, ["txt"]= "radio modem"},
|
||||
{["mtu"]=386, ["txt"]= "ethernut"},
|
||||
{["mtu"]=552, ["txt"]= "SLIP line / encap ppp"},
|
||||
{["mtu"]=576, ["txt"]= "sometimes modem"},
|
||||
{["mtu"]=1280, ["txt"]= "gif tunnel"},
|
||||
{["mtu"]=1300, ["txt"]= "PIX, SMC, sometimes wireless"},
|
||||
{["mtu"]=1362, ["txt"]= "sometimes DSL (1)"},
|
||||
{["mtu"]=1372, ["txt"]= "cable modem"},
|
||||
{["mtu"]=1400, ["txt"]= "(Google/AOL)"},
|
||||
{["mtu"]=1415, ["txt"]= "sometimes wireless"},
|
||||
{["mtu"]=1420, ["txt"]= "GPRS, T1, FreeS/WAN"},
|
||||
{["mtu"]=1423, ["txt"]= "sometimes cable"},
|
||||
{["mtu"]=1440, ["txt"]= "sometimes DSL (2)"},
|
||||
{["mtu"]=1442, ["txt"]= "IPIP tunnel"},
|
||||
{["mtu"]=1450, ["txt"]= "vtun"},
|
||||
{["mtu"]=1452, ["txt"]= "sometimes DSL (3)"},
|
||||
{["mtu"]=1454, ["txt"]= "sometimes DSL (4)"},
|
||||
{["mtu"]=1456, ["txt"]= "ISDN ppp"},
|
||||
{["mtu"]=1458, ["txt"]= "BT DSL (?)"},
|
||||
{["mtu"]=1462, ["txt"]= "sometimes DSL (5)"},
|
||||
{["mtu"]=1470, ["txt"]= "(Google 2)"},
|
||||
{["mtu"]=1476, ["txt"]= "IPSec/GRE"},
|
||||
{["mtu"]=1480, ["txt"]= "IPv6/IPIP"},
|
||||
{["mtu"]=1492, ["txt"]= "pppoe (DSL)"},
|
||||
{["mtu"]=1496, ["txt"]= "vLAN"},
|
||||
{["mtu"]=1500, ["txt"]= "ethernet/modem"},
|
||||
{["mtu"]=1656, ["txt"]= "Ericsson HIS"},
|
||||
{["mtu"]=2024, ["txt"]= "wireless/IrDA"},
|
||||
{["mtu"]=2048, ["txt"]= "Cyclom X.25 WAN"},
|
||||
{["mtu"]=2250, ["txt"]= "AiroNet wireless"},
|
||||
{["mtu"]=3924, ["txt"]= "loopback"},
|
||||
{["mtu"]=4056, ["txt"]= "token ring (1)"},
|
||||
{["mtu"]=4096, ["txt"]= "Sangoma X.25 WAN"},
|
||||
{["mtu"]=4352, ["txt"]= "FDDI"},
|
||||
{["mtu"]=4500, ["txt"]= "token ring (2)"},
|
||||
{["mtu"]=9180, ["txt"]= "FORE ATM"},
|
||||
{["mtu"]=16384, ["txt"]= "sometimes loopback (1)"},
|
||||
{["mtu"]=16436, ["txt"]= "sometimes loopback (2)"},
|
||||
{["mtu"]=18000, ["txt"]= "token ring x4"},
|
||||
}
|
||||
if not self.tcp_opt_mss or self.tcp_opt_mss==0 then
|
||||
return "unspecified"
|
||||
end
|
||||
for _,x in ipairs(mtu_def) do
|
||||
local mtu = x["mtu"]
|
||||
local txt = x["txt"]
|
||||
if self.tcp_opt_mtu == mtu then
|
||||
return txt
|
||||
end
|
||||
if self.tcp_opt_mtu < mtu then
|
||||
return string.format("unknown-%i", self.tcp_opt_mtu)
|
||||
end
|
||||
end
|
||||
return string.format("unknown-%i", self.tcp_opt_mtu)
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- UTILS
|
||||
-- get binary string as hex string
|
||||
function bintohex(str)
|
||||
local b = ""
|
||||
if not str then -- nil
|
||||
return ""
|
||||
end
|
||||
for c in string.gmatch(str, ".") do
|
||||
b = string.format('%s%02x',b, string.byte(c))
|
||||
end
|
||||
return b
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Parse specifically printed hex string as binary
|
||||
-- Only bytes [a-f0-9A-F] from input are interpreted. The rest is ignored.
|
||||
-- Number of interpreted bytes _must_ be even. *The input is interpreted in pairs*.
|
||||
-- hextobin("20 20 20") -> " "
|
||||
-- hextobin("414243") -> "ABC"
|
||||
-- hextobin("\\41\\42\\43") -> "ABC"
|
||||
-- hextobin(" 41 42 43 ")-> "ABC"
|
||||
function hextobin(str)
|
||||
local ret = ""
|
||||
local a,b
|
||||
if not str then -- nil
|
||||
return ""
|
||||
end
|
||||
for c in string.gmatch(str, "[0-9a-fA-F][0-9a-fA-F]") do
|
||||
a = string.byte(c:sub(1,1))
|
||||
b = string.byte(c:sub(2,2))
|
||||
if a >= string.byte('a') then -- 97>a-f
|
||||
a = a - string.byte('a') + 10
|
||||
elseif a >= string.byte('A') then -- 65>A-F
|
||||
a = a - string.byte('A') + 10
|
||||
else -- 48> 0-9
|
||||
a = a - string.byte('0')
|
||||
end
|
||||
if b >= string.byte('a') then -- 97>a-f
|
||||
b = b - string.byte('a') + 10
|
||||
elseif b >= string.byte('A') then -- 65>A-F
|
||||
b = b - string.byte('A') + 10
|
||||
else -- 48> 0-9
|
||||
b = b - string.byte('0')
|
||||
end
|
||||
--io.write(string.format(">%s %i %i\n",c, a, b))
|
||||
ret = ret .. string.char(a*16 + b)
|
||||
end
|
||||
|
||||
--io.write(string.format(">%s|%s<\n",bintohex(ret), str))
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
81
nselib/shortport.lua
Normal file
81
nselib/shortport.lua
Normal file
@@ -0,0 +1,81 @@
|
||||
-- See nmaps COPYING for licence
|
||||
module(..., package.seeall)
|
||||
|
||||
portnumber = function(port, _proto, _state)
|
||||
local port_table, state_table
|
||||
local proto = _proto or "tcp"
|
||||
local state = _state or {"open"}
|
||||
|
||||
if(type(port) == "number") then
|
||||
port_table = {port}
|
||||
elseif(type(port) == "table") then
|
||||
port_table = port
|
||||
end
|
||||
|
||||
if(type(state) == "string") then
|
||||
state_table = {state}
|
||||
elseif(type(state) == "table") then
|
||||
state_table = state
|
||||
end
|
||||
|
||||
return function(host, port)
|
||||
for _, state in pairs(state_table) do
|
||||
if(port.protocol == proto and port.state == state) then
|
||||
for _, _port in ipairs(port_table) do
|
||||
if(port.number == _port) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
service = function(service, _proto, _state)
|
||||
local service_table;
|
||||
local state = _state or "open"
|
||||
local proto = _proto or "tcp"
|
||||
|
||||
if(type(service) == "string") then
|
||||
service_table = {service}
|
||||
elseif(type(service) == "table") then
|
||||
service_table = service
|
||||
end
|
||||
|
||||
return function(host, port)
|
||||
if(port.protocol == proto and port.state == state) then
|
||||
for _, service in ipairs(service_table) do
|
||||
if(port.service == service) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
port_or_service = function(port, _service, proto, _state)
|
||||
local state = _state or {"open"}
|
||||
local state_table
|
||||
|
||||
if(type(state) == "string") then
|
||||
state_table = {state}
|
||||
elseif(type(state) == "table") then
|
||||
state_table = state
|
||||
end
|
||||
|
||||
return function(host, port)
|
||||
for _, state in pairs(state_table) do
|
||||
local port_checker = portnumber(port, proto, state)
|
||||
local service_checker = service(_service, proto, state)
|
||||
if (port_checker(host, port) or service_checker(host, port)) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
106
nselib/stdnse.lua
Normal file
106
nselib/stdnse.lua
Normal file
@@ -0,0 +1,106 @@
|
||||
-- See nmaps COPYING for licence
|
||||
module(..., package.seeall)
|
||||
|
||||
print_debug = function(...)
|
||||
local verbosity = 1;
|
||||
if ((#arg > 1) and (tonumber(arg[1]))) then
|
||||
verbosity = table.remove(arg, 1);
|
||||
end
|
||||
|
||||
nmap.print_debug_unformatted(verbosity, string.format(unpack(arg, start)));
|
||||
end
|
||||
|
||||
-- Concat the contents of the parameter list,
|
||||
-- separated by the string delimiter (just like in perl)
|
||||
-- example: strjoin(", ", {"Anna", "Bob", "Charlie", "Dolores"})
|
||||
function strjoin(delimiter, list)
|
||||
return table.concat(list, delimiter);
|
||||
end
|
||||
|
||||
-- Split text into a list consisting of the strings in text,
|
||||
-- separated by strings matching delimiter (which may be a pattern).
|
||||
-- example: strsplit(",%s*", "Anna, Bob, Charlie,Dolores")
|
||||
function strsplit(delimiter, text)
|
||||
local list = {}
|
||||
local pos = 1
|
||||
|
||||
if string.find("", delimiter, 1) then -- this would result in endless loops
|
||||
error("delimiter matches empty string!")
|
||||
end
|
||||
|
||||
while 1 do
|
||||
local first, last = string.find(text, delimiter, pos)
|
||||
if first then -- found?
|
||||
table.insert(list, string.sub(text, pos, first-1))
|
||||
pos = last+1
|
||||
else
|
||||
table.insert(list, string.sub(text, pos))
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return list
|
||||
end
|
||||
|
||||
|
||||
-- Generic buffer implementation using lexical closures
|
||||
--
|
||||
-- Pass make_buffer a socket and a separator lua pattern [1].
|
||||
--
|
||||
-- Returns a function bound to your provided socket with behaviour identical
|
||||
-- to receive_lines() except it will return AT LEAST ONE [2] and AT MOST ONE
|
||||
-- "line" at a time.
|
||||
--
|
||||
-- [1] Use the pattern "\r?\n" for regular newlines
|
||||
-- [2] Except where there is trailing "left over" data not terminated by a
|
||||
-- pattern (in which case you get the data anyways)
|
||||
-- [3] The data is returned WITHOUT the pattern/newline on the end.
|
||||
-- [4] Empty "lines" are returned as "". With the pattern in [1] you will
|
||||
-- receive a "" for each newline in the stream.
|
||||
-- [5] Errors/EOFs are delayed until all "lines" have been processed.
|
||||
--
|
||||
-- -Doug, June, 2007
|
||||
|
||||
make_buffer = function(sd, sep)
|
||||
local self, result
|
||||
local buf = ""
|
||||
|
||||
self = function()
|
||||
local i, j, status, value
|
||||
|
||||
i, j = string.find(buf, sep)
|
||||
|
||||
if i then
|
||||
if i == 1 then -- empty line
|
||||
buf = string.sub(buf, j+1, -1)
|
||||
--return self() -- skip empty, tail
|
||||
return true, "" -- return empty
|
||||
else
|
||||
value = string.sub(buf, 1, i-1)
|
||||
buf = string.sub(buf, j+1, -1)
|
||||
return true, value
|
||||
end
|
||||
end
|
||||
|
||||
if result then
|
||||
if string.len(buf) > 0 then -- left over data with no terminating pattern
|
||||
value = buf
|
||||
buf = ""
|
||||
return true, value
|
||||
end
|
||||
return nil, result
|
||||
end
|
||||
|
||||
status, value = sd:receive()
|
||||
|
||||
if status then
|
||||
buf = buf .. value
|
||||
else
|
||||
result = value
|
||||
end
|
||||
|
||||
return self() -- tail
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
84
nselib/strbuf.lua
Normal file
84
nselib/strbuf.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
-- license = "See nmaps COPYING for license"
|
||||
module("strbuf" ,package.seeall)
|
||||
|
||||
-- String buffer functions. Concatenation is not efficient in
|
||||
-- lua as strings are immutable. If a large amount of '..'
|
||||
-- operations are needed a string buffer should be used instead
|
||||
|
||||
--[[
|
||||
local buf = strbuf.new()
|
||||
-- from here buf may be used like a string for concatenation operations
|
||||
-- (the lefthand-operand has to be a strbuf, the righthand-operand may be
|
||||
-- a string or a strbuf)
|
||||
-- alternativly you can assign a value (which will become the first string
|
||||
-- inside the buffer) with new
|
||||
local buf2 = strbuf.new('hello')
|
||||
buf = buf .. 'string'
|
||||
buf = buf .. 'data'
|
||||
print(buf) -- default seperator is a new line
|
||||
print(strbuf.dump(buf)) -- no seperator
|
||||
print(strbuf.dump(buf, ' ')) -- seperated by spaces
|
||||
strbuf.clear(buf)
|
||||
--]]
|
||||
|
||||
|
||||
|
||||
dump = table.concat
|
||||
|
||||
concatbuf =function(sbuf, s)
|
||||
if sbuf == s then
|
||||
error("refusing to concat the same buffer (recursion)!")
|
||||
end
|
||||
if getmetatable(sbuf) ~= mt then
|
||||
error("left-hand operand of the concat operation has to be a strbuf!")
|
||||
end
|
||||
if type(s)=="string" then
|
||||
table.insert(sbuf, s)
|
||||
elseif getmetatable(s) == mt then
|
||||
for _,v in ipairs(s) do
|
||||
table.insert(sbuf, v)
|
||||
end
|
||||
else
|
||||
error("right-hand operand of concat has to be either string or strbuf!")
|
||||
end
|
||||
return sbuf
|
||||
end
|
||||
|
||||
local eqbuf = function(sbuf1, sbuf2)
|
||||
if getmetatable(sbuf1) ~= mt then
|
||||
error("equal function expects a value of type strbuf as left-hand operand")
|
||||
end
|
||||
if getmetatable(sbuf1) ~= getmetatable(sbuf2) then
|
||||
return false
|
||||
end
|
||||
|
||||
if #sbuf1 ~= #sbuf2 then
|
||||
return false
|
||||
end
|
||||
|
||||
for i=1, #sbuf1 do
|
||||
if sbuf1[i] ~= sbuf2[i] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
clear = function(sbuf)
|
||||
for i, v in pairs(sbuf) do
|
||||
sbuf[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
mt = { __concat = concatbuf, __tostring = function(s) return dump(s, '\n') end , __eq=eqbuf}
|
||||
|
||||
new = function(val)
|
||||
local tmp ={}
|
||||
setmetatable(tmp, mt)
|
||||
if val ~=nil then
|
||||
table.insert(tmp, val)
|
||||
end
|
||||
return tmp
|
||||
end
|
||||
|
||||
|
||||
|
||||
356
nselib/url.lua
Normal file
356
nselib/url.lua
Normal file
@@ -0,0 +1,356 @@
|
||||
--[[
|
||||
|
||||
URI parsing, composition and relative URL resolution
|
||||
LuaSocket toolkit.
|
||||
Author: Diego Nehab
|
||||
RCS ID: $Id: url.lua,v 1.37 2005/11/22 08:33:29 diego Exp $
|
||||
|
||||
parse_query() and build_query() added For nmap (Eddie Bell <ejlbell@gmail.com>)
|
||||
|
||||
--]]
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Declare module
|
||||
-----------------------------------------------------------------------------
|
||||
local string = require("string")
|
||||
local base = _G
|
||||
local table = require("table")
|
||||
module(...,package.seeall)
|
||||
|
||||
_VERSION = "URL 1.0"
|
||||
|
||||
--[[ Internal functions --]]
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Protects a path segment, to prevent it from interfering with the
|
||||
-- url parsing.
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
-----------------------------------------------------------------------------
|
||||
local function make_set(t)
|
||||
local s = {}
|
||||
for i,v in base.ipairs(t) do
|
||||
s[t[i]] = 1
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
-- these are allowed withing a path segment, along with alphanum
|
||||
-- other characters must be escaped
|
||||
local segment_set = make_set {
|
||||
"-", "_", ".", "!", "~", "*", "'", "(",
|
||||
")", ":", "@", "&", "=", "+", "$", ",",
|
||||
}
|
||||
|
||||
local function protect_segment(s)
|
||||
return string.gsub(s, "([^A-Za-z0-9_])", function (c)
|
||||
if segment_set[c] then return c
|
||||
else return string.format("%%%02x", string.byte(c)) end
|
||||
end)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a path from a base path and a relative path
|
||||
-- Input
|
||||
-- base_path
|
||||
-- relative_path
|
||||
-- Returns
|
||||
-- corresponding absolute path
|
||||
-----------------------------------------------------------------------------
|
||||
local function absolute_path(base_path, relative_path)
|
||||
if string.sub(relative_path, 1, 1) == "/" then return relative_path end
|
||||
local path = string.gsub(base_path, "[^/]*$", "")
|
||||
path = path .. relative_path
|
||||
path = string.gsub(path, "([^/]*%./)", function (s)
|
||||
if s ~= "./" then return s else return "" end
|
||||
end)
|
||||
path = string.gsub(path, "/%.$", "/")
|
||||
local reduced
|
||||
while reduced ~= path do
|
||||
reduced = path
|
||||
path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
|
||||
if s ~= "../../" then return "" else return s end
|
||||
end)
|
||||
end
|
||||
path = string.gsub(reduced, "([^/]*/%.%.)$", function (s)
|
||||
if s ~= "../.." then return "" else return s end
|
||||
end)
|
||||
return path
|
||||
end
|
||||
|
||||
|
||||
--[[ External functions --]]
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Encodes a string into its escaped hexadecimal representation
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
-----------------------------------------------------------------------------
|
||||
function escape(s)
|
||||
return string.gsub(s, "([^A-Za-z0-9_])", function(c)
|
||||
return string.format("%%%02x", string.byte(c))
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Encodes a string into its escaped hexadecimal representation
|
||||
-- Input
|
||||
-- s: binary string to be encoded
|
||||
-- Returns
|
||||
-- escaped representation of string binary
|
||||
-----------------------------------------------------------------------------
|
||||
function unescape(s)
|
||||
return string.gsub(s, "%%(%x%x)", function(hex)
|
||||
return string.char(base.tonumber(hex, 16))
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Parses a url and returns a table with all its parts according to RFC 2396
|
||||
-- The following grammar describes the names given to the URL parts
|
||||
-- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment>
|
||||
-- <authority> ::= <userinfo>@<host>:<port>
|
||||
-- <userinfo> ::= <user>[:<password>]
|
||||
-- <path> :: = {<segment>/}<segment>
|
||||
-- Input
|
||||
-- url: uniform resource locator of request
|
||||
-- default: table with default values for each field
|
||||
-- Returns
|
||||
-- table with the following fields, where RFC naming conventions have
|
||||
-- been preserved:
|
||||
-- scheme, authority, userinfo, user, password, host, port,
|
||||
-- path, params, query, fragment
|
||||
-- Obs:
|
||||
-- the leading '/' in {/<path>} is considered part of <path>
|
||||
-----------------------------------------------------------------------------
|
||||
function parse(url, default)
|
||||
-- initialize default parameters
|
||||
local parsed = {}
|
||||
for i,v in base.pairs(default or parsed) do parsed[i] = v end
|
||||
-- empty url is parsed to nil
|
||||
if not url or url == "" then return nil, "invalid url" end
|
||||
-- remove whitespace
|
||||
-- url = string.gsub(url, "%s", "")
|
||||
-- get fragment
|
||||
url = string.gsub(url, "#(.*)$", function(f)
|
||||
parsed.fragment = f
|
||||
return ""
|
||||
end)
|
||||
-- get scheme
|
||||
url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
|
||||
function(s) parsed.scheme = s; return "" end)
|
||||
-- get authority
|
||||
url = string.gsub(url, "^//([^/]*)", function(n)
|
||||
parsed.authority = n
|
||||
return ""
|
||||
end)
|
||||
-- get query stringing
|
||||
url = string.gsub(url, "%?(.*)", function(q)
|
||||
parsed.query = q
|
||||
return ""
|
||||
end)
|
||||
-- get params
|
||||
url = string.gsub(url, "%;(.*)", function(p)
|
||||
parsed.params = p
|
||||
return ""
|
||||
end)
|
||||
-- path is whatever was left
|
||||
if url ~= "" then parsed.path = url end
|
||||
local authority = parsed.authority
|
||||
if not authority then return parsed end
|
||||
authority = string.gsub(authority,"^([^@]*)@",
|
||||
function(u) parsed.userinfo = u; return "" end)
|
||||
authority = string.gsub(authority, ":([^:]*)$",
|
||||
function(p) parsed.port = p; return "" end)
|
||||
if authority ~= "" then parsed.host = authority end
|
||||
local userinfo = parsed.userinfo
|
||||
if not userinfo then return parsed end
|
||||
userinfo = string.gsub(userinfo, ":([^:]*)$",
|
||||
function(p) parsed.password = p; return "" end)
|
||||
parsed.user = userinfo
|
||||
return parsed
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Rebuilds a parsed URL from its components.
|
||||
-- Components are protected if any reserved or unallowed characters are found
|
||||
-- Input
|
||||
-- parsed: parsed URL, as returned by parse
|
||||
-- Returns
|
||||
-- a stringing with the corresponding URL
|
||||
-----------------------------------------------------------------------------
|
||||
function build(parsed)
|
||||
local ppath = parse_path(parsed.path or "")
|
||||
local url = build_path(ppath)
|
||||
if parsed.params then url = url .. ";" .. parsed.params end
|
||||
if parsed.query then url = url .. "?" .. parsed.query end
|
||||
local authority = parsed.authority
|
||||
if parsed.host then
|
||||
authority = parsed.host
|
||||
if parsed.port then authority = authority .. ":" .. parsed.port end
|
||||
local userinfo = parsed.userinfo
|
||||
if parsed.user then
|
||||
userinfo = parsed.user
|
||||
if parsed.password then
|
||||
userinfo = userinfo .. ":" .. parsed.password
|
||||
end
|
||||
end
|
||||
if userinfo then authority = userinfo .. "@" .. authority end
|
||||
end
|
||||
if authority then url = "//" .. authority .. url end
|
||||
if parsed.scheme then url = parsed.scheme .. ":" .. url end
|
||||
if parsed.fragment then url = url .. "#" .. parsed.fragment end
|
||||
-- url = string.gsub(url, "%s", "")
|
||||
return url
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a absolute URL from a base and a relative URL according to RFC 2396
|
||||
-- Input
|
||||
-- base_url
|
||||
-- relative_url
|
||||
-- Returns
|
||||
-- corresponding absolute url
|
||||
-----------------------------------------------------------------------------
|
||||
function absolute(base_url, relative_url)
|
||||
if type(base_url) == "table" then
|
||||
base_parsed = base_url
|
||||
base_url = build(base_parsed)
|
||||
else
|
||||
base_parsed = parse(base_url)
|
||||
end
|
||||
local relative_parsed = parse(relative_url)
|
||||
if not base_parsed then return relative_url
|
||||
elseif not relative_parsed then return base_url
|
||||
elseif relative_parsed.scheme then return relative_url
|
||||
else
|
||||
relative_parsed.scheme = base_parsed.scheme
|
||||
if not relative_parsed.authority then
|
||||
relative_parsed.authority = base_parsed.authority
|
||||
if not relative_parsed.path then
|
||||
relative_parsed.path = base_parsed.path
|
||||
if not relative_parsed.params then
|
||||
relative_parsed.params = base_parsed.params
|
||||
if not relative_parsed.query then
|
||||
relative_parsed.query = base_parsed.query
|
||||
end
|
||||
end
|
||||
else
|
||||
relative_parsed.path = absolute_path(base_parsed.path or "",
|
||||
relative_parsed.path)
|
||||
end
|
||||
end
|
||||
return build(relative_parsed)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Breaks a path into its segments, unescaping the segments
|
||||
-- Input
|
||||
-- path
|
||||
-- Returns
|
||||
-- segment: a table with one entry per segment
|
||||
-----------------------------------------------------------------------------
|
||||
function parse_path(path)
|
||||
local parsed = {}
|
||||
path = path or ""
|
||||
--path = string.gsub(path, "%s", "")
|
||||
string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
|
||||
for i = 1, table.getn(parsed) do
|
||||
parsed[i] = unescape(parsed[i])
|
||||
end
|
||||
if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
|
||||
if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
|
||||
return parsed
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a path component from its segments, escaping protected characters.
|
||||
-- Input
|
||||
-- parsed: path segments
|
||||
-- unsafe: if true, segments are not protected before path is built
|
||||
-- Returns
|
||||
-- path: corresponding path stringing
|
||||
-----------------------------------------------------------------------------
|
||||
function build_path(parsed, unsafe)
|
||||
local path = ""
|
||||
local n = table.getn(parsed)
|
||||
if unsafe then
|
||||
for i = 1, n-1 do
|
||||
path = path .. parsed[i]
|
||||
path = path .. "/"
|
||||
end
|
||||
if n > 0 then
|
||||
path = path .. parsed[n]
|
||||
if parsed.is_directory then path = path .. "/" end
|
||||
end
|
||||
else
|
||||
for i = 1, n-1 do
|
||||
path = path .. protect_segment(parsed[i])
|
||||
path = path .. "/"
|
||||
end
|
||||
if n > 0 then
|
||||
path = path .. protect_segment(parsed[n])
|
||||
if parsed.is_directory then path = path .. "/" end
|
||||
end
|
||||
end
|
||||
if parsed.is_absolute then path = "/" .. path end
|
||||
return path
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Breaks a query string into name/value pairs
|
||||
-- Input
|
||||
-- query string (name=value&name=value ...)
|
||||
-- Returns
|
||||
-- table where name=value is table['name'] = value
|
||||
-----------------------------------------------------------------------------
|
||||
function parse_query(query)
|
||||
local parsed = {}
|
||||
local pos = 0
|
||||
|
||||
query = string.gsub(query, "&", "&")
|
||||
query = string.gsub(query, "<", "<")
|
||||
query = string.gsub(query, ">", ">")
|
||||
|
||||
function ginsert(qstr)
|
||||
local first, last = string.find(qstr, "=")
|
||||
if first then
|
||||
parsed[string.sub(qstr, 0, first-1)] = string.sub(qstr, first+1)
|
||||
end
|
||||
end
|
||||
|
||||
while true do
|
||||
local first, last = string.find(query, "&", pos)
|
||||
if first then
|
||||
ginsert(string.sub(query, pos, first-1));
|
||||
pos = last+1
|
||||
else
|
||||
ginsert(string.sub(query, pos));
|
||||
break;
|
||||
end
|
||||
end
|
||||
return parsed
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Builds a query string from dictionary based table
|
||||
-- Input
|
||||
-- dictionary table where table['name'] = value
|
||||
-- Returns
|
||||
-- query string (name=value&name=value ...)
|
||||
-----------------------------------------------------------------------------
|
||||
function build_query(query)
|
||||
local qstr = ""
|
||||
|
||||
for i,v in pairs(query) do
|
||||
qstr = qstr .. i .. '=' .. v .. '&'
|
||||
end
|
||||
return string.sub(qstr, 0, string.len(qstr)-1)
|
||||
end
|
||||
Reference in New Issue
Block a user