description = [[ Multicast invalid hop-by-hop options ping. Do a very fast host discovery on link-local IPv6 network. ]] --- -- @usage -- ./nmap -6 --script=multicast_invalid_hopbyhop_exheader.nse --script-args 'newtargets,interface=eth0,ipv6=2001:da8:215:3320:223:aeff:fe5d:3b10' -sP -- @args newtargets If true, add discovered targets to the scan queue. -- @args interface The interface to use for host discovery. -- @args ipv6.src The source IPv6 address in the probe packets. author = "David and Weilin" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery"} require 'nmap' require 'target' require 'packet' prerule = function() return nmap.is_privileged() and (stdnse.get_script_args("interface") or nmap.get_interface()) end catch = function() dnet:ethernet_close() pcap:pcap_close() end try = nmap.new_try(catch) --- Get the destination's MAC address from the ethernet header. local function get_dst_mac(layer2) return string.sub(layer2,1,6) end --- Get the source IPv6 address from the IPv6 header. local function get_src_ip6(layer3) return string.sub(layer3,9,24) end local function get_ipv6_interface_info_by_name(if_name) local ifaces = nmap.list_interfaces() local iface local if_nfo for _,iface in pairs(ifaces) do if if_name == iface.device and (#iface.address>15 or string.find(iface.address, "::")) then if_nfo = iface return if_nfo end end return nil end action = function() local if_name = stdnse.get_script_args("interface") or nmap.get_interface() local dnet = nmap.new_dnet() local pcap = nmap.new_socket() try(dnet:ethernet_open(if_name)) pcap:pcap_open(if_name, 128, false, "icmp6 and ip6[6:1] = 58 and ip6[40:1] = 4") local if_nfo = get_ipv6_interface_info_by_name(if_name) local src_mac = if_nfo.mac local src_ip6 = packet.ipv6tobin(stdnse.get_script_args("ipv6.src")) or packet.ipv6tobin(if_nfo.address) local dst_mac = packet.mactobin("33:33:00:00:00:01") local dst_ip6 = packet.ipv6tobin("ff02::1") local probe = packet.Packet:new() probe.mac_src = src_mac probe.mac_dst = dst_mac probe.ip6_src = src_ip6 probe.ip6_dst = dst_ip6 probe:build_icmpv6_echo_request() probe:build_icmpv6_header() probe:build_invalid_extension_header(packet.IPV6_HOPBYHOP_OPTION) probe:build_ipv6_packet() probe:build_ether_frame() try(dnet:ethernet_send(probe.buf)) local addr_set = {} 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 elseif get_dst_mac(layer2) == src_mac then local target_addr = get_src_ip6(layer3) if not addr_set[target_addr] then addr_set[target_addr] = true local target_str = packet.toipv6(target_addr) target.add(target_str) end end until pcap_timeout_count >= 2 or cur_time - start_time >= nse_timeout dnet:ethernet_close() pcap:pcap_close() return true end