diff -Nraup nmap-4.22SOC4/nmap_dns.cc nmap-4.22SOC4-patched/nmap_dns.cc --- nmap-4.22SOC4/nmap_dns.cc 2007-08-14 08:46:54.000000000 +0200 +++ nmap-4.22SOC4-patched/nmap_dns.cc 2007-08-18 05:13:27.023300579 +0200 @@ -858,7 +858,7 @@ static void connect_dns_servers() { s->capacity = CAPACITY_MIN; s->write_busy = 0; - nsock_connect_udp(dnspool, s->nsd, connect_evt_handler, NULL, (struct sockaddr *) &s->addr, sizeof(struct sockaddr), 53); + nsock_connect_udp(dnspool, s->nsd, connect_evt_handler, NULL, (struct sockaddr *) &s->addr, sizeof(struct sockaddr), 53, 0); nsock_read(dnspool, s->nsd, read_evt_handler, -1, NULL); s->connected = 1; } diff -Nraup nmap-4.22SOC4/nselib/packet.lua nmap-4.22SOC4-patched/nselib/packet.lua --- nmap-4.22SOC4/nselib/packet.lua 1970-01-01 01:00:00.000000000 +0100 +++ nmap-4.22SOC4-patched/nselib/packet.lua 2007-08-18 05:13:27.027300806 +0200 @@ -0,0 +1,536 @@ +-- license = "See nmaps COPYING for license" +module("packet" ,package.seeall) + +-- Raw package parsing functions. Used with raw sockets +-- in nse. +-- Author: Marek Majkowski + +--[[ +--]] + + +require "bit" + + +---------------------------------------------------------------------------------------------------------------- +-- extract number from 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 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) -- string.byte(c:sub(1,1)) + string.byte(c:sub(2,2))*256 -- u16(c, 0) + end + if x == 1 then + + end + + -- sum = bit.band(sum, 0xffffffff) + 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 + + +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 +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 +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 +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 + +-- Body +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 +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 +function Packet:ip_set_len(len) + self:set_u16(self.ip_offset + 2, len) +end +function Packet:ip_set_ttl(ttl) + self:set_u8(self.ip_offset + 8, ttl) +end +function Packet:ip_set_checksum(checksum) + self:set_u16(self.ip_offset + 10, checksum) +end +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 +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 +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 +function Packet:ip_set_options(ipoptions) + -- packet = + ipoptions + + 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 + + +function Packet:ip_tostring() + return string.format( + "IP %s -> %s", + self.ip_src, + self.ip_dst) +end + +function Packet:parse_options(offset, length) -- parse ip/tcp options to dict structure + 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 + + +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 "" +end + +---------------------------------------------------------------------------------------------------------------- +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 +function Packet:icmp_tostring() + return self:ip_tostring() .. " ICMP(" .. self.icmp_payload:tostring() .. ")" +end + +---------------------------------------------------------------------------------------------------------------- +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 + +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_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 + +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 +function Packet:tcp_set_seq(new_seq) + self:set_u32(self.tcp_offset + 4, new_seq) +end +function Packet:tcp_set_flags(new_flags) + self:set_u8(self.tcp_offset + 13, new_flags) +end +function Packet:tcp_set_urp(urg_ptr) + self:set_u16(self.tcp_offset + 18, urg_ptr) +end + +function Packet:tcp_set_checksum(checksum) + self:set_u16(self.tcp_offset + 16, checksum) +end + +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 + + +-- io.write(string.format("XXSUM 0x%04x\n", in_cksum("abcde"))) + +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 +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 + + +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 + + diff -Nraup nmap-4.22SOC4/nse_nsock.cc nmap-4.22SOC4-patched/nse_nsock.cc --- nmap-4.22SOC4/nse_nsock.cc 2007-08-16 12:51:27.000000000 +0200 +++ nmap-4.22SOC4-patched/nse_nsock.cc 2007-08-18 05:13:27.023300579 +0200 @@ -16,6 +16,7 @@ #include "utils.h" #include "tcpip.h" +#include "Target.h" #if HAVE_OPENSSL #include @@ -34,6 +35,9 @@ #define DEFAULT_TIMEOUT 30000 + +/* current_hosts from nse_main, indexed by target ip (as string)*/ +extern std::map current_hosts; extern NmapOps o; // defined in nse_main.cc but also declared here @@ -54,6 +58,7 @@ static int l_nsock_receive_buf(lua_State static int l_nsock_ncap_open(lua_State* l); static int l_nsock_ncap_close(lua_State* l); static int l_nsock_ncap_register(lua_State *l); +static int l_nsock_ncap_unregister(lua_State *l); static int l_nsock_pcap_receive(lua_State* l); @@ -84,6 +89,7 @@ static luaL_reg l_nsock [] = { {"pcap_open", l_nsock_ncap_open}, {"pcap_close", l_nsock_ncap_close}, {"pcap_register", l_nsock_ncap_register}, + {"pcap_unregister", l_nsock_ncap_unregister}, {"pcap_receive", l_nsock_pcap_receive}, // {"callback_test", l_nsock_pcap_callback_test}, {NULL, NULL} @@ -211,7 +217,8 @@ static int l_nsock_connect(lua_State* l) const char* addr = luaL_checkstring(l, 2); unsigned short port = (unsigned short) luaL_checkint(l, 3); const char *how = luaL_optstring(l, 4, "tcp"); - + unsigned short localport = (unsigned short) luaL_optint(l, 5, 0); + const char* error; struct addrinfo *dest; int error_id; @@ -232,19 +239,19 @@ static int l_nsock_connect(lua_State* l) case 't': if (strcmp(how, "tcp")) goto error; nsock_connect_tcp(nsp, udata->nsiod, l_nsock_connect_handler, - udata->timeout, l, dest->ai_addr, dest->ai_addrlen, port); + udata->timeout, l, dest->ai_addr, dest->ai_addrlen, port, localport); break; case 'u': if (strcmp(how, "udp")) goto error; nsock_connect_udp(nsp, udata->nsiod, l_nsock_connect_handler, - l, dest->ai_addr, dest->ai_addrlen, port); + l, dest->ai_addr, dest->ai_addrlen, port, localport); break; case 's': if (strcmp(how, "ssl")) goto error; #ifdef HAVE_OPENSSL nsock_connect_ssl(nsp, udata->nsiod, l_nsock_connect_handler, udata->timeout, l, dest->ai_addr, dest->ai_addrlen, port, - udata->ssl_session); + udata->ssl_session, localport); break; #else luaL_argerror(l, 4, "Sorry, you don't have openssl."); @@ -497,6 +504,11 @@ static int l_nsock_gc(lua_State* l){ static int l_nsock_close(lua_State* l) { l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1); + + /* Never ever collect nse-pcap connections. */ + if(udata->ncap_socket){ + return 0; + } l_nsock_clear_buf(l, udata); @@ -952,6 +964,45 @@ static int l_nsock_ncap_register(lua_Sta return 0; } +static int l_nsock_ncap_unregister(lua_State *l){ + l_nsock_udata* udata = (l_nsock_udata*) auxiliar_checkclass(l, "nsock", 1); + + if(!udata->nsiod || !udata->ncap_socket) { + luaL_argerror(l, 1, "You can't unregister to nsock-pcap if it wasn't opened."); + return 0; + } + if(!udata->ncap_request){ + luaL_argerror(l, 1, "You are not registered to this socket."); + return 0; + } + struct ncap_request *nr = udata->ncap_request; + udata->ncap_request = NULL; + + assert(!nr->suspended); + + + /* results not received? */ + if(!nr->received){ + ncap_request_map_del(nr); + nsock_event_cancel(nsp, nr->nseid, 0); + nr->nseid = 0; + }else{ + if(nr->r_status) free(nr->r_status); + if(nr->r_layer2) free(nr->r_layer2); + } + + nr->l = NULL; + nr->ncap_cback_ref = 0; /* this ref is freed in different place (on udata->ncap_cback_ref) */ + if(nr->key) free(nr->key); + /* dont' free r_layer3, it's in the same block as r_layer2*/ + + free(nr); + + + /* that's it. return to lua */ + return 0; +} + /* (LUA) After "register" use this function to block, and wait for packet. * If packet is already captured, this function will return immidietly. * @@ -999,7 +1050,7 @@ char* ncap_request_do_callback(nsock_eve /* get string from top of the stack*/ size_t testdatasz; const char* testdata = lua_tolstring(l, -1, &testdatasz); - // lua_pop(l, 1);/* just in case [nope, it's not needed]*/ + lua_pop(l, 1); /* must exist. if not stack _can_ be shifted (while doing two pcap_registers on two different pcaps in the same time)*/ char *key = strdup(hex((char*)testdata, testdatasz)); return key; @@ -1162,11 +1213,13 @@ int ncap_restore_lua(ncap_request *nr){ static int l_dnet_open_ethernet(lua_State* l); static int l_dnet_close_ethernet(lua_State* l); static int l_dnet_send_ethernet(lua_State* l); +static int l_dnet_send_ip(lua_State* l); static luaL_reg l_dnet [] = { {"ethernet_open", l_dnet_open_ethernet}, {"ethernet_close", l_dnet_close_ethernet}, {"ethernet_send", l_dnet_send_ethernet}, + {"ip_send", l_dnet_send_ip}, {NULL, NULL} }; @@ -1239,6 +1292,8 @@ eth_t *ldnet_eth_open_cached(const char dem->references++; return dem->eth; } + if(o.scriptTrace()) + log_write(LOG_STDOUT, "SCRIPT ENGINE: dnet:open_ethernet(%s)\n", device); dem = (dnet_eth_map *)safe_zalloc(sizeof(dnet_eth_map)); dem->eth = eth_open(device); @@ -1259,6 +1314,8 @@ void ldnet_eth_close_cached(const char * dnet_eth_cache.erase(key); eth_close(dem->eth); free(dem); + if(o.scriptTrace()) + log_write(LOG_STDOUT, "SCRIPT ENGINE: dnet:close_ethernet(%s)\n", device); } return; } @@ -1301,7 +1358,68 @@ static int l_dnet_send_ethernet(lua_Stat luaL_argerror(l, 1, "dnet is not valid opened ethernet interface"); return 0; } - eth_send(udata->eth, packet, packetsz); + if(o.scriptTrace()) + log_write(LOG_STDOUT, "SCRIPT ENGINE: send_ethernet %s\n", nse_hexify((const void*)packet, packetsz)); + int ret = eth_send(udata->eth, packet, packetsz); + lua_pushnumber(l, ret); + return 1; +} + +static int l_dnet_send_ip(lua_State* l){ + size_t packetsz = 0; + const char* packet = luaL_checklstring(l, 1, &packetsz); + + static int raw_socket; + if(!raw_socket){ + if(o.scriptTrace()) + log_write(LOG_STDOUT, "SCRIPT ENGINE: dnet:ip_open()\n"); + /* Init our raw socket */ + if ((raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 ){ + luaL_argerror(l, 1, "Can't open libdnet:ip_open() raw socket! (are you root?)"); + return 0; + //pfatal("socket troubles in %s", __func__); + } + unblock_socket(raw_socket); + broadcast_socket(raw_socket); + #ifndef WIN32 + sethdrinclude(raw_socket); + #endif + } + if(o.scriptTrace()) + log_write(LOG_STDOUT, "SCRIPT ENGINE: send_ip %s\n", nse_hexify((const void*)packet, packetsz)); + + if(packetsz < 20){ + luaL_argerror(l, 1, "ip packet is too small (less than 20 bytes)"); + return 0; + } + if((packet[0] & 0xF0) >> 4 != 4){ + luaL_argerror(l, 1, "ip verion is not 4?"); + return 0; + } + + char buf[20]; + Snprintf(buf, sizeof(buf), "%u.%u.%u.%u", (unsigned char)packet[16],(unsigned char)packet[17], + (unsigned char)packet[18],(unsigned char)packet[19]); + + std::string key = buf; + Target *target = current_hosts[key]; + if(!target){ + luaL_argerror(l, 1, "target not found in map"); + return 0; + } + + if ((o.sendpref & PACKET_SEND_ETH) && target->ifType() == devt_ethernet) { + + struct eth_nfo eth; + memcpy(eth.srcmac, target->SrcMACAddress(), 6); + memcpy(eth.dstmac, target->NextHopMACAddress(), 6); + //strncpy(eth.devname, target->deviceName(), 16); + eth.devname[0]='\0'; + eth.ethsd = eth_open_cached(target->deviceName()); + + send_ip_packet(raw_socket, ð, (u8*)packet, packetsz); + }else + send_ip_packet(raw_socket, NULL, (u8*)packet, packetsz); return 0; } diff -Nraup nmap-4.22SOC4/nsock/include/nsock.h nmap-4.22SOC4-patched/nsock/include/nsock.h --- nmap-4.22SOC4/nsock/include/nsock.h 2007-08-11 08:28:53.000000000 +0200 +++ nmap-4.22SOC4-patched/nsock/include/nsock.h 2007-08-18 05:13:27.027300806 +0200 @@ -377,7 +377,8 @@ typedef void (*nsock_ev_handler)(nsock_p nsock_event_id nsock_connect_tcp(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handler handler, int timeout_msecs, void *userdata, struct sockaddr *ss, - size_t sslen, unsigned short port); + size_t sslen, unsigned short port, + unsigned short localport); /* Request a UDP "connection" to another system (by IP address). The in_addr is normal network byte order, but the port number should be @@ -398,7 +399,8 @@ nsock_event_id nsock_connect_tcp(nsock_p nsock_event_id nsock_connect_udp(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handler handler, void *userdata, struct sockaddr *ss, size_t sslen, - unsigned short port); + unsigned short port, + unsigned short localport); /* Request an SSL over TCP connection to another system (by IP address). The in_addr is normal network byte order, but the port @@ -413,7 +415,8 @@ nsock_event_id nsock_connect_ssl(nsock_p nsock_ev_handler handler, int timeout_msecs, void *userdata, struct sockaddr *ss, size_t sslen, unsigned short port, - nsock_ssl_session ssl_session); + nsock_ssl_session ssl_session, + unsigned short localport); /* Request ssl connection over already established TCP connection. nsiod must be socket that is already connected to target diff -Nraup nmap-4.22SOC4/nsock/src/Makefile.in nmap-4.22SOC4-patched/nsock/src/Makefile.in --- nmap-4.22SOC4/nsock/src/Makefile.in 2007-08-11 08:28:53.000000000 +0200 +++ nmap-4.22SOC4-patched/nsock/src/Makefile.in 2007-08-18 05:13:27.027300806 +0200 @@ -1,4 +1,4 @@ -NSOCK_VERSION = 0.02 +NSOCK_VERSION = 0.03 prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ diff -Nraup nmap-4.22SOC4/nsock/src/nsock_connect.c nmap-4.22SOC4-patched/nsock/src/nsock_connect.c --- nmap-4.22SOC4/nsock/src/nsock_connect.c 2007-01-01 01:23:39.000000000 +0100 +++ nmap-4.22SOC4-patched/nsock/src/nsock_connect.c 2007-08-18 05:13:27.027300806 +0200 @@ -69,13 +69,15 @@ extern struct timeval nsock_tod; * shared by nsock_connect_tcp and nsock_connect_ssl */ static void nsock_connect_internal(mspool *ms, msevent *nse, int proto, struct sockaddr_storage *ss, size_t sslen, - unsigned short port) + unsigned short port, unsigned short localport) { - int res; + int res, x; struct sockaddr_in *sin = (struct sockaddr_in *) ss; + struct sockaddr_in sin4local; #if HAVE_IPV6 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss; + struct sockaddr_in6 sin6local; #endif /* Now it is time to actually attempt the connection */ @@ -98,11 +100,57 @@ static void nsock_connect_internal(mspoo #endif } + /* specified local port */ + if(localport){ + x = 1; + if (setsockopt(nse->iod->sd, SOL_SOCKET, SO_REUSEADDR, (const char*)&x, sizeof (x)) == -1) + perror("setsockopt(SO_REUSEADDR)"); /* not critical */ +#ifdef SO_REUSEPORT /* doesnt exist on all systems... */ + if (setsockopt(nse->iod->sd, SOL_SOCKET, SO_REUSEPORT, (const char*)&x, sizeof (x)) == -1) + perror("setsockopt(SO_REUSEPORT)"); /* not critical */ +#endif + + if (sin->sin_family == AF_INET) { + memset(&sin4local, 0, sizeof(sin4local)); + sin4local.sin_family = sin->sin_family; + sin4local.sin_addr.s_addr = INADDR_ANY; + sin4local.sin_port = htons(localport); + + int res = bind(nse->iod->sd, (struct sockaddr *)&sin4local, sizeof(sin4local)); + if(res != 0){ + perror("bind()"); + nse->event_done = 1; + nse->status = NSE_STATUS_ERROR; + nse->errnum = socket_errno(); + } + } else { + assert(sin->sin_family == AF_INET6); + #if HAVE_IPV6 + memset(&sin6local, 0, sizeof(sin6local)); + sin6local.sin6_family = sin->sin_family; + sin6local.sin6_addr = (struct in6_addr) IN6ADDR_ANY_INIT; + sin6local.sin6_port = htons(localport); + int res = bind(nse->iod->sd, (struct sockaddr *)&sin6local, sizeof(sin6local)); + if(res != 0){ + perror("bind()"); + nse->event_done = 1; + nse->status = NSE_STATUS_ERROR; + nse->errnum = socket_errno(); + } + #else + fatal("IPv6 address passed to nsock_connect_* call, but nsock was not compiled w/IPv6 support"); + #endif + } + } /*endif localport */ + + assert(sslen <= sizeof(nse->iod->peer)); memcpy(&nse->iod->peer, ss, sslen); nse->iod->peerlen = sslen; nse->iod->lastproto = proto; - + if(nse->event_done) + return; + if ((res = connect(nse->iod->sd, (struct sockaddr *) ss, sslen)) != -1) { nse->event_done = 1; nse->status = NSE_STATUS_SUCCESS; @@ -129,7 +177,8 @@ static void nsock_connect_internal(mspoo nsock_event_id nsock_connect_tcp(nsock_pool nsp, nsock_iod ms_iod, nsock_ev_handler handler, int timeout_msecs, void *userdata, struct sockaddr *saddr, - size_t sslen, unsigned short port) { + size_t sslen, unsigned short port, + unsigned short localport) { msiod *nsi = (msiod *) ms_iod; mspool *ms = (mspool *) nsp; @@ -149,7 +198,7 @@ nsock_event_id nsock_connect_tcp(nsock_p inet_ntop_ez(ss, sslen), port, nsi->id, nse->id); /* Do the actual connect() */ - nsock_connect_internal(ms, nse, IPPROTO_TCP, ss, sslen, port); + nsock_connect_internal(ms, nse, IPPROTO_TCP, ss, sslen, port, localport); nsp_add_event(ms, nse); return nse->id; @@ -168,7 +217,8 @@ nsock_event_id nsock_connect_ssl(nsock_p nsock_ev_handler handler, int timeout_msecs, void *userdata, struct sockaddr *saddr, size_t sslen, unsigned short port, - nsock_ssl_session ssl_session) { + nsock_ssl_session ssl_session, + unsigned short localport) { #ifndef HAVE_OPENSSL fatal("nsock_connect_ssl called - but nsock was built w/o SSL support. QUITTING"); @@ -201,7 +251,7 @@ nsock_event_id nsock_connect_ssl(nsock_p nsock_trace(ms, "SSL/TCP connection requested to %s:%hi (IOD #%li) EID %li", inet_ntop_ez(ss, sslen), port, nsi->id, nse->id); /* Do the actual connect() */ - nsock_connect_internal(ms, nse, IPPROTO_TCP, ss, sslen, port); + nsock_connect_internal(ms, nse, IPPROTO_TCP, ss, sslen, port, localport); nsp_add_event(ms, nse); return nse->id; @@ -264,7 +314,8 @@ nsock_event_id nsock_reconnect_ssl(nsock nsock_event_id nsock_connect_udp(nsock_pool nsp, nsock_iod nsiod, nsock_ev_handler handler, void *userdata, struct sockaddr *saddr, size_t sslen, - unsigned short port) { + unsigned short port, + unsigned short localport) { msiod *nsi = (msiod *) nsiod; mspool *ms = (mspool *) nsp; @@ -282,7 +333,7 @@ assert(nse); if (ms->tracelevel > 0) nsock_trace(ms, "UDP connection requested to %s:%hi (IOD #%li) EID %li", inet_ntop_ez(ss, sslen), port, nsi->id, nse->id); - nsock_connect_internal(ms, nse, IPPROTO_UDP, ss, sslen, port); + nsock_connect_internal(ms, nse, IPPROTO_UDP, ss, sslen, port, localport); nsp_add_event(ms, nse); diff -Nraup nmap-4.22SOC4/scripts/0trace.nse nmap-4.22SOC4-patched/scripts/0trace.nse --- nmap-4.22SOC4/scripts/0trace.nse 1970-01-01 01:00:00.000000000 +0100 +++ nmap-4.22SOC4-patched/scripts/0trace.nse 2007-08-18 05:13:27.019300352 +0200 @@ -0,0 +1,201 @@ +id = "0trace" +description = "" +author = "Marek Majkowski " +license = "See nmaps COPYING for licence" + +require "bit" +require "packet" + +--[[ + The idea of this script is pretty simple. Next traceroute tool. + But istead of sending udp or tcp-Syn packets with small ttl, + this tool injects correct (I hope) packets to tcp stream. + + How it works in detail: + 1) we randomly select source port + 2) We connect() to target host, using specified source port. + 3) While connecting we sniff network for third packet (ACK) in three-way tcp handshake. + 4) After we captured ACK packet, we're going to craft new packet based on caputered one: + - we add payload (in our case "\0") + - set PUSH flag + 5) We send crafted packet (which should be valid packet for this tcp stream) with ttls from 1 to 64. + 6) We listen for incoming ICMP error packages or valid ACK packet. + 7) Print source host from received icmp packets with ip destination/source from _payload on icmp_ message. + 8) If this destination address is different than the address of our target host, we found DNAT/SNAT :) + +]]-- + +categories = {"safe"} -- intrusive? + +Packet = packet.Packet + +---------------------------------------------------------------------------------------------------------------- +-- Main script body + +-- For every open tcp port +portrule = function(host, port) + if port.protocol == "tcp" and port.state == "open" and host.interface then + return true + end + return false +end + +-- index is on target_ip, target_port, localport +callback = function(packetsz, layer2, layer3) + local pac = Packet:new(layer3, packetsz-string.len(layer2)) + if pac.tcp then + return "0trace" .. pac.ip_bin_dst .. " " .. pac.tcp_dport .. " " .. pac.tcp_sport + end + return layer2 .. layer3 -- ignore +end + +-- only ack. no fin and no syn +bpf = "tcp and ((tcp[tcpflags] & tcp-ack) != 0 and (tcp[tcpflags] & tcp-syn) = 0 and (tcp[tcpflags] & tcp-fin) = 0)" + +action = function(host, port) + local pcap = nmap.new_socket() + local conn = nmap.new_socket() + local status, _, localport + + -- index is on target_ip, target_port, localport + pcap:pcap_open(host.interface, 5000, 0, callback, bpf) -- Only ACK flag + pcap:set_timeout(5000) -- 5 seconds? enough? + + for try=1,3 do + localport = math.random(2048, 65535) + -- capture ACK packet + pcap:pcap_register( "0trace" .. host.bin_ip .. " " .. port.number .. " " .. localport) + + local localport2 + status = conn:connect(host.ip, port.number, "tcp", localport) + if status then + _, _, localport2, _, _ = conn:get_info() + if localport2 ~= localport then + io.write("Sorry, setting source port is not working correctly!") + return + end + break + end + + -- let's try next port. unregister event and try again + pcap:pcap_unregister() + end + if not status then + -- return "can't find free port to bind to!!!" + return + end + + local ret + + -- receive ACK packet + local status, packetsz, layer2, layer3 + status, packetsz, layer2, layer3 = pcap:pcap_receive() + if status then + local tcp = Packet:new(layer3, packetsz-string.len(layer2)) + ret = trace_phase2(host, tcp) + else -- timeouted + ret = "Failed to capture ACK packet. Bad." + end + + conn:close() + return ret +end + +-- index is only on dport. +icmp_callback = function(packetsz, layer2, layer3) + local pac = Packet:new(layer3, packetsz-string.len(layer2)) + if pac.tcp then + return "0trace" .. pac.tcp_dport + elseif pac.icmp and pac.icmp_payload and pac.icmp_payload.tcp then + return "0trace" .. pac.icmp_payload.tcp_sport + end + return layer2 .. layer3 -- ignore +end + +-- Spoof packets +trace_phase2 = function(host, tcp) + local pcap = nmap.new_socket() + local dnet = nmap.new_dnet() + + -- icmp or ack. + bpf = string.format("icmp or (%s)", bpf) + pcap:pcap_open(host.interface, 5000, 0, icmp_callback, bpf) -- ACK or ICMP, index on port at host side + pcap:set_timeout(5000) -- 5 seconds? enough? + + -- fake new data packet + -- make sure buffer is good size + tcp.buf = tcp.buf:sub(1, tcp.ip_len) + local payload = "\0" + tcp.buf = tcp.buf .. payload + -- insert push flag + tcp:tcp_set_flags(bit.bor(tcp.tcp_flags, 0x08 )) --PUSH(0x08) + -- increase length + tcp:ip_set_len(tcp.ip_len + payload:len()) + tcp.tcp_data_length = tcp.tcp_data_length + payload:len() + -- recount checksum on tcp + tcp:tcp_count_checksum(tcp.ip_len) + + local src_ip = tcp.ip_bin_src .. "" + local dst_ip = tcp.ip_bin_dst .. "" + + local prev_packet -- previous received packet + local ret = "" -- return string + local badlevels = 0 -- how many ttl-levels were dropped by middle servers? + local noresponse = 0 -- received no response? + local ttl = 1 -- current ttl value. from 1 to 64 + while ttl < 64 do -- must be 'while' loop, becouse we modifi ttl variable by hand + -- capture packet, index only on sport + pcap:pcap_register( "0trace" .. tcp.tcp_sport) + + tcp:ip_set_ttl(ttl) + tcp:ip_count_checksum() + + dnet.ip_send(tcp.buf) + + local status, layer2, layer3, packetsz + status, packetsz, layer2, layer3 = pcap:pcap_receive() + if status then + -- got packet! + local curr_packet = Packet:new(layer3, packetsz-string.len(layer2)) + if curr_packet.tcp and prev_packet and prev_packet.tcp and curr_packet.ip_src == prev_packet.ip_src then + -- second good tcp responce, it's time to quit + break + end + + if curr_packet.tcp then + ret = ret .. "ack:" + end + ret = ret .. curr_packet.ip_src + if curr_packet.icmp and curr_packet.icmp_payload then + if curr_packet.icmp_payload.ip_bin_dst ~= dst_ip then + ret = ret .. "[DNAT" .. curr_packet.icmp_payload.ip_dst .. "]" + dst_ip = curr_packet.icmp_payload.ip_bin_dst + end + if curr_packet.icmp_payload.ip_bin_src ~= src_ip then + ret = ret .. "[SNAT" .. curr_packet.icmp_payload.ip_src .. "]" + src_ip = curr_packet.icmp_payload.ip_bin_src + end + end + ret = ret .. " " + prev_packet = curr_packet + noresponse = 0 + else -- timeouted + noresponse = noresponse + 1 + if noresponse <= 3 then + -- stay on this ttl-depth + ttl = ttl - 1 + else --more than 3 retries + ret = ret .. "[silent] " + -- give up after three hosts without responce + badlevels = badlevels + 1 + if badlevels > 3 then + break + end + end + end + ttl = ttl + 1 -- next level + end + + return ret +end + diff -Nraup nmap-4.22SOC4/scripts/p0fa.fp nmap-4.22SOC4-patched/scripts/p0fa.fp --- nmap-4.22SOC4/scripts/p0fa.fp 1970-01-01 01:00:00.000000000 +0100 +++ nmap-4.22SOC4-patched/scripts/p0fa.fp 2007-08-18 05:13:27.019300352 +0200 @@ -0,0 +1,208 @@ +# +# p0f - SYN+ACK fingerprints +# -------------------------- +# +# .-------------------------------------------------------------------------. +# | The purpose of this file is to cover signatures for outgoing TCP/IP | +# | connections (SYN+ACK packets). This mode of operation can be enabled | +# | with -A option. Please refer to p0f.fp for information on the metrics | +# | used to create a signature, and for a guide on adding new entries to | +# | those files. This database is somewhat neglected, and is looking for a | +# | caring maintainer. | +# `-------------------------------------------------------------------------' +# +# (C) Copyright 2000-2006 by Michal Zalewski +# +# Plenty of signatures contributed in bulk by rain forest puppy, Paul Woo and +# Michael Bauer. +# +# Submit all additions to the authors. Read p0f.fp before adding any +# signatures. Run p0f -A -C after making any modifications. This file is +# NOT compatible with SYN, RST+, or stray ACK modes. Use only with -A option. +# +# Feel like contributing? You can run p0f -A -K, then test/tryid -iR nnn... +# +# IMPORTANT INFORMATION ABOUT THE INTERDEPENDENCY OF SYNs AND SYN+ACKs +# -------------------------------------------------------------------- +# +# Some systems would have different SYN+ACK fingerprints depending on +# the system that sent SYN. More specifically, RFC1323, RFC2018 and +# RFC1644 extensions sometimes show up only if SYN had them enabled. +# +# Also, some silly systems may copy WSS from the SYN packet you've sent, +# in which case, you need to wildcard the value. Use test/sendsyn.c, which +# uses a distinct WSS of 12345, to test for this condition if unsure. +# +# IMPORTANT INFORMATION ABOUT DIFFERENCES IN COMPARISON TO p0f.fp: +# ---------------------------------------------------------------- +# +# - 'A' quirk would be present on almost every signature here. ACK number +# is unusual for SYN packets, but is a commonplace in SYN+ACK packets, +# of course. It is still possible to have a signature without 'A', when +# the ACK flag is present but the value is zero - this, however, is +# very uncommon. +# +# - 'T' quirk would show up on almost all signatures for systems implementing +# RFC1323. The second timestamp is only unusual for SYN packets. SYN+ACK +# are expected to have it set. +# + +########################## +# Standard OS signatures # +########################## + +# ---------------- Linux ------------------- + +32736:64:0:44:M*:A:Linux:2.0 +S22:64:1:60:M*,S,T,N,W0:AT:Linux:2.2 +S22:64:1:52:M*,N,N,S,N,W0:A:Linux:2.2 w/o timestamps + +5792:64:1:60:M*,S,T,N,W0:AT:Linux:older 2.4 +5792:64:1:60:M*,S,T,N,W0:ZAT:Linux:recent 2.4 (1) +S4:64:1:44:M*:ZA:Linux:recent 2.4 (2) +5792:64:1:44:M*:ZA:Linux:recent 2.4 (3) + +S4:64:1:52:M*,N,N,S,N,W0:ZA:Linux:2.4 w/o timestamps + +# --------------- Windows ------------------ + +65535:128:1:64:M*,N,W0,N,N,T0,N,N,S:A:Windows:2000 SP4 +S44:128:1:64:M*,N,W0,N,N,T0,N,N,S:A:Windows:XP SP1 +S12:128:1:64:M*,N,W0,N,N,T0,N,N,S:A:Windows:2000 (SP1+) +S6:128:1:44:M*:A:Windows:NT 4.0 SP1+ +65535:128:1:48:M*,N,N,S:A:Windows:98 (SE) +65535:128:1:44:M*:A:Windows:2000 (1) +16616:128:1:44:M*:A:Windows:2003 +16384:128:1:44:M*:A:Windows:2000 (2) +S16:128:1:44:M*:A:Windows:2000 (3) + +# ------------------- OpenBSD -------------- + +17376:64:1:64:M*,N,N,S,N,W0,N,N,T:AT:OpenBSD:3.3 + +# ------------------- NetBSD ---------------- + +16384:64:0:60:M*,N,W0,N,N,T0:AT:NetBSD:1.6 + +# ----------------- HP/UX ------------------ + +32768:64:1:44:M*:A:HPUX:10.20 + +# ----------------- Tru64 ------------------ + +S23:60:0:48:M*,N,W0:A:Tru64:5.0 (1) +65535:64:0:44:M*:A:Tru64:5.0 (2) + +# ----------------- Novell ----------------- + +6144:128:1:52:M*,W0,N,S,N,N:A:Novell:Netware 6.0 (SP3) +32768:128:1:44:M*:A:Novell:Netware 5.1 + +# ------------------ IRIX ------------------ + +60816:60:1:60:M*,N,W0,N,N,T:AT:IRIX:6.5.0 + +# ----------------- Solaris ---------------- + +49232:64:1:64:N,N,T,M*,N,W0,N,N,S:AT:Solaris:9 (1) +S1:255:1:60:N,N,T,N,W0,M*:AT:Solaris:7 +24656:64:1:44:M*:A:Solaris:8 +33304:64:1:60:N,N,T,M*,N,W1:AT:Solaris:9 (2) + +# ----------------- FreeBSD ---------------- + +65535:64:1:60:M*,N,W1,N,N,T:AT:FreeBSD:5.0 +57344:64:1:44:M*:A:FreeBSD:4.6-4.8 +65535:64:1:44:M*:A:FreeBSD:4.4 + +57344:64:1:48:M1460,N,W0:A:FreeBSD:4.6-4.8 (wscale) +57344:64:1:60:M1460,N,W0,N,N,T:AT:FreeBSD:4.6-4.8 (RFC1323) + +# ------------------- AIX ------------------ + +S17:255:1:44:M536:A:AIX:4.2 + +S12:64:0:44:M1460:A:AIX:5.2 ML04 (1) +S42:64:0:44:M1460:A:AIX:5.2 ML04 (2) + +# ------------------ BSD/OS ---------------- + +S6:64:1:60:M1460,N,W0,N,N,T:AT:BSD/OS:4.0.x + +# ------------------ OS/390 ---------------- + +2048:64:0:44:M1460:A:OS/390:? + +# ------------------ Novell ---------------- + +6144:128:1:44:M1400:A:Novell:iChain 2.2 + +# ------------------ MacOS ----------------- + +33304:64:1:60:M*,N,W0,N,N,T:AT:MacOS:X 10.2.6 + +################################################################# +# Contributed by Ryan Kruse - trial run # +################################################################# + +# S4:255:0:44:M1024:A:Cisco:LocalDirector +# 1024:255:0:44:M536:A:Cisco,3COM,Nortel:CatIOS,SuperStack,BayStack +# S16:64:0:44:M512:A:Nortel:Contivity +# 8192:64:0:44:M1460:A:Cisco,Nortel,SonicWall,Tasman:Aironet,BayStack Switch,Soho,1200 +# 4096:255:0:44:M1460:A:Cisco:PIX,CatOS +# 8192:128:0:44:M1460:A:Cisco:VPN Concentrator +# 8192:128:0:60:M1460,N,W0,N,N,T:AT:Cisco:VPN Concentrator +# 4096:32:0:44:M1460:A:Cisco,3COM,Extreme,Nortel:Catalyst Switch CatOS,CoreBuilder,Summit,Passport +# S4:255:0:44:M536:ZA:Cisco:IOS +# 1024:32:0:44:M1480:UA:Nortel:BayStack Switch +# 4096:60:0:44:M1460:A:Adtran:NetVanta +# 4096:64:0:44:M1008:A:Adtran:TSU +# S4:32:0:44:M1024:A:Alcatel:Switch +# S8:255:0:44:M536:ZA:Cisco:IOS +# 50:255:0:44:M536:ZA:Cisco:CatIOS +# 512:64:0:40:.:A:Dell:Switch +# 4096:64:0:40:.:A:Enterasys:Vertical Horizon Switch +# 17640:64:1:44:M1460:A:F5,Juniper,RiverStone:BigIP,Juniper OS,Router 7.0+ +# 16384:64:0:44:M1460:A:Foundry,SonicWall:BigIron,TZ +# 4096:64:0:44:M1452:A:HP:ProCurve Switch +# 1024:64:0:44:M1260:A:Marconi:ES +# 10240:30:0:44:M1460:A:Milan:Switch +# 4096:64:0:44:M1380:A:NetScreen:Firewall +# S32:64:0:44:M512:A:Nokia:CheckPoint +# 1024:64:0:44:M536:A:Nortel:BayStack Switch +# 4128:255:0:44:M*:ZA:Cisco:IOS +# 1024:16:0:44:M536:A:Nortel:BayStack Switch +# 1024:30:0:44:M1480:A:Nortel:BayStack Switch +# S4:64:0:44:M1460:A:Symbol:Spectrum Access Point +# S2:255:0:44:M512:A:ZyXEL:Prestige +# S16:255:0:44:M1024:A:ZyXEL:ZyAI + +########################################### +# Appliance / embedded / other signatures # +########################################### + +16384:64:1:44:M1460:A:F5:BigIP LB 4.1.x (sometimes FreeBSD) +4128:255:0:44:M*:ZA:Cisco:Catalyst 2900 12.0(5) +4096:60:0:44:M*:A:Brother:HL-1270N +S1:30:0:44:M1730:A:Cyclades:PR3000 +8192:64:1:44:M1460:A:NetApp:Data OnTap 6.x +5792:64:1:60:W0,N,N,N,T,M1460:ZAT:FortiNet:FortiGate 50 +S1:64:1:44:M1460:A:NetCache:5.3.1 +S1:64:0:44:M512:A:Printer:controller (?) +4096:128:0:40:.:A:Sequent:DYNIX 4.2.x +S16:64:0:44:M512:A:3Com:NBX PBX (BSD/OS 2.1) +16000:64:0:44:M1442:A:CastleNet:DSL router +S2:64:0:44:M32728:A:D-Link:DSL-500 +S4:60:0:44:M1460:A:HP:JetDirect A.05.32 +8576:64:1:44:M*:A:Raptor:firewall +S12:64:1:44:M1400:A:Cequrux Firewall:4.x +2048:255:0:44:M1400:A:Netgear:MR814 +16384:128:0:64:M1460,N,W0,N,N,T0,N,N,S:A:Akamai:??? (1) +16384:128:0:60:M1460,N,W0,N,N,T0:A:Akamai:??? (2) + +8190:255:0:44:M1452:A:Citrix:Netscaler 6.1 + +# Whatever they run. EOL boys... +S6:128:1:48:M1460,E:PA:@Slashdot:or BusinessWeek (???) + + diff -Nraup nmap-4.22SOC4/scripts/p0f.nse nmap-4.22SOC4-patched/scripts/p0f.nse --- nmap-4.22SOC4/scripts/p0f.nse 1970-01-01 01:00:00.000000000 +0100 +++ nmap-4.22SOC4-patched/scripts/p0f.nse 2007-08-18 05:13:27.019300352 +0200 @@ -0,0 +1,419 @@ +id = "p0f" +description = "Guesses target os per each opened port, instead of standard per host tests." +author = "Marek Majkowski " +license = "See nmaps COPYING for licence" + +require "bit" +require "packet" + +--[[ + it's just an implementation of lcamtuf's p0f SYN+ACK scan + Take a look at http://lcamtuf.coredump.cx/p0f.shtml +]]-- + +categories = {"safe"} -- intrusive? + +-- For every open tcp port +portrule = function(host, port) + if port.protocol == "tcp" and port.state == "open" and host.interface then + return true + end + return false +end + + + +---------------------------------------------------------------------------------------------------------------- +-- Needed helpers +Packet = packet.Packet + +-- split string to array +function split(str, regexp) + local tab = {} + local i = 0 + for x in string.gfind(str, regexp) do + i = i+1 + tab[i] = x + end + return tab +end +-- join array to string +function join(delim, arr, idx) + local i = idx + local o = "" + while arr[i] ~= nil do + if o ~= "" then + o = o .. delim + end + o = o .. arr[i] + i = i + 1 + end + return o +end +function tohex(str) + local b = "" + for c in string.gmatch(str, ".") do + b = string.format('%s%02x',b, string.byte(c)) + end + return b +end + +---------------------------------------------------------------------------------------------------------------- +-- Adding p0f specific features to Packet class +function Packet:to_p0f() + return string.format( + "%s:%i:%i:%i:%s:%s:?:?|link: %s, %s%s%s", + self:to_p0f_window_size(), + self.ip_ttl, + (self.ip_df and "1" or "0"), + self:to_p0f_packet_size(), + self:to_p0f_tcp_options(), + self:to_p0f_quirks(), + self:tcp_lookup_link(), + self:to_p0f_uptime(), + self:to_fill(), + self:to_ipid() + ) +end +function Packet:to_fill() -- ethernet fill, if packet is smaller than 46 bytes + local l = self.tcp_data_offset + self.tcp_data_length + local s = self.packet_len + if l < s then + return string.format(", fill:%s", tohex( string.sub(self.buf, l+1) )) + end + return "" +end +function Packet:to_ipid() -- ipid number + if self.ip_id > 0 then + return string.format(", ipid:%i", self.ip_id) + end + return "" +end + +function Packet:to_p0f_uptime() + if self.tcp_opt_t1 == nil then + return "up: disabled" + end + return string.format("up: %i hrs", self.tcp_opt_t1/360000) +end +function Packet:to_p0f_window_size() + local win = self.tcp_win + if self.tcp_opt_mss ~= nil and + win % self.tcp_opt_mss == 0 then + return string.format("S%i", win/self.tcp_opt_mss) -- not floating -> no reminder + end + if self.tcp_opt_mtu ~= nil and + win % self.tcp_opt_mtu == 0 then + return string.format("T%i", win/self.tcp_opt_mtu) -- not floating -> no reminder + end + return string.format("%i", win) +end +function Packet:to_p0f_packet_size() + if self.ip_len < 100 then + return string.format("%i", self.ip_len) + end + -- bigger than 99 + return "*" +end +function Packet:to_p0f_tcp_options() + local opt_chr = { + [0] = "E", + [1] = "N", + [2] = "M", + [3] = "W", + [4] = "S", + [8] = "T" + } + local str = "" + for k,opt in ipairs(self.tcp_options) do + if opt_chr[opt.type] ~= nil then + str = str .. opt_chr[opt.type] + else + str = str .. string.format("?%i", opt.type) + end + + if opt.type == 2 then + str = str .. string.format("%i", packet.u16(opt.data, 0)) + elseif opt.type == 3 then + str = str .. string.format("%i", packet.u8(opt.data, 0)) + elseif opt.type == 8 then + local t = packet.u32(opt.data, 0) + if t == 0 then + str = str .. "0" + end + end + str = str .. "," + end + if string.len(str) == 0 then + return "." + end + return string.sub(str, 0, string.len(str)-1) +end +function Packet:to_p0f_quirks() + local str = "" + + -- P + if self.tcp_opt_after_eol then + str = str .. "P" + end + + -- Z + if self.ip_id == 0 then + str = str .. "Z" + end + + -- I + if self.ip_options[1] ~= nil then + str = str .. "I" + end + + -- U + if self.tcp_urp ~= 0 then + str = str .. "U" + end + + -- X + if self.tcp_x2 ~= 0 then + str = str .. "X" + end + + -- A + if self.tcp_ack ~= 0 then + str = str .. "A" + end + + -- T + if self.tcp_opt_t2 ~= nil and self.tcp_opt_t2 > 0 then + str = str .. "T" + end + + -- D + if self.tcp_data_length > 0 then + str = str .. "D" + end + + -- F + if self.tcp_th_urg or self.tcp_th_fin then -- no push? + str = str .. "F" + end + + -- not implemented option -> "!" + + if string.len(str) == 0 then + return "." + end + return str +end + +---------------------------------------------------------------------------------------------------------------- +-- signature mangling functions + +function sig_unpack(signature) + local s = {} + local tab = split(signature, "[^:]+") + s.wwww = tab[1] + s.ttt = tonumber(tab[2]) + s.D = tab[3] + s.ss = tab[4] + s.OOO = split(tab[5], "[^,]+") + s.QQ = tab[6] -- split(tab[6], ".") + s.OS = tab[7] + s.details = join(":" ,tab, 8) + s.full = signature + return s +end +function sig_getindex_OOO(t) + local s = "" + for k,v in ipairs(t) do + local t = string.find(v, "^[NEST?]") -- no W and M + if t ~= nil then + s = s .. v .. "," + end + end + return s +end +function sig_getindex(s) + return string.format("%s|%s|%s|%s", s.D, s.ss, sig_getindex_OOO(s.OOO), s.QQ ) +end + +function sigs_load(filename) + local sigs = {} + local f = io.open("scripts/" .. filename, "r") + if f == nil then + io.write("P0F file NOT FOUND " .. filename .. "\n") + end +-- io.write("Loading p0f signature file\n") + while true do + local line = f:read("*line") + if line == nil then break end + if string.find(line, "^#") == nil and + string.find(line, ":") ~= nil then + -- io.write(line .. "!\n") + local sig = sig_unpack(line) + local idx = sig_getindex(sig) + if sigs[idx] == nil then + sigs[idx] = {} + end + table.insert(sigs[idx], sig) + -- io.write(string.format("%s\t%s\n", idx , line)) + end + + end + f:close() + return sigs +end +function test_opt(a, b) -- a=['Xnnn', 'X%nnn', 'X*'] b=[Xnnn] + if a == b then + return true + end + if string.len(a)<2 then + return false + end + local a1 = string.sub(a, 1, 1) + local b1 = string.sub(b, 1, 1) + local a2 = string.sub(a, 2, 2) + local b2 = string.sub(b, 2, 2) + local a2s = string.sub(a, 2) + local b2s = string.sub(b, 2) -- can't be % + local a3s = string.sub(a, 3) + local b3s = string.sub(b, 3) + if a1 ~= b1 then + return false + end + if a2s == "*" then + return true + end + if a2 == "%" then + if tonumber(b2s) % tonumber(a3s) == 0 then + return true + else + return false + end + end + return false +end + +function sig_compare(t, s) + if test_opt(t.wwww, s.wwww)~= true then + return false, string.format("wwww %s!=%s", t.wwww, s.wwww) + end + if t.ttt < s.ttt or + s.ttt < t.ttt-40 then + return false, string.format("ttl %i>=%i>=%i", t.ttt, s.ttt, t.ttt-40) + end + if t.D ~= s.D then + return false, string.format("D %s!=%s", t.D, s.D) + end + if t.ss ~= s.ss then + return false, string.format("ss %s!=%s", t.ss, s.ss) + end + if t.QQ ~= s.QQ then + return false, string.format("QQ %s!=%s", t.QQ, s.QQ) + end + + return sig_compare_OOO(t.OOO, s.OOO) +end + +function sig_compare_OOO(to, so) + for k,v in ipairs(to) do + local a = v + local b = so[k] + if test_opt(a,b) ~= true then + return false, string.format("Opt %s!=%s", a, b) + end + end + return true +end + +function sig_test(sigs, tsignature) + local ts = sig_unpack(tsignature) + local idx = sig_getindex(ts) + local t = split(tsignature, "[^|]+") + if sigs[idx] == nil then + return string.format("UNKNOWN [%s] (%s)", t[1], t[2]) + end + local out = {} + for k,sig in ipairs(sigs[idx]) do + local t, err = sig_compare(sig, ts) + if t == true then + table.insert(out, sig) +-- else +-- io.write(string.format("%s\t\t%s\n", sig.full, err)) -- match debugging + end + end + + if out[1] == nil then + return string.format("UNKNOWN [%s] (%s)", t[1], t[2]) + end + + local s = "" + local dist + for k, sig in ipairs(out) do + dist = tonumber(sig.ttt) - tonumber(ts.ttt) + s = s .. string.format("%s %s|", sig.OS, sig.details) + end + s = string.sub(s, 1, string.len(s)-1) + return string.format("%s (distance: %i, %s)", s, dist, t[2]) +end + +---------------------------------------------------------------------------------------------------------------- +-- Main script body + + + +-- index is on target_ip, target_port +-- packet is from target (so target is source) +callback = function(packetsz, layer2, layer3) + local tcp = Packet:new(layer3, packetsz-string.len(layer2)) + local a = tcp.ip_bin_src .. string.format("%i", tcp.tcp_sport) + return a +end + +function make_index(target_ip, target_port) + local a = target_ip .. string.format("%i", target_port) + return a +end + + +action = function(host, port) + local pcap = nmap.new_socket() + local conn = nmap.new_socket() + local status, packetsz, layer2, layer3 + local sigs = nmap.registry["p0f_sigs"] + local _, o, tcp, localport + if sigs == nil then + sigs = sigs_load("p0fa.fp") + nmap.registry["p0f_sigs"] = sigs + end + + -- index is on source_ip, target_ip, target_port + pcap:pcap_open(host.interface, 256, 0, callback, + "tcp and (tcp[tcpflags] & tcp-ack) != 0 and (tcp[tcpflags] & tcp-syn) != 0") + pcap:set_timeout(5000) -- 5 seconds? enough? + + + pcap:pcap_register( make_index(host.bin_ip, port.number) ) + + status = conn:connect(host.ip, port.number) + _, _, localport, _, _ = conn:get_info() + if not status then + return nil + end + + while true do + status , packetsz, layer2, layer3 = pcap:pcap_receive() + if status then + tcp = Packet:new(layer3, packetsz-string.len(layer2)) + if tcp.tcp_dport == localport then + o = sig_test(sigs, tcp:to_p0f()) + break + end + else -- timeouted + o = "failed to capture SYN+ACK packet" + break + end + end + + conn:close() + return o +end diff -Nraup nmap-4.22SOC4/scripts/promiscuous.nse nmap-4.22SOC4-patched/scripts/promiscuous.nse --- nmap-4.22SOC4/scripts/promiscuous.nse 1970-01-01 01:00:00.000000000 +0100 +++ nmap-4.22SOC4-patched/scripts/promiscuous.nse 2007-08-18 05:13:27.019300352 +0200 @@ -0,0 +1,134 @@ +id = "Promiscuous detection" +description = "Checks if hosts on local ethernet have network card in promiscuous mode." +author = "Marek Majkowski " +license = "See nmaps COPYING for licence" + +--[[ +This script tries to guess if node in local ethernet is in promisucous mode. + +The technique is described here: + http://www.securityfriday.com/promiscuous_detection_01.pdf + +]]-- + +categories = {"safe"} -- intrusive? + +-- okay, we're interested only in hosts that are on our ethernet lan +hostrule = function(host, port) + if host.directly_connected == true and + host.mac_addr ~= nil and + host.mac_addr_src ~= nil and + host.interface ~= nil and + nmap.get_interface_link(host.interface) == 'ethernet' then + return true + end + return false +end + +--[[ +function bintohex(str) + local b = "" + for c in string.gmatch(str, ".") do + b = string.format('%s%02x',b, string.byte(c)) + end + return b +end +]]-- + +callback = function(packetsz, layer2, layer3) + return string.sub(layer2, 0, 12) +end + + +do_test = function(dnet, pcap, host, test) + local _ + local status + local i = 0 + + -- ARP requests are send with timeouts: 10ms, 40ms, 90ms + -- before each try, we wait at least 100ms + -- in summary, this test takes at least 100ms and at most 440ms + for i=1,3 do + -- flush buffers :), wait quite long. + repeat + pcap:set_timeout(100) + pcap:pcap_register(host.mac_addr_src .. host.mac_addr) + status ,_,_,_ = pcap:pcap_receive() + until status ~= true + pcap:set_timeout(10 * i*i) + pcap:pcap_register(host.mac_addr_src .. host.mac_addr) + + dnet:ethernet_send(test) + + status ,_,_,_ = pcap:pcap_receive() + if status == true then + -- the basic idea, was to inform user about time, when we got packet + -- so that 1 would mean (0-10ms), 2=(10-40ms) and 3=(40ms-90ms) + -- but when we're running this tests on macs, first test is always 2. + -- which means that the first answer is dropped. + -- for now, just return 1 if test was successfull, it's easier + -- return(i) + return(1) + end + end + return('_') +end + +action = function(host, port) + local dnet = nmap.new_dnet() + local pcap = nmap.new_socket() + local _ + local status + local results = { + ['1_____1_'] = false, -- MacOSX(Tiger.Panther)/Linux/ ?Win98/ WinXP sp2(no pcap) + ['1_______'] = false, -- Old Apple/SunOS/3Com + ['1___1_1_'] = false, -- MacOSX(Tiger) + ['11111111'] = true, -- BSD/Linux/OSX/ (or not promiscous openwrt ) + ['1_1___1_'] = false, -- WinXP sp2 + pcap|| win98 sniff || win2k sniff (see below) + ['111___1_'] = true, -- WinXP sp2 promisc +-- ['1111__1_'] = true, -- ?Win98 promisc + ??win98 no promisc *not confirmed* + } + dnet:ethernet_open(host.interface) + + pcap:pcap_open(host.interface, 64, 0, callback, "arp") + + local test_static = host.mac_addr_src .. + string.char(0x08,0x06, 0x00,0x01, 0x08,0x00, 0x06,0x04, 0x00,0x01) .. + host.mac_addr_src .. + host.bin_ip_src .. + string.char(0x00,0x00, 0x00,0x00, 0x00,0x00) .. + host.bin_ip + local t = { + string.char(0xff,0xff, 0xff,0xff, 0xff,0xff), -- B32 no meaning? + string.char(0xff,0xff, 0xff,0xff, 0xff,0xfe), -- B31 + string.char(0xff,0xff, 0x00,0x00, 0x00,0x00), -- B16 + string.char(0xff,0x00, 0x00,0x00, 0x00,0x00), -- B8 + string.char(0x01,0x00, 0x00,0x00, 0x00,0x00), -- G + string.char(0x01,0x00, 0x5e,0x00, 0x00,0x00), -- M0 + string.char(0x01,0x00, 0x5e,0x00, 0x00,0x01), -- M1 no meaning? + string.char(0x01,0x00, 0x5e,0x00, 0x00,0x03), -- M3 + } + local v + local out = "" + for _, v in ipairs(t) do + out = out .. do_test(dnet, pcap, host, v .. test_static) + end + + dnet:ethernet_close() + pcap:pcap_close() + + if out == '1_1___1_' then + return 'Win98/Win2K/WinXP with pcap installed. I\'m unsure if they\'re sniffing. (tests: "' .. out .. '")' + end + if results[out] == false then + -- probably not sniffing + return + end + if results[out] == true then + -- rather sniffer. + return 'PROMISCUOUS (tests: "' .. out .. '")' + end + + -- results[out] == nil + return 'Unknown (tests: "' .. out .. '")' +end diff -Nraup nmap-4.22SOC4/scripts/recordroute.nse nmap-4.22SOC4-patched/scripts/recordroute.nse --- nmap-4.22SOC4/scripts/recordroute.nse 1970-01-01 01:00:00.000000000 +0100 +++ nmap-4.22SOC4-patched/scripts/recordroute.nse 2007-08-18 05:13:27.019300352 +0200 @@ -0,0 +1,116 @@ +id = "ip RR" +description = "" +author = "Marek Majkowski " +license = "See nmaps COPYING for licence" + +require "bit" +require "packet" + +--[[ + We send tcp SYN packet to target host/port with IP RecordRoute option. + It should be able to record up to nine hops ip addresses in the way to target. + + This tcp SYN packet have the same signatures as nmap's standard tcp-syn scan (except the RR flag of course). + +]]-- + +categories = {"safe"} -- intrusive? + +Packet = packet.Packet + +---------------------------------------------------------------------------------------------------------------- +-- Main script body + +-- For every open tcp port +portrule = function(host, port) + if port.protocol == "tcp" and port.state == "open" and host.interface then + return true + end + return false +end + + +callback = function(packetsz, layer2, layer3) + local pac = Packet:new(layer3, packetsz-string.len(layer2)) + if pac.tcp then + return "recordroute" .. pac.ip_bin_src .. " " .. pac.tcp_sport .. " " .. pac.tcp_dport + end + return layer2 .. layer3 -- ignore +end + +-- packet from ME to TARGET +action = function(host, port) + local pcap = nmap.new_socket() + local dnet = nmap.new_dnet() + + -- SYN+ACK + local bpf = "tcp and ((tcp[tcpflags] & tcp-syn) != 0 and (tcp[tcpflags] & tcp-ack) != 0)" + pcap:pcap_open(host.interface, 5000, 0, callback, bpf) -- SYN+ACK, key is ip_shost, tcp_sport, tcp_dport + pcap:set_timeout(5000) -- 5 seconds? enough? + + + local pck = packet.hextobin( -- standard Nmap syn packet + "4500 002c 55d1 0000 2a06 de79 0000 0000" .. + "0000 0000 cba4 0050 e56a 62e7 0000 0000" .. + "6002 0c00 1b5e 0000 0204 05b4" + ) + local tcp = Packet:new(pck, pck:len()) + tcp:ip_set_bin_src(host.bin_ip_src) + tcp:ip_set_bin_dst(host.bin_ip) + tcp:ip_set_ttl(math.random(37,63)) + local seq = math.random(1,2147483647) -- Lua can't handle bigger number. + local localport = math.random(1025, 65535) + tcp:tcp_set_seq(seq) + tcp:tcp_set_sport(localport) + tcp:tcp_set_dport(port.number) + + -- set Record Route ip option + tcp:ip_set_options(packet.hextobin("0107 2704 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000")) -- RR + -- recount checksum on tcp + tcp:tcp_count_checksum(tcp.ip_len) + -- recount checksum on ip + tcp:ip_count_checksum() + + local bad + for bad=1,3 do -- + -- capture packet + pcap:pcap_register( "recordroute" .. host.bin_ip .. " " .. port.number .. " " .. localport ) + + dnet.ip_send(tcp.buf) + + local status, packetsz, layer2, layer3 + status , packetsz, layer2, layer3 = pcap:pcap_receive() + if status then -- OK + local tcp = Packet:new(layer3, packetsz-string.len(layer2)) + -- good packet + return ips_from_rr(tcp) + end + end + return "packet dropped" +end + +function ips_from_rr(tcp) + local str = "" + if not tcp.ip_options then + return nil + end + for k,opt in ipairs(tcp.ip_options) do + if opt.type == 0x07 then -- RR + local d = opt.data:sub(2) -- ignore pointer + local ip + + while d:len()>3 do + ip = d:sub(1,4) + d = d:sub(5) + if ip ~= "\0\0\0\0" then + str = str .. packet.toip(ip) .. " " + end + end + end + end + if str == "" then + return "RR cleared" + end + return str +end + diff -Nraup nmap-4.22SOC4/service_scan.cc nmap-4.22SOC4-patched/service_scan.cc --- nmap-4.22SOC4/service_scan.cc 2007-08-14 08:46:54.000000000 +0200 +++ nmap-4.22SOC4-patched/service_scan.cc 2007-08-18 05:13:27.023300579 +0200 @@ -1770,13 +1770,13 @@ static void startNextProbe(nsock_pool ns nsock_connect_tcp(nsp, svc->niod, servicescan_connect_handler, DEFAULT_CONNECT_TIMEOUT, svc, (struct sockaddr *) &ss, ss_len, - svc->portno); + svc->portno, 0); } else { assert(svc->tunnel == SERVICE_TUNNEL_SSL); nsock_connect_ssl(nsp, svc->niod, servicescan_connect_handler, DEFAULT_CONNECT_SSL_TIMEOUT, svc, (struct sockaddr *) &ss, - ss_len, svc->portno, svc->ssl_session); + ss_len, svc->portno, svc->ssl_session, 0); } } else { assert(svc->proto == IPPROTO_UDP); @@ -1968,12 +1968,12 @@ static int launchSomeServiceProbes(nsock nsock_connect_tcp(nsp, svc->niod, servicescan_connect_handler, DEFAULT_CONNECT_TIMEOUT, svc, (struct sockaddr *)&ss, ss_len, - svc->portno); + svc->portno, 0); else { assert(svc->proto == IPPROTO_UDP); nsock_connect_udp(nsp, svc->niod, servicescan_connect_handler, svc, (struct sockaddr *) &ss, ss_len, - svc->portno); + svc->portno, 0); } // Now remove it from the remaining service list SG->services_remaining.pop_front();