1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-09 06:01:28 +00:00

Merge through r16884 from /nmap-exp/kris/nse-rawip plus the following changelog

entries:

o [NSE] Raw packet sending at the IP layer is now supported, in addition to
  the Ethernet sending functionality.  Packets to send start with an IPv4
  header and can be sent to arbitrary hosts. [Kris]

o [NSE] Added the ipidseq script to classify a host's IP ID sequence numbers
  in the same way Nmap does.  This can be used to test hosts' suitability for
  Nmap's Idle Scan (-sI), i.e. check if a host is an idle zombie.  This is
  the first script to use the new raw IP sending functionality in NSE. [Kris]

o [NSE] Added the function nmap.is_privileged() to tell a script if, as far
  as Nmap's concerned, it can do privileged operations.  For instance, this
  can be used to see if a script should be able to open a raw socket or
  Ethernet interface. [Kris]

o [NSE] Added the function nmap.get_ports() to allow a script to iterate
  over a host's port tables matching a certain protocol and state. [Kris,
  Patrick]
This commit is contained in:
kris
2010-02-26 20:42:10 +00:00
parent 480394756b
commit a42ea72a97
9 changed files with 563 additions and 23 deletions

View File

@@ -2,6 +2,24 @@
[NOT YET RELEASED] [NOT YET RELEASED]
o [NSE] Raw packet sending at the IP layer is now supported, in addition to
the Ethernet sending functionality. Packets to send start with an IPv4
header and can be sent to arbitrary hosts. [Kris]
o [NSE] Added the ipidseq script to classify a host's IP ID sequence numbers
in the same way Nmap does. This can be used to test hosts' suitability for
Nmap's Idle Scan (-sI), i.e. check if a host is an idle zombie. This is
the first script to use the new raw IP sending functionality in NSE. [Kris]
o [NSE] Added the function nmap.is_privileged() to tell a script if, as far
as Nmap's concerned, it can do privileged operations. For instance, this
can be used to see if a script should be able to open a raw socket or
Ethernet interface. [Kris]
o [NSE] Added the function nmap.get_ports() to allow a script to iterate
over a host's port tables matching a certain protocol and state. [Kris,
Patrick]
o [Ncat] Fixed a handle leak with --exec and --sh-exec on Windows, o [Ncat] Fixed a handle leak with --exec and --sh-exec on Windows,
found by Jon Greaves. One thread handle was being leaked per child found by Jon Greaves. One thread handle was being leaked per child
process invocation. [David] process invocation. [David]

View File

