summaryrefslogtreecommitdiffstats
path: root/scripts/targets-ipv6-multicast-echo.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/targets-ipv6-multicast-echo.nse')
-rw-r--r--scripts/targets-ipv6-multicast-echo.nse170
1 files changed, 170 insertions, 0 deletions
diff --git a/scripts/targets-ipv6-multicast-echo.nse b/scripts/targets-ipv6-multicast-echo.nse
new file mode 100644
index 0000000..adf3459
--- /dev/null
+++ b/scripts/targets-ipv6-multicast-echo.nse
@@ -0,0 +1,170 @@
+local coroutine = require "coroutine"
+local ipOps = require "ipOps"
+local nmap = require "nmap"
+local packet = require "packet"
+local stdnse = require "stdnse"
+local tab = require "tab"
+local table = require "table"
+local target = require "target"
+
+description = [[
+Sends an ICMPv6 echo request packet to the all-nodes link-local
+multicast address (<code>ff02::1</code>) to discover responsive hosts
+on a LAN without needing to individually ping each IPv6 address.
+]]
+
+---
+-- @usage
+-- ./nmap -6 --script=targets-ipv6-multicast-echo.nse --script-args 'newtargets,interface=eth0' -sL
+-- @output
+-- Pre-scan script results:
+-- | targets-ipv6-multicast-echo:
+-- | IP: 2001:0db8:0000:0000:0000:0000:0000:0001 MAC: 11:22:33:44:55:66 IFACE: eth0
+-- |_ Use --script-args=newtargets to add the results as targets
+-- @args newtargets If true, add discovered targets to the scan queue.
+-- @args targets-ipv6-multicast-echo.interface The interface to use for host discovery.
+
+author = {"David Fifield", "Xu Weilin"}
+
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+
+categories = {"discovery","broadcast"}
+
+
+prerule = function()
+ return nmap.is_privileged()
+end
+
+local function get_interfaces()
+ local interface_name = stdnse.get_script_args(SCRIPT_NAME .. ".interface")
+ or nmap.get_interface()
+
+ -- interfaces list (decide which interfaces to broadcast on)
+ local interfaces = {}
+ if interface_name then
+ -- single interface defined
+ local if_table = nmap.get_interface_info(interface_name)
+ if if_table and ipOps.ip_to_str(if_table.address) and if_table.link == "ethernet" then
+ interfaces[#interfaces + 1] = if_table
+ else
+ stdnse.debug1("Interface not supported or not properly configured.")
+ end
+ else
+ for _, if_table in ipairs(nmap.list_interfaces()) do
+ if ipOps.ip_to_str(if_table.address) and if_table.link == "ethernet" then
+ table.insert(interfaces, if_table)
+ end
+ end
+ end
+
+ return interfaces
+end
+
+local function single_interface_broadcast(if_nfo, results)
+ stdnse.debug1("Starting " .. SCRIPT_NAME .. " on " .. if_nfo.device)
+
+ local condvar = nmap.condvar(results)
+ local src_mac = if_nfo.mac
+ local src_ip6 = ipOps.ip_to_str(if_nfo.address)
+ local dst_mac = packet.mactobin("33:33:00:00:00:01")
+ local dst_ip6 = ipOps.ip_to_str("ff02::1")
+
+ ----------------------------------------------------------------------------
+ --Multicast echo ping probe
+
+ local dnet = nmap.new_dnet()
+ local pcap = nmap.new_socket()
+
+ local function catch ()
+ dnet:ethernet_close()
+ pcap:pcap_close()
+ end
+ local try = nmap.new_try(catch)
+
+ try(dnet:ethernet_open(if_nfo.device))
+ pcap:pcap_open(if_nfo.device, 128, false, "icmp6 and ip6[6:1] = 58 and ip6[40:1] = 129")
+
+ local probe = packet.Frame:new()
+ probe.mac_src = src_mac
+ probe.mac_dst = dst_mac
+ probe.ip_bin_src = src_ip6
+ probe.ip_bin_dst = dst_ip6
+ probe.echo_id = 5
+ probe.echo_seq = 6
+ probe.echo_data = "Nmap host discovery."
+ probe:build_icmpv6_echo_request()
+ probe:build_icmpv6_header()
+ probe:build_ipv6_packet()
+ probe:build_ether_frame()
+
+ try(dnet:ethernet_send(probe.frame_buf))
+
+ pcap:set_timeout(1000)
+ local pcap_timeout_count = 0
+ local nse_timeout = 5
+ local start_time = nmap:clock()
+ local cur_time = nmap:clock()
+
+ repeat
+ local status, length, layer2, layer3 = pcap:pcap_receive()
+ cur_time = nmap:clock()
+ if not status then
+ pcap_timeout_count = pcap_timeout_count + 1
+ else
+ local reply = packet.Frame:new(layer2..layer3)
+ if reply.mac_dst == src_mac then
+ local target_str = reply.ip_src
+ if not results[target_str] then
+ if target.ALLOW_NEW_TARGETS then
+ target.add(target_str)
+ end
+ results[#results + 1] = { address = target_str, mac = stdnse.format_mac(reply.mac_src), iface = if_nfo.device }
+ results[target_str] = true
+ end
+ end
+ end
+ until pcap_timeout_count >= 2 or cur_time - start_time >= nse_timeout
+
+ dnet:ethernet_close()
+ pcap:pcap_close()
+
+ condvar("signal")
+end
+
+local function format_output(results)
+ local output = tab.new()
+
+ for _, record in ipairs(results) do
+ tab.addrow(output, "IP: " .. record.address, "MAC: " .. record.mac, "IFACE: " .. record.iface)
+ end
+ if #results > 0 then
+ output = { tab.dump(output) }
+ if not target.ALLOW_NEW_TARGETS then
+ output[#output + 1] = "Use --script-args=newtargets to add the results as targets"
+ end
+ return stdnse.format_output(true, output)
+ end
+end
+
+action = function()
+ local threads = {}
+ local results = {}
+ local condvar = nmap.condvar(results)
+
+ for _, if_nfo in ipairs(get_interfaces()) do
+ -- create a thread for each interface
+ local co = stdnse.new_thread(single_interface_broadcast, if_nfo, results)
+ threads[co] = true
+ end
+
+ repeat
+ for thread in pairs(threads) do
+ if coroutine.status(thread) == "dead" then threads[thread] = nil end
+ end
+ if ( next(threads) ) then
+ condvar "wait"
+ end
+ until next(threads) == nil
+
+ return format_output(results)
+end