@@ -1379,7 +1379,7 @@ LUALIB_API int luaopen_openssl(lua_State *L) {
The port table is passed to an NSE service script (i.e. only those with a portrule rather than a hostrule) in the same The port table is passed to an NSE service script (i.e. only those with a portrule rather than a hostrule) in the same
fashion as the host table. It contains information about the port fashion as the host table. It contains information about the port
against which the script is running. While this table is not passed to host scripts, port states on the target can still be requested from Nmap against which the script is running. While this table is not passed to host scripts, port states on the target can still be requested from Nmap
using the <literal>nmap.get_port_state()</literal> call. using the <literal>nmap.get_port_state()</literal> and <literal>nmap.get_ports()</literal> calls.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@@ -1509,8 +1509,8 @@ LUALIB_API int luaopen_openssl(lua_State *L) {
<literal>port.state</literal> generally contains one <literal>port.state</literal> generally contains one
of those values. Other values might appear if the port of those values. Other values might appear if the port
table is a result of the table is a result of the
<literal>get_port_state</literal> function. You can <literal>get_port_state</literal> or <literal>get_ports</literal>
adjust the port state using the functions. You can adjust the port state using the
<literal>nmap.set_port_state()</literal> call. This is <literal>nmap.set_port_state()</literal> call. This is
normally done when an <literal>open|filtered</literal> normally done when an <literal>open|filtered</literal>
port is determined to be <literal>open</literal>. port is determined to be <literal>open</literal>.
@@ -1624,24 +1624,33 @@ socket:close()
with <function>socket_object:close</function>&mdash;just like with <function>socket_object:close</function>&mdash;just like
with the connection-based network I/O.</para> with the connection-based network I/O.</para>
<para> <para>While receiving packets is important, sending them is certainly
Receiving raw packets is important, but sending them is a key feature as well. To accomplish this, NSE can a key feature as well. To accomplish this, NSE provides access to
access a wrapper around the sending at the IP and Ethernet layers. Raw packet writes do not use
<literal>libdnet</literal> library.<indexterm><primary>libdnet</primary></indexterm> Raw packet writes do not the same socket object as raw packet reads, so the <function>nmap.new_dnet</function>
use a standard socket object like reads do. Instead, call the function function is called to create the required object for sending. After
<function>nmap.new_dnet</function> to create a dnet object this, a raw socket or Ethernet interface handle can be opened for use.</para>
with ethernet sending methods. Then open an interface with the
<function>ethernet_open</function> method. Raw ethernet
frames can then be sent
with <function>ethernet_send</function>. When you're done,
close the ethernet handle
with <function>ethernet_close</function>.</para>
<para>Sometimes the easiest ways to understand complex APIs <para>Once the dnet object is created, the function <function>ip_open</function>
is by example. The <filename>sniffer-detect.nse</filename> can be called to initialize the object for IP sending. <function>ip_send</function>
script included with Nmap uses raw packet capture and sends the actual raw packet, which must start with the IPv4 header.
sending in an attempt to detect promiscuous-mode machines on The dnet object places no restrictions on which IP hosts may be sent
the network (those running sniffers).</para> to, so the same object may be used to send to many different hosts
while it is open. To close the raw socket, call <function>ip_close</function>.</para>
<para>For sending at a lower level than IP, NSE provides functions for
writing Ethernet frames. <function>ethernet_open</function> initializes
the dnet object for sending by opening an Ethernet interface. The raw
frame is sent with <function>ethernet_send</function>. To close the
handle, call <function>ethernet_close</function>.</para>
<para>Sometimes the easiest ways to understand complex APIs is by
example. The <filename>ipidseq.nse</filename> script included with
Nmap uses raw IP packets to test hosts for suitability for Nmap's
Idle Scan (<option>-sI</option>). The <filename>sniffer-detect.nse</filename>
script also included with Nmap uses raw Ethernet frames in an attempt
to detect promiscuous-mode machines on the network (those running
sniffers).</para>
</sect3> </sect3>
</sect2> </sect2>

View File

@@ -448,6 +448,34 @@ Port *get_port (lua_State *L, Target *target, Port *port, int index)
return p; return p;
} }
/* Generates an array of port data for the given host and leaves it on
* the top of the stack
*/
static int l_get_ports (lua_State *L)
{
static const char *op1[] = {"tcp", "udp", "sctp", NULL};
static const int states1[] = {IPPROTO_TCP, IPPROTO_UDP, IPPROTO_SCTP};
static const char *op2[] = {"open", "filtered", "unfiltered", "closed",
"open|filtered", "closed|filtered", NULL};
static const int states2[] = {PORT_OPEN, PORT_FILTERED, PORT_UNFILTERED,
PORT_CLOSED, PORT_OPENFILTERED, PORT_CLOSEDFILTERED};
Port *p = NULL, port;
Target *target = get_target(L, 1);
int protocol = states1[luaL_checkoption(L, 3, NULL, op1)];
int state = states2[luaL_checkoption(L, 4, NULL, op2)];
if (!lua_isnil(L, 2))
p = get_port(L, target, &port, 2);
if (!(p = target->ports.nextPort(p, &port, protocol, state))) {
lua_pushnil(L);
} else {
lua_newtable(L);
set_portinfo(L, target, p);
}
return 1;
}
/* this function can be called from lua to obtain the port state /* this function can be called from lua to obtain the port state
* of a port different from the one the script rule is matched * of a port different from the one the script rule is matched
* against * against
@@ -658,10 +686,17 @@ static int l_get_dns_servers (lua_State *L)
return 1; return 1;
} }
static int l_is_privileged(lua_State *L)
{
lua_pushboolean(L, o.isr00t);
return 1;
}
int luaopen_nmap (lua_State *L) int luaopen_nmap (lua_State *L)
{ {
static const luaL_reg nmaplib [] = { static const luaL_reg nmaplib [] = {
{"get_port_state", l_get_port_state}, {"get_port_state", l_get_port_state},
{"get_ports", l_get_ports},
{"set_port_state", l_set_port_state}, {"set_port_state", l_set_port_state},
{"set_port_version", l_set_port_version}, {"set_port_version", l_set_port_version},
{"new_socket", l_nsock_new}, {"new_socket", l_nsock_new},
@@ -676,6 +711,7 @@ int luaopen_nmap (lua_State *L)
{"fetchfile", l_fetchfile}, {"fetchfile", l_fetchfile},
{"timing_level", l_get_timing_level}, {"timing_level", l_get_timing_level},
{"get_dns_servers", l_get_dns_servers}, {"get_dns_servers", l_get_dns_servers},
{"is_privileged", l_is_privileged},
{NULL, NULL} {NULL, NULL}
}; };

View File

@@ -1876,15 +1876,19 @@ int l_get_ssl_certificate(lua_State *L)
/****************** DNET ******************************************************/ /****************** DNET ******************************************************/
static int l_dnet_open_ethernet(lua_State * L); static int l_dnet_open_ethernet(lua_State * L);
static int l_dnet_close_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_ethernet(lua_State * L);
static int l_dnet_open_ip(lua_State * L);
static int l_dnet_close_ip(lua_State * L);
static int l_dnet_send_ip(lua_State * L);
static luaL_reg l_dnet[] = { static luaL_reg l_dnet[] = {
{"ethernet_open", l_dnet_open_ethernet}, {"ethernet_open", l_dnet_open_ethernet},
{"ethernet_close", l_dnet_close_ethernet}, {"ethernet_close", l_dnet_close_ethernet},
{"ethernet_send", l_dnet_send_ethernet}, {"ethernet_send", l_dnet_send_ethernet},
{"ip_open", l_dnet_open_ip},
{"ip_close", l_dnet_close_ip},
{"ip_send", l_dnet_send_ip},
{NULL, NULL} {NULL, NULL}
}; };
@@ -1903,6 +1907,7 @@ struct l_dnet_udata
{ {
char *interface; char *interface;
eth_t *eth; eth_t *eth;
int sock; // raw ip socket
}; };
int l_dnet_new(lua_State * L) int l_dnet_new(lua_State * L)
@@ -1915,6 +1920,7 @@ int l_dnet_new(lua_State * L)
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
udata->interface = NULL; udata->interface = NULL;
udata->eth = NULL; udata->eth = NULL;
udata->sock = -1;
return 1; return 1;
} }
@@ -2055,3 +2061,147 @@ static int l_dnet_send_ethernet(lua_State * L)
eth_send(udata->eth, packet, packetsz); eth_send(udata->eth, packet, packetsz);
return 0; return 0;
} }
static int l_dnet_open_ip(lua_State * L)
{
l_dnet_udata *udata = (l_dnet_udata *) luaL_checkudata(L, 1, "dnet");
udata->sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (udata->sock == -1) {
lua_pushboolean(L, false);
lua_pushfstring(L, "Failed to open raw socket: %s (errno %d)", socket_strerror(errno), errno);
return 2;
}
broadcast_socket(udata->sock);
#ifndef WIN32
sethdrinclude(udata->sock);
#endif
lua_pushboolean(L, true);
return 1;
}
static int l_dnet_close_ip(lua_State * L)
{
l_dnet_udata *udata = (l_dnet_udata *) luaL_checkudata(L, 1, "dnet");
if (udata->sock == -1) {
lua_pushboolean(L, false);
lua_pushstring(L, "Raw socket all ready closed");
return 2;
}
close(udata->sock);
if (udata->eth && udata->interface) {
ldnet_eth_close_cached(udata->interface);
free(udata->interface);
udata->eth = NULL;
udata->interface = NULL;
}
lua_pushboolean(L, true);
return 1;
}
static int l_dnet_send_ip(lua_State * L)
{
l_dnet_udata *udata = (l_dnet_udata *) luaL_checkudata(L, 1, "dnet");
size_t packetsz = 0;
const char *packet = luaL_checklstring(L, 2, &packetsz);
char dev[16];
int ret;
if (udata->sock == -1) {
lua_pushboolean(L, false);
lua_pushstring(L, "Raw socket not open to send");
return 2;
}
if (packetsz < sizeof(struct ip)) {
lua_pushboolean(L, false);
lua_pushstring(L, "Won't send: IP packet too short");
return 2;
}
*dev = 0;
if ((o.sendpref & PACKET_SEND_ETH)) {
struct route_nfo route;
struct sockaddr_storage srcss, dstss, *nexthop;
struct sockaddr_in *srcsin = (struct sockaddr_in *) &srcss;
struct sockaddr_in *dstsin = (struct sockaddr_in *) &dstss;
struct ip *ip = (struct ip *) packet;
u8 dstmac[6];
eth_nfo eth;
/* build sockaddr for target from user packet and determine route */
memset(&dstss, 0, sizeof(dstss));
dstsin->sin_family = AF_INET;
dstsin->sin_addr.s_addr = ip->ip_dst.s_addr;
if (!route_dst(&dstss, &route))
goto usesock;
strncpy(dev, route.ii.devname, sizeof(dev));
if (route.ii.device_type != devt_ethernet)
goto usesock;
/* above we fallback to using the raw socket if we can't find an (ethernet)
* route to the host. From here on out it's ethernet all the way.
*/
/* build sockaddr for source from user packet to determine next hop mac */
memset(&srcss, 0, sizeof(srcss));
srcsin->sin_family = AF_INET;
srcsin->sin_addr.s_addr = ip->ip_src.s_addr;
if (route.direct_connect)
nexthop = &dstss;
else
nexthop = &route.nexthop;
if (!getNextHopMAC(route.ii.devfullname, route.ii.mac, &srcss, nexthop, dstmac)) {
lua_pushboolean(L, false);
lua_pushstring(L, "Failed to determine next hop MAC address");
return 2;
}
/* Use cached ethernet device, and use udata's eth and interface to keep
* track of if we're reusing the same device from the previous packet, and
* close the cached device if not.
*/
memset(&eth, 0, sizeof(eth));
memcpy(&eth.srcmac, route.ii.mac, sizeof(eth.srcmac));
memcpy(&eth.dstmac, dstmac, sizeof(eth.dstmac));
eth.ethsd = ldnet_eth_open_cached(dev);
if (!udata->eth) {
udata->eth = eth.ethsd;
udata->interface = strdup(route.ii.devname);
} else if (udata->eth != eth.ethsd) {
ldnet_eth_close_cached(udata->interface);
free(udata->interface);
udata->eth = eth.ethsd;
udata->interface = strdup(route.ii.devname);
}
ret = send_ip_packet(udata->sock, &eth, (u8 *) packet, packetsz);
} else {
usesock:
#ifdef WIN32
if (strlen(dev))
win32_warn_raw_sockets(dev);
#endif
ret = send_ip_packet(udata->sock, NULL, (u8 *) packet, packetsz);
}
if (ret == -1) {
lua_pushboolean(L, false);
lua_pushfstring(L, "Error while sending: %s (errno %d)", socket_strerror(errno), errno);
return 2;
}
lua_pushboolean(L, true);
return 1;
}

View File

@@ -31,6 +31,11 @@ function have_ssl()
-- @usage if nmap.verbosity() > 0 then ... end -- @usage if nmap.verbosity() > 0 then ... end
function verbosity() function verbosity()
--- Returns whether a script should be able to perform privileged operations
--
-- @return True if Nmap is running privileged, false otherwise.
function is_privileged()
--- Searches for the specified file and returns a string containing its path if --- Searches for the specified file and returns a string containing its path if
-- it is found and readable (to the process). -- it is found and readable (to the process).
-- --
@@ -73,6 +78,25 @@ function timing_level()
-- @usage p = nmap.get_port_state({ip="127.0.0.1"}, {number="80", protocol="tcp"}) -- @usage p = nmap.get_port_state({ip="127.0.0.1"}, {number="80", protocol="tcp"})
function get_port_state(host, port) function get_port_state(host, port)
--- Iterates over port tables matching protocol and state for a given host
--
-- This function takes a host table, previous port table, port protocol and
-- port state to return matching port tables on a host.
--
-- The first time you call this function, pass <code>nil</code> for the port
-- parameter to get the first matching port table. From then on, pass the
-- previous port table returned by this function to the port parameter for the
-- next matching port table.
--
-- @param host Host table, containing an <code>ip</code> field
-- @param port Port table, containing a <code>number</code> field; or <code>nil</code>
-- for first port
-- @param proto Port protocol, such as <code>"tcp"</code>
-- @param state Port state, such as <code>"open"</code>
-- @return Next port table for host, or <code>nil</code> when exhausted
-- @usage port = nmap.get_ports(host, port, "tcp", "open")
function get_ports(host, port, proto, state)
--- Sets the state of a port on a given host. --- Sets the state of a port on a given host.
-- --
-- Using this function, the final port state, reflected in Nmap's results, can -- Using this function, the final port state, reflected in Nmap's results, can
@@ -630,6 +654,26 @@ function ethernet_send(packet)
-- @usage dnet:ethernet_close() -- @usage dnet:ethernet_close()
function ethernet_close() function ethernet_close()
--- Opens a socket for raw IPv4 packet sending.
-- @see new_dnet
-- @usage dnet:ip_open()
function ip_open()
--- Sends a raw IPv4 packet.
--
-- The dnet object must be associated with a previously opened socket. The
-- packet must begin with an IP header. If there was no previous valid call
-- to <code>ip_open</code> an error is thrown.
-- @param packet An IP packet to send.
-- @see new_dnet
-- @usage dnet:ip_send(packet)
function ip_send(packet)
--- Closes a raw IPv4 socket.
-- @see new_dnet, ip_open
-- @usage dnet:ip_close()
function ip_close()
--- Writes to a log file. --- Writes to a log file.
-- --
-- Writes <code>string</code> to <code>file</code> ("stdout" or "stderr"). -- Writes <code>string</code> to <code>file</code> ("stdout" or "stderr").

247
scripts/ipidseq.nse Normal file
View File

@@ -0,0 +1,247 @@
description = [[
Classifies a host's IP ID sequence (e.g. test for Idle Scan suitability).
Sends six probes to obtain IP IDs from the target and classifies them
similiarly to Nmap's method. This is useful for finding suitable zombies
for Nmap's Idle Scan (-sI) as Nmap itself doesn't provide a way to scan
*for* these hosts.
]]
---
-- @usage
-- nmap --script ipidseq [--script-args probeport=port] target
-- @args probeport Set destination port to probe
-- @output
-- Host script results:
-- |_ipidseq: Incremental! [used port 80]
-- I also implemented this in Metasploit as auxiliary/scanner/ip/ipidseq, but
-- this NSE script was actually written first (unfortunately it only worked
-- with vanilla Nmap using dnet ethernet sending.. ugh)
--
-- Originally written 05/24/2008; revived 01/24/2010
author = "Kris Katterjohn <katterjohn[at]gmail.com>"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"safe", "discovery"}
require 'bin'
require 'packet'
local NUMPROBES = 6
--- Pcap callback
-- @return Destination and source IP addresses and TCP ports
local callback = function(size, layer2, layer3)
local ip = packet.Packet:new(layer3, layer3:len())
return bin.pack('AA=S=S', ip.ip_bin_dst, ip.ip_bin_src, ip.tcp_dport, ip.tcp_sport)
end
--- Updates a TCP Packet object
-- @param tcp The TCP object
local updatepkt = function(tcp)
tcp:tcp_set_sport(math.random(0x401, 0xffff))
tcp:tcp_set_seq(math.random(1, 0x7fffffff))
tcp:tcp_count_checksum(tcp.ip_len)
tcp:ip_count_checksum()
end
--- Create a TCP Packet object
-- @param host Host object
-- @param port Port number
-- @return TCP Packet object
local genericpkt = function(host, port)
local pkt = bin.pack("H",
"4500 002c 55d1 0000 8006 0000 0000 0000" ..
"0000 0000 0000 0000 0000 0000 0000 0000" ..
"6002 0c00 0000 0000 0204 05b4"
)
local tcp = packet.Packet:new(pkt, pkt:len())
tcp:ip_set_bin_src(host.bin_ip_src)
tcp:ip_set_bin_dst(host.bin_ip)
tcp:tcp_set_dport(port)
updatepkt(tcp)
return tcp
end
--- Classifies a series of IP ID numbers like get_ipid_sequence() in osscan2.cc
-- @param ipids Table of IP IDs
local ipidseqclass = function(ipids)
local diffs = {}
local allzeros = true
local allsame = true
local mul256 = true
local inc = true
if #ipids < 2 then
return "Unknown"
end
local i = 2
while i <= #ipids do
if ipids[i-1] ~= 0 or ipids[i] ~= 0 then
allzeros = false
end
if ipids[i-1] <= ipids[i] then
diffs[i-1] = ipids[i] - ipids[i-1]
else
diffs[i-1] = ipids[i] - ipids[i-1] + 65536
end
if #ipids > 2 and diffs[i-1] > 20000 then
return "Randomized"
end
i = i + 1
end
if allzeros then
return "All zeros"
end
i = 1
while i <= #diffs do
if diffs[i] ~= 0 then
allsame = false
end
if (diffs[i] > 1000) and ((diffs[i] % 256) ~= 0 or
((diffs[i] % 256) == 0 and diffs[i] > 25600)) then
return "Random Positive Increments"
end
if diffs[i] > 5120 or (diffs[i] % 256) ~= 0 then
mul256 = false
end
if diffs[i] >= 10 then
inc = false
end
i = i + 1
end
if allsame then
return "Constant"
end
if mul256 then
return "Broken incremental!"
end
if inc then
return "Incremental!"
end
return "Unknown"
end
--- Determines what port to probe
-- @param host Host object
local getport = function(host)
for _, k in ipairs({"ipidseq.probeport", "probeport"}) do
if nmap.registry.args[k] then
return tonumber(nmap.registry.args[k])
end
end
--local states = { "open", "closed", "unfiltered", "open|filtered", "closed|filtered" }
local states = { "open", "closed" }
local port = nil
for _, s in ipairs(states) do
port = nmap.get_ports(host, nil, "tcp", s)
if port then
break
end
end
if not port then
return nil
end
return port.number
end
--- Sets probe port number in registry
-- @param host Host object
-- @param port Port number
local setreg = function(host, port)
if not nmap.registry[host.ip] then
nmap.registry[host.ip] = {}
end
nmap.registry[host.ip]['ipidseqprobe'] = port
end
hostrule = function(host)
if not nmap.is_privileged() then
return false
end
if not host.interface then
return false
end
local port = getport(host)
if not port then
return false
end
setreg(host, port)
return true
end
action = function(host)
local i = 1
local ipids = {}
local sock = nmap.new_dnet()
local pcap = nmap.new_socket()
local port = nmap.registry[host.ip]['ipidseqprobe']
local saddr = packet.toip(host.bin_ip_src)
local daddr = packet.toip(host.bin_ip)
local try = nmap.new_try()
try(sock:ip_open())
try = nmap.new_try(function() sock:ip_close() end)
pcap:pcap_open(host.interface, 104, 0, callback, "tcp and dst host " .. saddr .. " and src host " .. daddr .. " and src port " .. port)
pcap:set_timeout(3000)
local tcp = genericpkt(host, port)
while i <= NUMPROBES do
try(sock:ip_send(tcp.buf))
pcap:pcap_register(bin.pack('AA=S=S', tcp.ip_bin_src, tcp.ip_bin_dst, tcp.tcp_sport, tcp.tcp_dport))
local status, len, _, pkt = pcap:pcap_receive()
if status then
table.insert(ipids, packet.u16(pkt, 4))
end
updatepkt(tcp)
i = i + 1
end
pcap:close()
sock:ip_close()
local output = ipidseqclass(ipids)
if nmap.debugging() > 0 then
output = output .. " [used port " .. port .. "]"
end
return output
end

View File

@@ -38,6 +38,7 @@ Entry { filename = "http-userdir-enum.nse", categories = { "discovery", "intrusi
Entry { filename = "http-vmware-path-vuln.nse", categories = { "default", "safe", "vuln", } } Entry { filename = "http-vmware-path-vuln.nse", categories = { "default", "safe", "vuln", } }
Entry { filename = "iax2-version.nse", categories = { "version", } } Entry { filename = "iax2-version.nse", categories = { "version", } }
Entry { filename = "imap-capabilities.nse", categories = { "default", "safe", } } Entry { filename = "imap-capabilities.nse", categories = { "default", "safe", } }
Entry { filename = "ipidseq.nse", categories = { "discovery", "safe", } }
Entry { filename = "irc-info.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "irc-info.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "ldap-brute.nse", categories = { "auth", "intrusive", } } Entry { filename = "ldap-brute.nse", categories = { "auth", "intrusive", } }
Entry { filename = "ldap-rootdse.nse", categories = { "discovery", "safe", } } Entry { filename = "ldap-rootdse.nse", categories = { "discovery", "safe", } }
@@ -79,7 +80,7 @@ Entry { filename = "smb-server-stats.nse", categories = { "discovery", "intrusiv
Entry { filename = "smb-system-info.nse", categories = { "discovery", "intrusive", } } Entry { filename = "smb-system-info.nse", categories = { "discovery", "intrusive", } }
Entry { filename = "smbv2-enabled.nse", categories = { "default", "safe", } } Entry { filename = "smbv2-enabled.nse", categories = { "default", "safe", } }
Entry { filename = "smtp-commands.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "smtp-commands.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "smtp-open-relay.nse", categories = { "demo", } } Entry { filename = "smtp-open-relay.nse", categories = { "discovery", "external", "intrusive", } }
Entry { filename = "smtp-strangeport.nse", categories = { "malware", "safe", } } Entry { filename = "smtp-strangeport.nse", categories = { "malware", "safe", } }
Entry { filename = "sniffer-detect.nse", categories = { "discovery", "intrusive", } } Entry { filename = "sniffer-detect.nse", categories = { "discovery", "intrusive", } }
Entry { filename = "snmp-brute.nse", categories = { "auth", "intrusive", } } Entry { filename = "snmp-brute.nse", categories = { "auth", "intrusive", } }
@@ -95,6 +96,7 @@ Entry { filename = "sql-injection.nse", categories = { "intrusive", "vuln", } }
Entry { filename = "ssh-hostkey.nse", categories = { "default", "intrusive", "safe", } } Entry { filename = "ssh-hostkey.nse", categories = { "default", "intrusive", "safe", } }
Entry { filename = "sshv1.nse", categories = { "default", "safe", } } Entry { filename = "sshv1.nse", categories = { "default", "safe", } }
Entry { filename = "ssl-cert.nse", categories = { "discovery", "safe", } } Entry { filename = "ssl-cert.nse", categories = { "discovery", "safe", } }
Entry { filename = "ssl-enum-ciphers.nse", categories = { "discovery", "intrusive", } }
Entry { filename = "sslv2.nse", categories = { "default", "safe", } } Entry { filename = "sslv2.nse", categories = { "default", "safe", } }
Entry { filename = "telnet-brute.nse", categories = { "auth", "intrusive", } } Entry { filename = "telnet-brute.nse", categories = { "auth", "intrusive", } }
Entry { filename = "upnp-info.nse", categories = { "default", "safe", } } Entry { filename = "upnp-info.nse", categories = { "default", "safe", } }

View File

@@ -2835,6 +2835,37 @@ bool setTargetNextHopMAC(Target *target) {
return false; return false;
} }
/* Like to getTargetNextHopMAC(), but for arbitrary hosts (not Targets) */
bool getNextHopMAC(char *iface, u8 *srcmac, struct sockaddr_storage *srcss,
struct sockaddr_storage *dstss, u8 *dstmac)
{
arp_t *a;
struct arp_entry ae;
/* Nmap's ARP cache */
if (NmapArpCache(ARPCACHE_GET, dstss, dstmac))
return true;
/* System ARP cache */
a = arp_open();
addr_ston((sockaddr *) dstss, &ae.arp_pa);
if (arp_get(a, &ae) == 0) {
NmapArpCache(ARPCACHE_SET, dstss, ae.arp_ha.addr_eth.data);
memcpy(dstmac, ae.arp_ha.addr_eth.data, 6);
arp_close(a);
return true;
}
arp_close(a);
/* Send ARP */
if (doArp(iface, srcmac, srcss, dstss, dstmac)) {
NmapArpCache(ARPCACHE_SET, dstss, dstmac);
return true;
}
return false;
}
/* Set a pcap filter */ /* Set a pcap filter */
void set_pcap_filter(const char *device, pcap_t *pd, const char *bpf, ...) { void set_pcap_filter(const char *device, pcap_t *pd, const char *bpf, ...) {
va_list ap; va_list ap;

View File

@@ -703,6 +703,9 @@ int setTargetMACIfAvailable(Target *target, struct link_header *linkhdr,
after an ARP scan if many directly connected machines are involved. */ after an ARP scan if many directly connected machines are involved. */
bool setTargetNextHopMAC(Target *target); bool setTargetNextHopMAC(Target *target);
bool getNextHopMAC(char *iface, u8 *srcmac, struct sockaddr_storage *srcss,
struct sockaddr_storage *dstss, u8 *dstmac);
int islocalhost(const struct in_addr * const addr); int islocalhost(const struct in_addr * const addr);
int isipprivate(const struct in_addr * const addr); int isipprivate(const struct in_addr * const addr);