diff --git a/CHANGELOG b/CHANGELOG index efd7fd9da..3428c265f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,10 @@ #Nmap Changelog ($Id$); -*-text-*- +o [GH#2541] UDP port scan (-sU) and version scan (-sV) now both use the same + data source, nmap-service-probes, for data payloads. Previously, the + nmap-payloads file was used for port scan. Port scan responses will be used + to kick-start the version matching process. [Daniel Miller] + o Nmap's service scan (-sV) can now probe the UDP service behind a DTLS tunnel, the same as it already does for TCP services with SSL/TLS encryption. The DTLSSessionReq probe has had its rarity lowered to 2 to allow it to be sent diff --git a/Target.cc b/Target.cc index 538b6f73d..3a257dd08 100644 --- a/Target.cc +++ b/Target.cc @@ -145,6 +145,11 @@ void Target::FreeInternal() { } if (FPR) delete FPR; + for (std::vector::iterator it=earlySvcResponses.begin(); + it != earlySvcResponses.end(); it++) { + free(*it); + } + earlySvcResponses.clear(); } /* Creates a "presentation" formatted string out of the IPv4/IPv6 address. diff --git a/Target.h b/Target.h index 024b2dd85..14fd7a265 100644 --- a/Target.h +++ b/Target.h @@ -83,6 +83,7 @@ class FingerPrintResults; #include #include +#include #include /* time_t */ #ifndef INET6_ADDRSTRLEN @@ -116,6 +117,12 @@ struct TracerouteHop { } }; +struct EarlySvcResponse { + probespec pspec; + int len; + u8 data[1]; +}; + class Target { public: /* For now ... TODO: a lot of the data members should be made private */ Target(); @@ -248,6 +255,7 @@ class Target { enum dist_calc_method distance_calculation_method; FingerPrintResults *FPR; /* FP results get by the OS scan system. */ PortList ports; + std::vector earlySvcResponses; int weird_responses; /* echo responses from other addresses, Ie a network broadcast address */ int flags; /* HOST_UNKNOWN, HOST_UP, or HOST_DOWN. */ diff --git a/nmap-payloads b/nmap-payloads deleted file mode 100644 index 133559eb8..000000000 --- a/nmap-payloads +++ /dev/null @@ -1,502 +0,0 @@ -# Nmap nmap payload database -*- mode: fundamental; -*- -# $Id$ -# -# These payloads are sent with every host discovery or port scan probe -# by default. This database should only include payloads that are -# unlikely to crash services, trip IDS alerts, or change state on the -# server. The idea behind these is to evoke a response using a payload. -# Some of them are taken from nmap-service-probes. -# -# This collection of data is (C) 1996-2022 by Nmap Software LLC. It -# is distributed under the Nmap Public Source license as provided in -# the LICENSE file of the source distribution or at -# https://nmap.org/npsl/. Note that this free license does not allow -# incorporation of Nmap or its data files within proprietary -# software. We sell a separate Nmap OEM for that as described -# (including pricing) at https://nmap.org/npsl/. -# -# Each entry begins with a protocol (only "udp" is supported) followed -# by a comma-separated list of ports, followed by one or more quoted -# strings containing the payload. These elements may be broken across -# several lines. For future expansion, additional keywords may follow -# the payload data. Any data following one of these keywords must be on -# the same line as the keyword so that unknown keywords can be ignored -# by the parser. Currently this file contains some entries with the -# "source" keyword to specify a desired source port, but it is not -# honored by Nmap. -# -# Multiple payloads may be defined for a single protocol and port, in -# which case they will be all be sent concurrently. There is a limit -# of 255 payloads per port. -# -# Lines longer than 1024 characters will be ignored. -# -# Example: -# udp 1234 "payloaddatapayloaddata" -# "payloaddatapayloaddata" -# source 5678 - -# GenericLines. Use for the echo service. -udp 7 "\x0D\x0A\x0D\x0A" -# DNSStatusRequest -# Sent for TFTP (69) as well due to its ability to provoke an error response -udp 53,69,5353,26198 "\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00" -# DNS VER -udp 53,5353,26198 - "\x77\x77\x01\x00\x00" - "\x01\x00\x00\x00\x00\x00\x00\x07version\x04bind\x00\x00\x10\x00\x03" - -# DHCP INFORM -udp 67 - "\x01\x01\x06\x00" - "\x01\x23\x45\x67\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x35\xd4\xd8\x51\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x63\x82\x53\x63\x35\x01" - "\x08\xff" - -# TFTP GET -udp 69 "\x00\x01r7tftp.txt\x00octet\x00" - -# QUIC packet with unsupported version Q999 -# Also found on 443, but need to check whether DTLS or QUIC is more prevalent -udp 80 "\r12345678Q999\x00" -# RPCCheck -udp 111 - "\x72\xFE\x1D\x13\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x86\xA0" - "\x00\x01\x97\x7C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" -# ONCRPC CALL -udp 111,2049,4045,32768-65535 - "\x3e\xec\xe3\xca\x00\x00\x00\x00\x00\x00\x00\x02\x00" - "\xbc\x61\x4e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" -# NTPRequest -udp 123 - "\xE3\x00\x04\xFA\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\xC5\x4F\x23\x4B\x71\xB1\x52\xF3" -# NTP REQ -udp 123 - "\xd9\x00\x0a\xfa\x00\x00\x00" - "\x00\x00\x01\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6" - "\xf1\x5e\xdb\x78\x00\x00\x00" -# DCERPC CALL -udp 135,1025-1199 - "\x05\x00\x0b\x03\x10\x00\x00\x00\x48\x00" - "\x00\x00\x01\x00\x00\x00\xb8\x10\xb8\x10\x00\x00\x00\x00\x01\x00\x00" - "\x00\x00\x00\x01\x00\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67" - "\x89\xab\xcd\xef\xe7\x03\x00\x00\xfe\xdc\xba\x98\x76\x54\x32\x10\x01" - "\x23\x45\x67\x89\xab\xcd\xef\xe7\x03\x00\x00" -# NBTStat -udp 137 - "\x80\xF0\x00\x10\x00\x01\x00\x00\x00\x00\x00\x00" - "\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00\x21\x00\x01" -# CIFS NS NAME QUERY UC -udp 137 - "\x01\x91\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" - "\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00\x21\x00\x01" -# CIFS NS NAME QUERY BC -udp 137 - "\x01\x91\x00\x10\x00\x01\x00\x00\x00\x00\x00\x00" - "\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x00\x00\x21\x00\x01" -# SNMPv3GetRequest -udp 161,260,3401 - "\x30\x3A\x02\x01\x03\x30\x0F\x02\x02\x4A\x69\x02\x03\x00\xFF\xE3" - "\x04\x01\x04\x02\x01\x03\x04\x10\x30\x0E\x04\x00\x02\x01\x00\x02" - "\x01\x00\x04\x00\x04\x00\x04\x00\x30\x12\x04\x00\x04\x00\xA0\x0C" - "\x02\x02\x37\xF0\x02\x01\x00\x02\x01\x00\x30\x00" -# SNMP PUBLIC WALK -udp 161,260,3401 - "\x30\x1f\x02\x01\x00\x04\x06public\xa1\x12\x02\x01\x00\x02" - "\x01\x00\x02\x01\x00\x30\x07\x30\x05\x06\x01\x00\x05\x00" - -# Sqlping - disabled because it trips a Snort rule with SID 2049 -# ("MS-SQL ping attempt"). -# udp 1434 "\x02" - -# xdmcp - X Display Manager Control Protocol. Version 1, packet type -# Query (2), no authorization names. We expect a Willing or Unwilling -# packet in reply. -# http://cgit.freedesktop.org/xorg/doc/xorg-docs/plain/hardcopy/XDMCP/xdmcp.PS.gz -udp 177 "\x00\x01\x00\x02\x00\x01\x00" - -# Connectionless LDAP - used by Microsoft Active Directory -udp 389 - "\x30\x84\x00\x00\x00\x2d\x02\x01\x07\x63\x84\x00\x00\x00\x24\x04\x00" - "\x0a\x01\x00\x0a\x01\x00\x02\x01\x00\x02\x01\x64\x01\x01\x00\x87\x0b" - "objectClass0\x84\x00\x00\x00\x00" - - -# svrloc -udp 427 - "\x02\x01\x00\x006 \x00\x00\x00\x00\x00\x01\x00\x02en\x00\x00\x00\x15" - "service:service-agent\x00\x07default\x00\x00\x00\x00" - -# DTLS -udp 443,853,3391,4433,4740,5349,5684,5868,6514,6636,8232,10161,10162,12346,12446,12546,12646,12746,12846,12946,13046 - # DTLS 1.0, length 52 - "\x16\xfe\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x36" - # ClientHello, length 40, sequence 0, offset 0 - "\x01\x00\x00\x2a\x00\x00\x00\x00\x00\x00\x00\x2a" - # DTLS 1.2 - "\xfe\xfd" - # Random - "\x00\x00\x00\x00\x7c\x77\x40\x1e\x8a\xc8\x22\xa0\xa0\x18\xff\x93" - "\x08\xca\xac\x0a\x64\x2f\xc9\x22\x64\xbc\x08\xa8\x16\x89\x19\x3f" - # Session id length 0, cookie length 0 - "\x00\x00" - # Cipher suites, mandatory TLS_RSA_WITH_AES_128_CBC_SHA - "\x00\x02\x00\x2f" - # Compressors (NULL) - "\x01\x00" - -# Internet Key Exchange version 1, phase 1 Main Mode. We offer every -# combination of (DES, 3DES) and (MD5, SHA) in the hope that one of them will -# be acceptable. Because we use a fixed cookie, we set the association lifetime -# to 1 second to reduce the chance that repeated probes will look like -# retransmissions (and therefore not get a response). This payload comes from -# ike-scan --lifetime 1 --cookie 0011223344556677 --trans=5,2,1,2 --trans=5,1,1,2 --trans=1,2,1,2 --trans=1,1,1,2 -# We expect another phase 1 message in response. This payload works better with -# a source port of 500 or a randomized initiator cookie. -udp 500 - # Initiator cookie 0x0011223344556677, responder cookie 0x0000000000000000. - "\x00\x11\x22\x33\x44\x55\x66\x77\x00\x00\x00\x00\x00\x00\x00\x00" - # Version 1, Main Mode, flags 0x00, message ID 0x00000000, length 192. - "\x01\x10\x02\x00\x00\x00\x00\x00\x00\x00\x00\xC0" - # Security Association payload, length 164, IPSEC, IDENTITY. - "\x00\x00\x00\xA4\x00\x00\x00\x01\x00\x00\x00\x01" - # Proposal 1, length 152, ISAKMP, 4 transforms. - "\x00\x00\x00\x98\x01\x01\x00\x04" - # Transform 1, 3DES-CBC, SHA, PSK, group 2. - "\x03\x00\x00\x24\x01\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02" - "\x80\x03\x00\x01\x80\x04\x00\x02" - "\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01" - # Transform 2, 3DES-CBC, MD5, PSK, group 2. - "\x03\x00\x00\x24\x02\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x01" - "\x80\x03\x00\x01\x80\x04\x00\x02" - "\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01" - # Transform 3, DES-CBC, SHA, PSK, group 2. - "\x03\x00\x00\x24\x03\x01\x00\x00\x80\x01\x00\x01\x80\x02\x00\x02" - "\x80\x03\x00\x01\x80\x04\x00\x02" - "\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01" - # Transform 4, DES-CBC, MD5, PSK, group 2. - "\x00\x00\x00\x24\x04\x01\x00\x00\x80\x01\x00\x01\x80\x02\x00\x01" - "\x80\x03\x00\x01\x80\x04\x00\x02" - "\x80\x0B\x00\x01\x00\x0C\x00\x04\x00\x00\x00\x01" -source 500 -# IPSEC START -udp 500,4500 - "\x31\x27\xfc" - "\xb0\x38\x10\x9e\x89\x00\x00\x00\x00\x00\x00\x00\x00\x01\x10\x02\x00" - "\x00\x00\x00\x00\x00\x00\x00\xcc\x0d\x00\x00\x5c\x00\x00\x00\x01\x00" - "\x00\x00\x01\x00\x00\x00\x50\x01\x01\x00\x02\x03\x00\x00\x24\x01\x01" - "\x00\x00\x80\x01\x00\x05\x80\x02\x00\x02\x80\x04\x00\x02\x80\x03\x00" - "\x03\x80\x0b\x00\x01\x00\x0c\x00\x04\x00\x00\x0e\x10\x00\x00\x00\x24" - "\x02\x01\x00\x00\x80\x01\x00\x05\x80\x02\x00\x01\x80\x04\x00\x02\x80" - "\x03\x00\x03\x80\x0b\x00\x01\x00\x0c\x00\x04\x00\x00\x0e\x10\x0d\x00" - "\x00\x18\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4" - "\x61\x00\x00\x00\x04\x0d\x00\x00\x14\x40\x48\xb7\xd5\x6e\xbc\xe8\x85" - "\x25\xe7\xde\x7f\x00\xd6\xc2\xd3\x0d\x00\x00\x14\x90\xcb\x80\x91\x3e" - "\xbb\x69\x6e\x08\x63\x81\xb5\xec\x42\x7b\x1f\x00\x00\x00\x14\x26\x24" - "\x4d\x38\xed\xdb\x61\xb3\x17\x2a\x36\xe3\xd0\xcf\xb8\x19" -source 500 - -# Routing Information Protocol version 1. Special-case request for the entire -# routing table (address family 0, address 0.0.0.0, metric 16). RFC 1058, -# section 3.4.1. -udp 520 - "\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x10" - -# RMCP ASF ping -udp 623 - "\x06\x00\xff\x06" # RMCP version 6, sequence 0xff, normal RMCP class ASF - "\x00\x00\x11\xbe" # IAN ASF code 4542 - "\x80\x00\x00\x00" # payload-less ASF presence ping - -# IPMI -# RMCP Get Channel Auth Capabilities -udp 623 - "\x06\x00\xff\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x20\x18" - "\xc8\x81\x00\x38\x8e\x04\xb5" - -# serialnumberd. This service runs on Mac OS X Server. This probe -# requests the serial number of another server. In response we expect a -# packet starting with "SNRESPS:", followed by some data whose purpose -# is not known. -udp 626 "SNQUERY: 127.0.0.1:AAAAAA:xsvr" - -# OpenVPN P_CONTROL_HARD_RESET_CLIENT_V2 -# Byte 0; 0x38 opcode -# Byte 1-8: Session ID, random -# Byte 9: Message packet-id array length (0) -# Byte 10-13: Message packet-id (0) -udp 1194 "8d\xc1x\x01\xb8\x9b\xcb\x8f\0\0\0\0\0" -# OpenVPN when in PKI mode and without the "HMAC Firewall" setting enabled -# (tls-auth) should respond to the following probe, which is -# 0x38<8 random bytes><4 null bytes> -udp 1194 - "\x38\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00\x00\x00" - -# Citrix MetaFrame application browser service -# Original idea from http://sh0dan.org/oldfiles/hackingcitrix.html -# Payload contents copied from Wireshark capture of Citrix Program -# Neighborhood client application. The application uses this payload to -# locate Citrix servers on the local network. Response to this probe is -# a 48 byte UDP payload as shown here: -# -# 0000 30 00 02 31 02 fd a8 e3 02 00 06 44 c0 a8 80 55 -# 0010 00 00 00 00 00 00 00 00 00 00 00 00 02 00 06 44 -# 0020 c0 a8 80 56 00 00 00 00 00 00 00 00 00 00 00 00 -# -# The first 12 bytes appear to be the same in all responses. -# -# Bytes 0x00 appears to be a packet length field -# Bytes 0x0C - 0x0F are the IP address of the server -# Bytes 0x10 - 0x13 may vary, 0x14 - 0x1F do not appear to -# Bytes 0x20 - 0x23 are the IP address of the primary system in a server farm -# configuration -# Bytes 0x24 - 0x27 can vary, 0x28 - 0x2F do not appear to -udp 1604 - "\x1e\x00\x01\x30\x02\xfd\xa8\xe3\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - -# RADIUS Access-Request. This is a degenerate packet with no username or -# password; we expect an Access-Reject in response. The Identifier and Request -# Authenticator are both 0. It was generated by running -# echo 'User-Password = ""' | radclient auth "" -# and then manually stripping out the password. -# -# Section 2 of the RFC says "A request from a client for which the -# RADIUS server does not have a shared secret MUST be silently -# discarded." So this payload only works when the server is configured -# (or misconfigured) to know the scanning machine as a client. -# -# RFC 2865: "The early deployment of RADIUS was done using UDP port -# number 1645, which conflicts with the "datametrics" service. The -# officially assigned port number for RADIUS is 1812. -udp 1645,1812 - "\x01\x00\x00\x14" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - -# L2TP ICRQ -udp 1701 - "\xc8\x02" - "\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x80\x08\x00\x00\x00\x00\x00" - "\x01\x80\x08\x00\x00\x00\x02\x01\x00\x80\x0e\x00\x00\x00\x07" - "nxp-scan\x80\x0a\x00\x00\x00\x03\x00\x00\x00\x03\x80" - "\x08\x00\x00\x00\x09\x00\x00" - -# UPNP MSEARCH -udp 1900 - "M-SEARCH * HTTP/1.1\r\nHost: 239.255.255.250:1900\r\n" - "Man: \"ssdp:discover\"\r\nMX: 5\r\nST: ssdp:all\r\n\r\n" - -# NFS version 2, RFC 1831. XID 0x00000000, program 100003 (NFS), procedure -# NFSPROC_NULL (does nothing, see section 2.2.1), null authentication (see -# section 9.1). -udp 2049 - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x86\xA3" - "\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - -# GPRS Tunneling Protocol (GTP) -udp 2123,2152 -# GTPv1, protocol 1 -"\x32" -# EchoRequest -"\x01" -# message length -"\x00\x04" -# Tunnel endpoint identifier -"\x00\x00\x42\x00" -# sequence number -"\x13\x37" -# N-PDU number -"\x00" -# next extension header type -"\x00" - -# GPRS Tunneling Protocol (GTP) "prime" v2 -# This same packet can be used for GTP v2 on ports 2123 and 2152 if you change -# the first byte from \x4e to \x40 -udp 3386 -# GTP'v2 -"\x4e" -# EchoRequest -"\x01" -# message length -"\x00\x04" -# sequence number -"\xde\xfe\xc8\x00" - -# Freelancer game server status query -# http://sourceforge.net/projects/gameq/ -# (relevant files: games.ini, packets.ini, freelancer.php) -udp 2302 "\x00\x02\xf1\x26\x01\x26\xf0\x90\xa6\xf0\x26\x57\x4e\xac\xa0\xec\xf8\x68\xe4\x8d\x21" - -# Apple Remote Desktop (ARD) -udp 3283 "\0\x14\0\x01\x03" - -# STUN Binding request, see RFC 5389 Section 6 -# message type = 0x001, Binding (see Section 18.1) -# message length = 0 -# magic cookie = 0x2112a442 -# transaction ID = "\x00"*12 -udp 3478 "\x00\x01\x00\x00\x21\x12\xa4\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - -# Sun Service Tag Discovery protocol (stdiscover) -# http://arc.opensolaris.org/caselog/PSARC/2006/638/stdiscover_protocolv2.pdf -# Would work better with a varying cookie; the second and later sends of this -# probe will be interpreted as resends by the server and will be ignored. -udp 6481 "[PROBE] 0000" - -# NAT-PMP external IP address request. See section 3.2 of -# http://files.dns-sd.org/draft-cheshire-nat-pmp.txt. -udp 5351 "\x00\x00" - -# DNS Service Discovery (DNS-SD) service query, as used in Zeroconf. -# Transaction ID 0x0000, flags 0x0000, 1 question: PTR query for -# _services._dns-sd._udp.local. If the remote host supports DNS-SD it will send -# back a list of all its services. This is the same as a packet capture of -# dns-sd -B _services._dns-sd._udp . -# See section 9 of -# http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt. -# This first probe is a QU probe, meaning a unicast response is desired -udp 5353 - "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" - "\x09_services\x07_dns-sd\x04_udp\x05local\x00\x00\x0C\x80\x01" -# This second probe is a QM probe, meaning a unicast response is desired -udp 5353 - "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" - "\x09_services\x07_dns-sd\x04_udp\x05local\x00\x00\x0C\x00\x01" - -# PCANY STATUS -udp 5632 "ST" - -# CoAP GET .well-known/core -udp 5683 "@\x01\x01\xce\xbb.well-known\x04core" - -# UT2K PING -udp 7777 "None\x00" - -# Ubiquiti Discovery Service - v1 -udp 10001 "\x01\x00\x00\x00" - -# Amanda backup service noop request. I think that this does nothing on the -# server but only asks it to send back its feature list. In reply we expect an -# ACK or (more likely) an ERROR. I couldn't find good online documentation of -# the Amanda network protocol. There is parsing code in the Amanda source at -# common-src/security-util.c. This is based on a packet capture of -# amcheck -udp 10080 - "Amanda 2.6 REQ HANDLE 000-00000000 SEQ 0\n" - "SERVICE noop\n" - -# VxWorks Wind River Debugger -udp 17185 -# Random XID -"\x00\x00\x00\x00" -# RPC version 2 procedure call -"\x00\x00\x00\x00\x00\x00\x00\x02" -# WDB version 1 -"\x55\x55\x55\x55\x00\x00\x00\x01" -# WDB_TARGET_PING -"\x00\x00\x00\x00" -# RPC Auth NULL -"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" -# Checksum -"\xff\xff\x55\x13" -# WDB wrapper (length and sequence number) -"\x00\x00\x00\x30\x00\x00\x00\x01" -# Empty data? -"\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00" -# VXWORKS DEBUG (alternative?) -udp 17185 - "\x72\x37\x72\x37\x00\x00\x00" - "\x00\x00\x00\x00\x02\x55\x55\x55\x55\x00\x00\x00\x01\x00\x00\x00\x01" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff" - "\xff\x55\x10\x00\x00\x00\x3c\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00" - "\x00\x00\x00\x00\x00\x00" - -# Quake 2 and Quake 3 game servers (and servers of derived games like Nexuiz). -# Gets game information from the server (see probe responses in -# nmap-service-probes). These services typically run on a base port or a -# few numbers higher. -# Quake 2. Typical ports: 27910-27914. -udp 27910-27914 "\xff\xff\xff\xffstatus" -# Quake 3. Typical ports: -# 26000-26004: Nexuiz -# 27960-27964: Various games -# 30720-30724: Tremulous -# 44400: Warsow -udp 26000-26004,27960-27964,30720-30724,44400 "\xff\xff\xff\xffgetstatus" - -# Murmur 1.2.X (Mumble server) -# UDP ping. "abcdefgh" is an identifier. See -# http://mumble.sourceforge.net/Protocol. -udp 64738 "\x00\x00\x00\x00abcdefgh" - -# Ventrilo 2.1.2+ -# UDP general status request (encrypted). -# See http://aluigi.altervista.org/papers.htm#ventrilo -udp 3784 -"\x01\xe7\xe5\x75\x31\xa3\x17\x0b\x21\xcf\xbf\x2b\x99\x4e\xdd\x19\xac\xde\x08\x5f\x8b\x24\x0a\x11\x19\xb6\x73\x6f\xad\x28\x13\xd2\x0a\xb9\x12\x75" - -# Kademlia (kad) as used by various P2P applications. Send a Kademlia ping -# 4665, 4666, 4672, 6429: eDonkey/eMule and variants -udp 4665,4666,4672,6429 "\xE4\x60" - -# TeamSpeak 2 -# UDP login request -# See http://wiki.wireshark.org/TeamSpeak2 -udp 8767 -"\xf4\xbe\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x002x\xba\x85\tTeamSpeak\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\nWindows XP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00 \x00<\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08nickname\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - -# TS3INIT1 -udp 9987 -"TS3INIT1\x00\x65\x00\x00\x88\x0a\x39\x7b\x0f\x00\x5b\x55\x72\xef\xdc\x78\x32\x6b\x00\x00\x00\x00\x00\x00\x00\x00" - -# TeamSpeak 3 -# UDP login request (encrypted) -# http://seclists.org/nmap-dev/2013/q3/72 -udp 9987 -"\x05\xca\x7f\x16\x9c\x11\xf9\x89\x00\x00\x00\x00\x02\x9d\x74\x8b\x45\xaa\x7b\xef\xb9\x9e\xfe\xad\x08\x19\xba\xcf\x41\xe0\x16\xa2\x32\x6c\xf3\xcf\xf4\x8e\x3c\x44\x83\xc8\x8d\x51\x45\x6f\x90\x95\x23\x3e\x00\x97\x2b\x1c\x71\xb2\x4e\xc0\x61\xf1\xd7\x6f\xc5\x7e\xf6\x48\x52\xbf\x82\x6a\xa2\x3b\x65\xaa\x18\x7a\x17\x38\xc3\x81\x27\xc3\x47\xfc\xa7\x35\xba\xfc\x0f\x9d\x9d\x72\x24\x9d\xfc\x02\x17\x6d\x6b\xb1\x2d\x72\xc6\xe3\x17\x1c\x95\xd9\x69\x99\x57\xce\xdd\xdf\x05\xdc\x03\x94\x56\x04\x3a\x14\xe5\xad\x9a\x2b\x14\x30\x3a\x23\xa3\x25\xad\xe8\xe6\x39\x8a\x85\x2a\xc6\xdf\xe5\x5d\x2d\xa0\x2f\x5d\x9c\xd7\x2b\x24\xfb\xb0\x9c\xc2\xba\x89\xb4\x1b\x17\xa2\xb6" - -# Memcached -# version request (shorter response than stats) -# https://github.com/memcached/memcached/blob/master/doc/protocol.txt -udp 11211 -"\0\x01\0\0\0\x01\0\0version\r\n" - -# Steam, typically using a port in 27015-27030. Send a "Source Engine query" -udp 27015-27030 - "\xff\xff\xff\xffTSource Engine Query\x00" - -# TRIN00 UNIX PING -udp 27444 "png l44adsl" - -# BO PING -udp 31337 - "\xce\x63\xd1\xd2\x16\xe7\x13\xcf\x38" - "\xa5\xa5\x86\xb2\x75\x4b\x99\xaa\x32\x58" - -# TRIN00 WIN PING -udp 34555 "png []..Ks" - -# Beckhoff ADS discovery request -# https://github.com/ONE75/adsclient/blob/master/src/AdsClient.Finder/DeviceFinder.cs#L49-L64 -udp 48899 -"\x03\x66\x14\x71\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x01\x10\x27\x00\x00\x00\x00" diff --git a/nmap-service-probes b/nmap-service-probes index 17fe27db3..1f0737544 100644 --- a/nmap-service-probes +++ b/nmap-service-probes @@ -12444,7 +12444,7 @@ match dtls m|^\x15\xfe[\xfd\xff]\0\0\0\0\0\0\0\0..\x02.\0\0\0\0\0| ##############################NEXT PROBE############################## Probe UDP DNSVersionBindReq q|\0\x06\x01\0\0\x01\0\0\0\0\0\0\x07version\x04bind\0\0\x10\0\x03| rarity 1 -ports 53,1967,2967 +ports 53,1967,2967,26198 # Matches here have been grouped by product and roughly ordered based on prevalence # on the Internet @@ -12770,7 +12770,7 @@ match ssl m|^\x15\x03[\x00-\x04]\0\x02\x02[\nF\x28]| ##############################NEXT PROBE############################## Probe UDP DNSStatusRequest q|\0\0\x10\0\0\0\0\0\0\0\0\0| rarity 5 -ports 53,69,135,1761 +ports 53,69,135,1761,26198 # Note when generating match lines - TCP DNS responses have two bytes at the beginning # of the response that the UDP doesn't, otherwise they are the same. Account for this @@ -14977,7 +14977,7 @@ softmatch radmin m|^\x01\x00\x00\x00\x25.\x00..\x08.\x00..|s p/Famatech Radmin/ match srcds m|^\n\0\0\0\0\0\0\0\0\0\0\0\0\0$| p/srcds game server/ ##############################NEXT PROBE############################## -Probe UDP Sqlping q|\x02| +Probe UDP Sqlping q|\x02| no-payload rarity 6 ports 1434,19131-19133 match ms-sql-m m|^\x05..ServerName;([\w\-]+);InstanceName;[\w\-]+;IsClustered;\w{2,3};Version;([\d\.]+);np;.+;tcp;(\d{1,5});| p/Microsoft SQL Server/ v/$2/ i/ServerName: $1; TCPPort: $3/ o/Windows/ cpe:/a:microsoft:sql_server:$2/ cpe:/o:microsoft:windows/a @@ -15069,7 +15069,7 @@ match zabbix m|^NOT OK\n$| p/Zabbix Monitoring System/ cpe:/a:zabbix:zabbix/ ##############################NEXT PROBE############################## Probe UDP SNMPv1public q|0\x82\0/\x02\x01\0\x04\x06public\xa0\x82\0\x20\x02\x04\x4c\x33\xa7\x56\x02\x01\0\x02\x01\0\x30\x82\0\x10\x30\x82\0\x0c\x06\x08\x2b\x06\x01\x02\x01\x01\x05\0\x05\0| rarity 4 -ports 161 +ports 161,260,3401 match bittorrent-udp-tracker m|^\x03\0\0\0lic\xa0Connection ID missmatch\.\0| p/opentracker UDP tracker/ cpe:/a:dirk_engling:opentracker/ match snmp m|^0.*\x02\x01\0\x04\x06public\xa2.*\x06\x08\+\x06\x01\x02\x01\x01\x05\0\x04[^\0]([^\0]+)|s p/SNMPv1 server/ i/public/ h/$1/ @@ -15081,7 +15081,7 @@ match echo m|^0\x82\0/\x02\x01\0\x04\x06public\xa0\x82\0\x20\x02\x04\x4c\x33\xa7 ##############################NEXT PROBE############################## Probe UDP SNMPv3GetRequest q|\x30\x3a\x02\x01\x03\x30\x0f\x02\x02\x4a\x69\x02\x03\0\xff\xe3\x04\x01\x04\x02\x01\x03\x04\x10\x30\x0e\x04\0\x02\x01\0\x02\x01\0\x04\0\x04\0\x04\0\x30\x12\x04\0\x04\0\xa0\x0c\x02\x02\x37\xf0\x02\x01\0\x02\x01\0\x30\0| rarity 4 -ports 161 +ports 161,260,3401 match echo m|^\x30\x3a\x02\x01\x03\x30\x0f\x02\x02\x4a\x69\x02\x03\0\xff\xe3\x04\x01\x04\x02\x01\x03\x04\x10\x30\x0e\x04\0\x02\x01\0\x02\x01\0\x04\0\x04\0\x04\0\x30\x12\x04\0\x04\0\xa0\x0c\x02\x02\x37\xf0\x02\x01\0\x02\x01\0\x30\0$| # H.225 bandwidthReject @@ -16166,7 +16166,7 @@ match teamspeak2 m|^\xf4\xbe\x04\x00\x00\x00\x00\x00....\x02\x00\x00\x00....\0{6 # UDP login request (encrypted) # http://seclists.org/nmap-dev/2013/q3/72 Probe UDP TeamSpeak3 q|\x05\xca\x7f\x16\x9c\x11\xf9\x89\x00\x00\x00\x00\x02\x9d\x74\x8b\x45\xaa\x7b\xef\xb9\x9e\xfe\xad\x08\x19\xba\xcf\x41\xe0\x16\xa2\x32\x6c\xf3\xcf\xf4\x8e\x3c\x44\x83\xc8\x8d\x51\x45\x6f\x90\x95\x23\x3e\x00\x97\x2b\x1c\x71\xb2\x4e\xc0\x61\xf1\xd7\x6f\xc5\x7e\xf6\x48\x52\xbf\x82\x6a\xa2\x3b\x65\xaa\x18\x7a\x17\x38\xc3\x81\x27\xc3\x47\xfc\xa7\x35\xba\xfc\x0f\x9d\x9d\x72\x24\x9d\xfc\x02\x17\x6d\x6b\xb1\x2d\x72\xc6\xe3\x17\x1c\x95\xd9\x69\x99\x57\xce\xdd\xdf\x05\xdc\x03\x94\x56\x04\x3a\x14\xe5\xad\x9a\x2b\x14\x30\x3a\x23\xa3\x25\xad\xe8\xe6\x39\x8a\x85\x2a\xc6\xdf\xe5\x5d\x2d\xa0\x2f\x5d\x9c\xd7\x2b\x24\xfb\xb0\x9c\xc2\xba\x89\xb4\x1b\x17\xa2\xb6| -rarity 9 +rarity 8 ports 9987 # These are the bytes in common, but a lot of the bytes are close in value @@ -16394,7 +16394,7 @@ softmatch openvpn m|^\0\x1e@........\x02\0\0\0\0\0\0\0\x007\xa5&\x08\xa2\x1b\xa0 # P_CONTROL_HARD_RESET_CLIENT_V2 Probe UDP OpenVPN q|8d\xc1x\x01\xb8\x9b\xcb\x8f\0\0\0\0\0| ports 1194,443,500 -rarity 9 +rarity 8 match openvpn m|^@........\x01\0\0\0\0d\xc1x\x01\xb8\x9b\xcb\x8f\0\0\0\0|s p/OpenVPN/ # INVALID-MAJOR-VERSION softmatch isakmp m|^................\x0b\x10\x05\0\0\0\0\0\0\0\0\(\0\0\0\x0c\0\0\0\x01\x01\0\0\x05| @@ -16438,7 +16438,7 @@ match mqtt m|^\x20\x02\x00.$| ##############################NEXT PROBE############################## # RMCP Get Channel Auth Capabilities Probe UDP ipmi-rmcp q|\x06\0\xff\x07\0\0\0\0\0\0\0\0\0\x09\x20\x18\xc8\x81\0\x38\x8e\x04\xb5| -rarity 9 +rarity 8 ports 623 softmatch asf-rmcp m|^\x06\0\xff\x07\0\0\0\0\0\0\0\0\0\x10| @@ -16456,7 +16456,7 @@ softmatch coap m|^`E| # DTLS Client Hello. Dissection available in nmap-payloads Probe UDP DTLSSessionReq q|\x16\xfe\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x36\x01\x00\x00\x2a\x00\x00\x00\x00\x00\x00\x00\x2a\xfe\xfd\x00\x00\x00\x00\x7c\x77\x40\x1e\x8a\xc8\x22\xa0\xa0\x18\xff\x93\x08\xca\xac\x0a\x64\x2f\xc9\x22\x64\xbc\x08\xa8\x16\x89\x19\x30\x00\x00\x00\x02\x00\x2f\x01\x00| rarity 2 -ports 443,853,4433,4740,5349,5684,5868,6514,6636,8232,10161,10162,12346,12446,12546,12646,12746,12846,12946,13046 +ports 443,853,3391,4433,4740,5349,5684,5868,6514,6636,8232,10161,10162,12346,12446,12546,12646,12746,12846,12946,13046 # OpenSSL 1.1.0 s_server -dtls -listen # HelloVerifyRequest always uses DTLS 1.1 version, per RFC 6347 @@ -16647,3 +16647,124 @@ ports 9761 # 06 - ACK (15 is NACK) match insteon-plm m|^\x02\x60...(.).\x9b\x06$| p/Insteon SmartLinc PLM/ i/device type: $I(1,">")/ match insteon-plm m|^\x02\x60...(.).[\x9c\x9d]\x06$| p/Insteon Hub PLM/ i/device type: $I(1,">")/ + +##############################NEXT PROBE############################## +Probe UDP DHCP_INFORM q|\x01\x01\x06\0\x01\x23\x45\x67\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\0\0\x0e\x35\xd4\xd8\x51\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\x82\x53\x63\x35\x01\x08\xff| +rarity 8 +ports 67 + +##############################NEXT PROBE############################## +Probe UDP TFTP_GET q|\0\x01r7tftp.txt\0octet\0| +rarity 8 +ports 69 + +Probe UDP ONCRPC_CALL q|\x3e\xec\xe3\xca\0\0\0\0\0\0\0\x02\0\xbc\x61\x4e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| +rarity 8 +ports 111,2049,4045,32768-65535 +Probe UDP NTP_REQ q|\xd9\0\x0a\xfa\0\0\0\0\0\x01\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xc6\xf1\x5e\xdb\x78\0\0\0| +rarity 8 +ports 123 +Probe UDP DCERPC_CALL q|\x05\0\x0b\x03\x10\0\0\0\x48\0\0\0\x01\0\0\0\xb8\x10\xb8\x10\0\0\0\0\x01\0\0\0\0\0\x01\0\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\xe7\x03\0\0\xfe\xdc\xba\x98\x76\x54\x32\x10\x01\x23\x45\x67\x89\xab\xcd\xef\xe7\x03\0\0| +rarity 8 +ports 135,1025-1199 +Probe UDP CIFS_NS_UC q|\x01\x91\0\0\0\x01\0\0\0\0\0\0\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\0\0\x21\0\x01| +rarity 8 +ports 137 +Probe UDP CIFS_NS_BC q|\x01\x91\0\x10\0\x01\0\0\0\0\0\0\x20CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\0\0\x21\0\x01| +rarity 8 +ports 137 +# Initiator cookie 0x0011223344556677, responder cookie 0x0000000000000000. +# Version 1, Main Mode, flags 0x00, message ID 0x00000000, length 192. +# Security Association payload, length 164, IPSEC, IDENTITY. +# Proposal 1, length 152, ISAKMP, 4 transforms. +# Transform 1, 3DES-CBC, SHA, PSK, group 2. +# Transform 2, 3DES-CBC, MD5, PSK, group 2. +# Transform 3, DES-CBC, SHA, PSK, group 2. +# Transform 4, DES-CBC, MD5, PSK, group 2. +Probe UDP IKE_MAIN_MODE q|\0\x11\x22\x33\x44\x55\x66\x77\0\0\0\0\0\0\0\0\x01\x10\x02\0\0\0\0\0\0\0\0\xC0\0\0\0\xA4\0\0\0\x01\0\0\0\x01\0\0\0\x98\x01\x01\0\x04\x03\0\0\x24\x01\x01\0\0\x80\x01\0\x05\x80\x02\0\x02\x80\x03\0\x01\x80\x04\0\x02\x80\x0B\0\x01\0\x0C\0\x04\0\0\0\x01\x03\0\0\x24\x02\x01\0\0\x80\x01\0\x05\x80\x02\0\x01\x80\x03\0\x01\x80\x04\0\x02\x80\x0B\0\x01\0\x0C\0\x04\0\0\0\x01\x03\0\0\x24\x03\x01\0\0\x80\x01\0\x01\x80\x02\0\x02\x80\x03\0\x01\x80\x04\0\x02\x80\x0B\0\x01\0\x0C\0\x04\0\0\0\x01\0\0\0\x24\x04\x01\0\0\x80\x01\0\x01\x80\x02\0\x01\x80\x03\0\x01\x80\x04\0\x02\x80\x0B\0\x01\0\x0C\0\x04\0\0\0\x01| source=500 +rarity 8 +ports 500 +Probe UDP IPSEC_START q|\x31\x27\xfc\xb0\x38\x10\x9e\x89\0\0\0\0\0\0\0\0\x01\x10\x02\0\0\0\0\0\0\0\0\xcc\x0d\0\0\x5c\0\0\0\x01\0\0\0\x01\0\0\0\x50\x01\x01\0\x02\x03\0\0\x24\x01\x01\0\0\x80\x01\0\x05\x80\x02\0\x02\x80\x04\0\x02\x80\x03\0\x03\x80\x0b\0\x01\0\x0c\0\x04\0\0\x0e\x10\0\0\0\x24\x02\x01\0\0\x80\x01\0\x05\x80\x02\0\x01\x80\x04\0\x02\x80\x03\0\x03\x80\x0b\0\x01\0\x0c\0\x04\0\0\x0e\x10\x0d\0\0\x18\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\0\0\0\x04\x0d\0\0\x14\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\0\xd6\xc2\xd3\x0d\0\0\x14\x90\xcb\x80\x91\x3e\xbb\x69\x6e\x08\x63\x81\xb5\xec\x42\x7b\x1f\0\0\0\x14\x26\x24\x4d\x38\xed\xdb\x61\xb3\x17\x2a\x36\xe3\xd0\xcf\xb8\x19| source=500 +rarity 8 +ports 500 +Probe UDP RIPv1 q|\x01\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10| +rarity 8 +ports 520 +Probe UDP RMCP_ASF_PING q|\x06\0\xff\x06\0\0\x11\xbe\x80\0\0\0| +rarity 9 +ports 623 +Probe UDP OPENVPN_PKI q|\x38\x01\x02\x03\x04\x05\x06\x07\x08\0\0\0\0| +rarity 9 +ports 1194 +Probe UDP RADIUS_ACCESS q|\x01\0\0\x14\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| +rarity 8 +ports 1645,1812 +Probe UDP L2TP_ICRQ q|\xc8\x02\0\x3c\0\0\0\0\0\0\0\0\x80\x08\0\0\0\0\0\x01\x80\x08\0\0\0\x02\x01\0\x80\x0e\0\0\0\x07nxp-scan\x80\x0a\0\0\0\x03\0\0\0\x03\x80\x08\0\0\0\x09\0\0| +rarity 8 +ports 1701 +Probe UDP UPNP_MSEARCH q|M-SEARCH * HTTP/1.1\r\nHost: 239.255.255.250:1900\r\nMan: "ssdp:discover"\r\nMX: 5\r\nST: ssdp:all\r\n\r\n| +rarity 8 +ports 1900 +Probe UDP NFSPROC_NULL q|\0\0\0\0\0\0\0\0\0\0\0\x02\0\x01\x86\xA3\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0| +rarity 8 +ports 2049 +Probe UDP GPRS_GTPv1 q|\x32\x01\0\x04\0\0\x42\0\x13\x37\0\0| +rarity 9 +ports 2123,2152 +Probe UDP GPRS_GTPv2prime q|\x4e\x01\0\x04\xde\xfe\xc8\0| +rarity 8 +ports 3386 +Probe UDP GPRS_GTPv2 q|\x4e\x01\0\x04\xde\xfe\xc8\0| +rarity 8 +ports 2123,2152 +Probe UDP STUN_BIND q|\0\x01\0\0\x21\x12\xa4\x42\0\0\0\0\0\0\0\0\0\0\0\0| +rarity 8 +ports 3478 +Probe UDP STD_DISCOVER q|[PROBE] 0000| +rarity 8 +ports 6481 +Probe UDP NAT_PMP_ADDR q|\0\0| +rarity 8 +ports 5351 +Probe UDP DNS_SD_QU q|\0\0\0\0\0\x01\0\0\0\0\0\0\x09_services\x07_dns-sd\x04_udp\x05local\0\0\x0c\x80\x01| +rarity 8 +ports 5353 +Probe UDP PCANY_STATUS q|ST| +rarity 8 +ports 5632 +Probe UDP UT2K_PING q|None\0| +rarity 8 +ports 7777 +Probe UDP AMANDA_NOOP q|Amanda 2.6 REQ HANDLE 000-00000000 SEQ 0\nSERVICE noop\n| +rarity 8 +ports 10080 +Probe UDP WDB_TARGET_PING q|\0\0\0\0\0\0\0\0\0\0\0\x02\x55\x55\x55\x55\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\x55\x13\0\0\0\x30\0\0\0\x01\0\0\0\x02\0\0\0\0\0\0\0\0| +rarity 8 +ports 17185 +Probe UDP WDB_TARGET_CONNECT q|\x72\x37\x72\x37\0\0\0\0\0\0\0\x02\x55\x55\x55\x55\0\0\0\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xff\xff\x55\x10\0\0\0\x3c\0\0\0\x03\0\0\0\x02\0\0\0\0\0\0\0\0| +rarity 9 +ports 17185 +Probe UDP KADEMLIA_PING q|\xE4\x60| +rarity 8 +ports 4665,4666,4672,6429 +Probe UDP TS3INIT1 q|TS3INIT1\0\x65\0\0\x88\x0a\x39\x7b\x0f\0\x5b\x55\x72\xef\xdc\x78\x32\x6b\0\0\0\0\0\0\0\0| +rarity 9 +ports 9987 +Probe UDP MEMCACHED_VERSION q|\0\x01\0\0\0\x01\0\0version\r\n| +rarity 9 +ports 11211 +Probe UDP STEAM q|\xff\xff\xff\xffTSourceEngineQuery\0| +rarity 8 +ports 27015-27030 +Probe UDP TRIN00_UNIX_PING q|png l44adsl| +rarity 9 +ports 27444 +Probe UDP BO_PING q|\xce\x63\xd1\xd2\x16\xe7\x13\xcf\x38\xa5\xa5\x86\xb2\x75\x4b\x99\xaa\x32\x58| +rarity 9 +ports 31337 +Probe UDP TRIN00_WIN_PING q|png []..Ks| +rarity 9 +ports 34555 +Probe UDP BECKHOFF_ADS q|\x03\x66\x14\x71\0\0\0\0\x01\0\0\0\0\0\0\0\x01\x01\x10\x27\0\0\0\0| +rarity 8 +ports 48899 diff --git a/nmap.cc b/nmap.cc index 213bbfd40..fca544ab1 100644 --- a/nmap.cc +++ b/nmap.cc @@ -1792,7 +1792,6 @@ void nmap_free_mem() { cp_free(); free_services(); freeinterfaces(); - free_payloads(); AllProbes::service_scan_free(); traceroute_hop_cache_clear(); nsock_set_default_engine(NULL); diff --git a/payload.cc b/payload.cc index 93c3034fc..2a14be753 100644 --- a/payload.cc +++ b/payload.cc @@ -77,374 +77,83 @@ #include "utils.h" #include "nmap_error.h" #include "scan_lists.h" +#include "service_scan.h" extern NmapOps o; -struct payload { - std::string data; +/* The key for the payload lookup map is u16 dport. We can make it a u32 and + * add proto later if needed. */ - payload (const char *c, size_t n) - : data(c, n) - {} - /* Extra data such as source port goes here. */ +static std::map > portPayloads; - /* If 2 payloads are equivalent according to this operator, we'll only keep - * the first one, so be sure you update it when adding other attributes. */ - bool operator==(const payload& other) const { - return data == other.data; - } -}; - -/* The key for the payload lookup map is a (proto, port) pair. */ -struct proto_dport { - u8 proto; - u16 dport; - - proto_dport(u8 proto, u16 dport) { - this->proto = proto; - this->dport = dport; - } - - bool operator<(const proto_dport& other) const { - if (proto == other.proto) - return dport < other.dport; - else - return proto < other.proto; - } -}; - -static std::map > portPayloads; -static std::vector uniquePayloads; // for accounting - -/* Newlines are significant because keyword directives (like "source") that - follow the payload string are significant to the end of the line. */ -typedef enum token_type { - TOKEN_ERROR = -1, - TOKEN_EOF = 0, - TOKEN_NEWLINE, - TOKEN_SYMBOL, - TOKEN_STRING, -} token_t; - -struct token { - token_t type; - size_t len; - char text[1024]; -}; - -static unsigned long line_no; - -/* Get the next token from fp. The return value is the token type, or -1 on - error. The token type is also stored in token->type. For TOKEN_SYMBOL and - TOKEN_STRING, the text is stored in token->text and token->len. The text is - null terminated. */ -static token_t next_token(FILE *fp, struct token *token) { - unsigned int i, tmplen; - int c; - - token->len = 0; - - /* Skip whitespace and comments. */ - while (isspace(c = fgetc(fp)) && c != '\n') - ; - - switch(c) { - case EOF: - token->type = TOKEN_EOF; - break; - case '\n': - line_no++; - token->type = TOKEN_NEWLINE; - break; - case '#': - while ((c = fgetc(fp)) != EOF && c != '\n') - ; - if (c == EOF) { - token->type = TOKEN_EOF; - } else { - line_no++; - token->type = TOKEN_NEWLINE; - } - break; - case '"': - token->type = TOKEN_STRING; - i = 0; - while ((c = fgetc(fp)) != EOF && c != '\n' && c != '"') { - if (i + 1 >= sizeof(token->text)) - return TOKEN_ERROR; - if (c == '\\') { - token->text[i++] = '\\'; - if (i + 1 >= sizeof(token->text)) - return TOKEN_ERROR; - c = fgetc(fp); - if (c == EOF) - return TOKEN_ERROR; - } - token->text[i++] = c; - } - if (c != '"') - return TOKEN_ERROR; - token->text[i] = '\0'; - if (cstring_unescape(token->text, &tmplen) == NULL) - return TOKEN_ERROR; - token->len = tmplen; - break; - default: - token->type = TOKEN_SYMBOL; - i = 0; - token->text[i++] = c; - while ((c = fgetc(fp)) != EOF && (isalnum(c) || c == ',' || c == '-')) { - if (i + 1 >= sizeof(token->text)) - return TOKEN_ERROR; - token->text[i++] = c; - } - ungetc(c, fp); - token->text[i] = '\0'; - token->len = i; - break; - } - - return token->type; -} - -/* Loop over fp, reading tokens and adding payloads to the global payloads map - as they are completed. Returns -1 on error. */ -static int load_payloads_from_file(FILE *fp) { - struct token token; - unsigned long firstline = 0; - - line_no = 1; - token_t type = next_token(fp, &token); - for (;;) { - unsigned short *ports; - int count; - bool duplicate = false; - - /* Skip everything (unknown keywords from previous payload, unknown file - * keywords, etc.) until the next payload entry or EOF */ - while (type != TOKEN_EOF && !(type == TOKEN_SYMBOL && strcmp(token.text, "udp") == 0)) - type = next_token(fp, &token); - if (type == TOKEN_EOF) - break; - - firstline = line_no; - - type = next_token(fp, &token); - if (type != TOKEN_SYMBOL) { - fprintf(stderr, "Expected a port list at line %lu of %s.\n", line_no, PAYLOAD_FILENAME); - return -1; - } - getpts_simple(token.text, SCAN_UDP_PORT, &ports, &count); - if (ports == NULL) { - fprintf(stderr, "Can't parse port list \"%s\" at line %lu of %s.\n", token.text, line_no, PAYLOAD_FILENAME); - return -1; - } - - while(TOKEN_NEWLINE == (type = next_token(fp, &token))) - ; // skip newlines - - if (type != TOKEN_STRING) { - log_write(LOG_STDERR, "Payload missing data at line %lu of %s.\n", line_no, PAYLOAD_FILENAME); - // Try a new payload - free(ports); - continue; - } - - struct payload *portPayload = NULL; - // Peek at the next significant token - struct token peek_token; - while (TOKEN_NEWLINE == (type = next_token(fp, &peek_token))) - ; // skip newlines - - // If it's a string continuation, see if we can squeeze it into the current token. - while (type == TOKEN_STRING) { - if (token.len + peek_token.len < sizeof(token.text)) { - // Next string fits in this one's buffer! - memcpy(token.text + token.len, peek_token.text, peek_token.len); - token.len += peek_token.len; - } - else { - // Token is full - if (portPayload == NULL) { - // Allocate new payload - portPayload = new struct payload (token.text, token.len); - } - else { - // append token to current payload - portPayload->data.append(token.text, token.len); - } - // peek_token becomes the previous token - token = peek_token; - } - // Keep peeking forward - while (TOKEN_NEWLINE == (type = next_token(fp, &peek_token))) - ; // skip newlines - } - - // If the string is still going, but we got an error, abandon this payload. - if (type == TOKEN_ERROR && peek_token.type == TOKEN_STRING) { - log_write(LOG_STDERR, "Error parsing payload data at line %lu of %s.\n", line_no, PAYLOAD_FILENAME); - if (portPayload) - delete portPayload; - // maybe we can pick up at the next payload. - type = next_token(fp, &token); - free(ports); - continue; - } - - // Otherwise, stash the last token in the payload and move on. - if (portPayload == NULL) { - // Allocate new payload - portPayload = new struct payload (token.text, token.len); - } - else { - // append token to current payload - portPayload->data.append(token.text, token.len); - } - token = peek_token; - - // Here we would parse additional keywords like "source" that we might care about. - - // Make sure these payloads are actually unique! - for (std::vector::const_iterator it = uniquePayloads.begin(); - it != uniquePayloads.end(); ++it) { - if (**it == *portPayload) { - // Probably not what they intended. - log_write(LOG_STDERR, "Duplicate payload on line %lu of %s.\n", firstline, PAYLOAD_FILENAME); - // Since they're functionally equivalent, only keep one copy. - duplicate = true; - delete portPayload; - portPayload = *it; - break; - } - } - if (!duplicate) { - uniquePayloads.push_back(portPayload); - duplicate = false; - } - - for (int p = 0; p < count; p++) { - const struct proto_dport key(IPPROTO_UDP, ports[p]); - - std::vector &portPayloadVector = portPayloads[key]; - - // Ports are unique, and we ensured payloads are unique earlier, so no chance of duplicate here. - portPayloadVector.push_back(portPayload); - if (portPayloadVector.size() > MAX_PAYLOADS_PER_PORT) { - fatal("Number of UDP payloads for port %u exceeds the limit of %u.\n", ports[p], MAX_PAYLOADS_PER_PORT); - } - } - - free(ports); - } - - return 0; -} - -/* Ensure that the payloads map is initialized from the nmap-payloads file. This - function keeps track of whether it has been called and does nothing after it - is called the first time. */ int init_payloads(void) { static bool payloads_loaded = false; - char filename[256]; - FILE *fp; int ret; if (payloads_loaded) return 0; + AllProbes *AP = AllProbes::service_scan_init(); + for (std::vector::const_iterator it = AP->probes.begin(); + it != AP->probes.end(); it++) { + ServiceProbe *current_probe = *it; + if (current_probe->getProbeProtocol() == IPPROTO_UDP && !current_probe->notForPayload) { + for (std::vector::const_iterator pt = current_probe->probablePortsBegin(); + pt != current_probe->probablePortsEnd(); pt++) { + std::vector &portPayloadVector = portPayloads[*pt]; + portPayloadVector.push_back(current_probe); + if (portPayloadVector.size() > MAX_PAYLOADS_PER_PORT) { + fatal("Number of UDP payloads for port %u exceeds the limit of %u.\n", *pt, MAX_PAYLOADS_PER_PORT); + } + } + } + } payloads_loaded = true; - if (nmap_fetchfile(filename, sizeof(filename), PAYLOAD_FILENAME) != 1) { - error("Cannot find %s. UDP payloads are disabled.", PAYLOAD_FILENAME); - return 0; - } - - fp = fopen(filename, "r"); - if (fp == NULL) { - gh_perror("Can't open %s for reading.\n", filename); - return -1; - } - /* Record where this data file was found. */ - o.loaded_data_files[PAYLOAD_FILENAME] = filename; - - ret = load_payloads_from_file(fp); - fclose(fp); - return ret; } -void free_payloads(void) { - std::vector::iterator vec_it; - - for (vec_it = uniquePayloads.begin(); vec_it != uniquePayloads.end(); ++vec_it) { - delete *vec_it; - } - uniquePayloads.clear(); - portPayloads.clear(); -} - /* Get a payload appropriate for the given UDP port. For certain selected ports a payload is returned, and for others a zero-length payload is returned. The length is returned through the length pointer. */ -const char *udp_port2payload(u16 dport, size_t *length, u8 index) { - static const char *payload_null = ""; - std::map >::const_iterator portPayloadIterator; - std::vector::const_iterator portPayloadVectorIterator; - const proto_dport key(IPPROTO_UDP, dport); +static const u8 *udp_port2payload(u16 dport, int *length, u8 index) { + const u8 *payload = NULL; + std::map >::const_iterator portPayloadIterator; int portPayloadVectorSize; - portPayloadIterator = portPayloads.find(key); + *length = 0; + portPayloadIterator = portPayloads.find(dport); if (portPayloadIterator != portPayloads.end()) { - const std::vector& portPayloadVector = portPayloads.find(key)->second; + const std::vector& portPayloadVector = portPayloadIterator->second; portPayloadVectorSize = portPayloadVector.size(); + assert(portPayloadVectorSize > 0); - index %= portPayloadVectorSize; + const ServiceProbe *SP = portPayloadVector[index % portPayloadVectorSize]; + payload = SP->getProbeString(length); - if (portPayloadVectorSize > 0) { - portPayloadVectorIterator = portPayloadVector.begin(); - - while (index > 0 && portPayloadVectorIterator != portPayloadVector.end()) { - index--; - portPayloadVectorIterator++; - } - - assert (index == 0); - assert (portPayloadVectorIterator != portPayloadVector.end()); - - const std::string &data = (*portPayloadVectorIterator)->data; - *length = data.size(); - return data.data(); - } else { - *length = 0; - return payload_null; - } - } else { - *length = 0; - return payload_null; } + return payload; } /* Get a payload appropriate for the given UDP port. If --data-length was used, returns the global random payload. Otherwise, for certain selected ports a payload is returned, and for others a zero-length payload is returned. The length is returned through the length pointer. */ -const char *get_udp_payload(u16 dport, size_t *length, u8 index) { +const u8 *get_udp_payload(u16 dport, int *length, u8 index) { if (o.extra_payload != NULL) { *length = o.extra_payload_length; - return o.extra_payload; + return (u8 *) o.extra_payload; } else { return udp_port2payload(dport, length, index); } } u8 udp_payload_count(u16 dport) { - std::map >::const_iterator portPayloadIterator; - const proto_dport key(IPPROTO_UDP, dport); + std::map >::const_iterator portPayloadIterator; size_t portPayloadVectorSize = 0; - portPayloadIterator = portPayloads.find(key); + portPayloadIterator = portPayloads.find(dport); if (portPayloadIterator != portPayloads.end()) { portPayloadVectorSize = portPayloadIterator->second.size(); @@ -452,3 +161,25 @@ u8 udp_payload_count(u16 dport) { return portPayloadVectorSize; } + +const struct MatchDetails *payload_service_match(u16 dport, const u8 *buf, int buflen) { + std::map >::const_iterator portPayloadIterator; + + portPayloadIterator = portPayloads.find(dport); + if (portPayloadIterator != portPayloads.end()) { + const std::vector& portPayloadVector = portPayloadIterator->second; + // We don't know which payload triggered this, since we send all at once + // with the same source port. + for (std::vector::const_iterator sp = portPayloadVector.begin(); + sp != portPayloadVector.end(); sp++) { + ServiceProbe *probe = *sp; + const struct MatchDetails *MD = NULL; + for (int fb = 0; probe->fallbacks[fb] != NULL; fb++) { + MD = probe->fallbacks[fb]->testMatch(buf, buflen, 0); + if (MD) + return MD; + } + } + } + return NULL; +} diff --git a/payload.h b/payload.h index 94342a8b3..c4d4d92e0 100644 --- a/payload.h +++ b/payload.h @@ -64,14 +64,16 @@ #ifndef PAYLOAD_H #define PAYLOAD_H +#include "service_scan.h" #define PAYLOAD_FILENAME "nmap-payloads" // Semi-arbitrary limit, but we use u8 for indexing/retrieval // and we send all payloads at once and need to not overwhelm. #define MAX_PAYLOADS_PER_PORT 0xff -const char *get_udp_payload(u16 dport, size_t *length, u8 index); +const u8 *get_udp_payload(u16 dport, int *length, u8 index); u8 udp_payload_count(u16 dport); +const struct MatchDetails *payload_service_match(u16 dport, const u8 *buf, int buflen); int init_payloads(void); void free_payloads(void); diff --git a/scan_engine_raw.cc b/scan_engine_raw.cc index 1049f8bc0..d8425d980 100644 --- a/scan_engine_raw.cc +++ b/scan_engine_raw.cc @@ -1292,8 +1292,8 @@ UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss, } } } else if (pspec->type == PS_UDP) { - const char *payload; - size_t payload_length; + const u8 *payload; + int payload_length; u8 numpayloads = udp_payload_count(pspec->pd.udp.dport); // Even if no payloads, we can send with null payload numpayloads = MAX(numpayloads, 1); @@ -2166,6 +2166,14 @@ bool get_pcap_result(UltraScanInfo *USI, struct timeval *stime) { newstate = PORT_OPEN; current_reason = ER_UDPRESPONSE; goodone = true; + /* Store the data response in case service_scan wants it later */ + if (datalen > UDP_HDR_LEN) { + struct EarlySvcResponse *esr = (EarlySvcResponse *) safe_zalloc(sizeof(struct EarlySvcResponse) + datalen - UDP_HDR_LEN); + esr->pspec = *(probe->pspec()); + esr->len = datalen - UDP_HDR_LEN; + memcpy(esr->data, (u8 *)data + UDP_HDR_LEN, esr->len); + hss->target->earlySvcResponses.push_back(esr); + } } } else continue; /* Unexpected protocol */ } while (!goodone && !timedout); diff --git a/service_scan.cc b/service_scan.cc index efeffd3ac..4a0110eb8 100644 --- a/service_scan.cc +++ b/service_scan.cc @@ -71,6 +71,7 @@ #include "Target.h" #include "utils.h" #include "nmap_error.h" +#include "payload.h" #include "protocols.h" #include "scan_lists.h" #include "charpool.h" @@ -239,7 +240,10 @@ struct substargs { static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *mydata); static void servicescan_write_handler(nsock_pool nsp, nsock_event nse, void *mydata); static void servicescan_connect_handler(nsock_pool nsp, nsock_event nse, void *mydata); -static void end_svcprobe(nsock_pool nsp, enum serviceprobestate probe_state, ServiceGroup *SG, ServiceNFO *svc, nsock_iod nsi); +static void end_svcprobe(enum serviceprobestate probe_state, ServiceGroup *SG, ServiceNFO *svc, nsock_iod nsi); +static int scanThroughTunnel(ServiceNFO *svc); +static bool processMatch(const struct MatchDetails *MD, ServiceNFO *svc, + const char *probeName, const char *fallbackName); ServiceProbeMatch::ServiceProbeMatch() { deflineno = -1; @@ -1076,6 +1080,7 @@ ServiceProbe::ServiceProbe() { // The default rarity level for a probe without a rarity // directive - should almost never have to be relied upon. rarity = 5; + notForPayload = false; fallbackStr = NULL; for (i=0; i &Targets, AllProbes *AP) { num_hosts_timedout = 0; gettimeofday(&now, NULL); + SPM = new ScanProgressMeter("Service scan"); for(targetno = 0 ; targetno < Targets.size(); targetno++) { + Target *target = Targets[targetno]; + assert(target); nxtport = NULL; - if (Targets[targetno]->timedOut(&now)) { + if (target->timedOut(&now)) { num_hosts_timedout++; continue; } - while((nxtport = Targets[targetno]->ports.nextPort(nxtport, &port, TCPANDUDPANDSCTP, PORT_OPEN))) { + while((nxtport = target->ports.nextPort(nxtport, &port, TCPANDUDPANDSCTP, PORT_OPEN))) { svc = new ServiceNFO(AP); - svc->target = Targets[targetno]; + svc->target = target; svc->portno = nxtport->portno; svc->proto = nxtport->proto; services_remaining.push_back(svc); } - } /* Use a whole new loop for PORT_OPENFILTERED so that we try all the known open ports first before bothering with this speculative stuff */ - for(targetno = 0 ; targetno < Targets.size(); targetno++) { - nxtport = NULL; - if (Targets[targetno]->timedOut(&now)) { - continue; - } - while((nxtport = Targets[targetno]->ports.nextPort(nxtport, &port, TCPANDUDPANDSCTP, PORT_OPENFILTERED))) { + while((nxtport = target->ports.nextPort(nxtport, &port, TCPANDUDPANDSCTP, PORT_OPENFILTERED))) { svc = new ServiceNFO(AP); - svc->target = Targets[targetno]; + svc->target = target; svc->portno = nxtport->portno; svc->proto = nxtport->proto; services_remaining.push_back(svc); } + + /* Check if any early responses can help */ + for (std::vector::iterator it = target->earlySvcResponses.begin(); + it != target->earlySvcResponses.end(); it++) { + EarlySvcResponse *esr = *it; + assert(esr); + const struct MatchDetails *MD = payload_service_match(esr->pspec.pd.udp.dport, + esr->data, esr->len); + if (MD) { + // Find the appropriate ServiceNFO and process it. + for (std::list::iterator i = services_remaining.begin(); + i != services_remaining.end(); i++) { + svc = *i; + if (svc->proto == IPPROTO_UDP && svc->portno == esr->pspec.pd.udp.dport) { + if (processMatch(MD, svc, "port scan", "udp payload") + && !scanThroughTunnel(svc)) { + end_svcprobe(PROBESTATE_FINISHED_HARDMATCHED, this, svc, NULL); + } + break; + } + } + } + } } - SPM = new ScanProgressMeter("Service scan"); desired_par = 1; if (o.timing_level == 3) desired_par = 20; if (o.timing_level == 4) desired_par = 30; @@ -2046,16 +2080,17 @@ static void startNextProbe(nsock_pool nsp, nsock_iod nsi, ServiceGroup *SG, } else { // Should only happen if someone has a highly perverse nmap-service-probes // file. Null scan should generally never be the only probe. - end_svcprobe(nsp, (svc->softMatchFound)? PROBESTATE_FINISHED_SOFTMATCHED : PROBESTATE_FINISHED_NOMATCH, SG, svc, NULL); + end_svcprobe((svc->softMatchFound)? PROBESTATE_FINISHED_SOFTMATCHED : PROBESTATE_FINISHED_NOMATCH, SG, svc, NULL); } } else { // The finished probe was not a NULL probe. So we close the // connection, and if further probes are available, we launch the // next one. + if (nsi) + nsock_iod_delete(nsi, NSOCK_PENDING_SILENT); if (!isInitial) probe = svc->nextProbe(true); // if was initial, currentProbe() returned the right one to execute. if (probe) { - nsock_iod_delete(nsi, NSOCK_PENDING_SILENT); if ((svc->niod = nsock_iod_new(nsp, svc)) == NULL) { fatal("Failed to allocate Nsock I/O descriptor in %s()", __func__); } @@ -2092,8 +2127,7 @@ static void startNextProbe(nsock_pool nsp, nsock_iod nsi, ServiceGroup *SG, } } else { // No more probes remaining! Failed to match - nsock_iod_delete(nsi, NSOCK_PENDING_SILENT); - end_svcprobe(nsp, (svc->softMatchFound)? PROBESTATE_FINISHED_SOFTMATCHED : + end_svcprobe((svc->softMatchFound)? PROBESTATE_FINISHED_SOFTMATCHED : PROBESTATE_FINISHED_NOMATCH, SG, svc, NULL); } @@ -2115,8 +2149,7 @@ static void startNextProbe(nsock_pool nsp, nsock_iod nsi, ServiceGroup *SG, That is a special case. */ -static int scanThroughTunnel(nsock_pool nsp, nsock_iod nsi, ServiceGroup *SG, - ServiceNFO *svc) { +static int scanThroughTunnel(ServiceNFO *svc) { if (svc->probe_matched && strncmp(svc->probe_matched, "ssl/", 4) == 0) { /* The service has been detected without having to make an SSL connection */ @@ -2145,7 +2178,6 @@ static int scanThroughTunnel(nsock_pool nsp, nsock_iod nsi, ServiceGroup *SG, svc->cpe_a_matched[0] = svc->cpe_h_matched[0] = svc->cpe_o_matched[0] = '\0'; svc->softMatchFound = false; svc->resetProbes(true); - startNextProbe(nsp, nsi, SG, svc, true); return 1; #else return 0; @@ -2153,7 +2185,7 @@ static int scanThroughTunnel(nsock_pool nsp, nsock_iod nsi, ServiceGroup *SG, } /* Prints completion estimates and the like when appropriate */ -static void considerPrintingStats(nsock_pool nsp, ServiceGroup *SG) { +static void considerPrintingStats(ServiceGroup *SG) { /* Check for status requests */ if (keyWasPressed()) { nmap_adjust_loglevel(o.versionTrace()); @@ -2193,7 +2225,8 @@ static void handleHostIfDone(ServiceGroup *SG, Target *target) { } if (!found) { - target->stopTimeOutClock(nsock_gettimeofday()); + if (target->timeOutClockRunning()) + target->stopTimeOutClock(nsock_gettimeofday()); if (target->timedOut(NULL)) { SG->num_hosts_timedout++; } @@ -2203,7 +2236,7 @@ static void handleHostIfDone(ServiceGroup *SG, Target *target) { // A simple helper function to cancel further work on a service and // set it to the given probe_state pass NULL for nsi if you don't want // it to be deleted (for example, if you already have done so). -static void end_svcprobe(nsock_pool nsp, enum serviceprobestate probe_state, ServiceGroup *SG, ServiceNFO *svc, nsock_iod nsi) { +static void end_svcprobe(enum serviceprobestate probe_state, ServiceGroup *SG, ServiceNFO *svc, nsock_iod nsi) { std::list::iterator member; Target *target = svc->target; @@ -2225,7 +2258,7 @@ static void end_svcprobe(nsock_pool nsp, enum serviceprobestate probe_state, Ser SG->services_finished.push_back(svc); - considerPrintingStats(nsp, SG); + considerPrintingStats(SG); if (nsi) nsock_iod_delete(nsi, NSOCK_PENDING_SILENT); @@ -2239,9 +2272,6 @@ static void end_svcprobe(nsock_pool nsp, enum serviceprobestate probe_state, Ser // appropriate ones and then starts them up. static int launchSomeServiceProbes(nsock_pool nsp, ServiceGroup *SG) { ServiceNFO *svc; - ServiceProbe *nextprobe; - struct sockaddr_storage ss; - size_t ss_len; static int warn_no_scanning=1; while (SG->services_in_progress.size() < SG->ideal_parallelism && @@ -2249,48 +2279,24 @@ static int launchSomeServiceProbes(nsock_pool nsp, ServiceGroup *SG) { // Start executing a probe from the new list and move it to in_progress svc = SG->services_remaining.front(); if (svc->target->timedOut(nsock_gettimeofday())) { - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, NULL); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, NULL); continue; } else if (!svc->target->timeOutClockRunning()) { svc->target->startTimeOutClock(nsock_gettimeofday()); } - nextprobe = svc->nextProbe(true); - if (nextprobe == NULL) { + // Launch it! If there were no probes, we'll get a NOMATCH immediately. + startNextProbe(nsp, NULL, SG, svc, true); + + if (svc->probe_state == PROBESTATE_FINISHED_NOMATCH) { if (warn_no_scanning && o.debugging) { log_write(LOG_PLAIN, "Service scan: Not probing some ports due to low intensity\n"); warn_no_scanning=0; } - end_svcprobe(nsp, PROBESTATE_FINISHED_NOMATCH, SG, svc, NULL); continue; } - // We start by requesting a connection to the target - if ((svc->niod = nsock_iod_new(nsp, svc)) == NULL) { - fatal("Failed to allocate Nsock I/O descriptor in %s()", __func__); - } - if (o.debugging > 1) { - log_write(LOG_PLAIN, "Starting probes against new service: %s:%hu (%s)\n", svc->target->targetipstr(), svc->portno, proto2ascii_lowercase(svc->proto)); - } - if (o.spoofsource) { - o.SourceSockAddr(&ss, &ss_len); - nsock_iod_set_localaddr(svc->niod, &ss, ss_len); - } - if (o.ipoptionslen) - nsock_iod_set_ipoptions(svc->niod, o.ipoptions, o.ipoptionslen); - svc->target->TargetSockAddr(&ss, &ss_len); - if (svc->proto == IPPROTO_TCP) - nsock_connect_tcp(nsp, svc->niod, servicescan_connect_handler, - DEFAULT_CONNECT_TIMEOUT, svc, - (struct sockaddr *)&ss, ss_len, - svc->portno); - else { - assert(svc->proto == IPPROTO_UDP); - nsock_connect_udp(nsp, svc->niod, servicescan_connect_handler, - svc, (struct sockaddr *) &ss, ss_len, - svc->portno); - } // Check that the service is still where we left it. // servicescan_connect_handler can call end_svcprobe before this point, // putting it into services_finished already. @@ -2316,7 +2322,7 @@ static void servicescan_connect_handler(nsock_pool nsp, nsock_event nse, void *m assert(type == NSE_TYPE_CONNECT || type == NSE_TYPE_CONNECT_SSL); if (svc->target->timedOut(nsock_gettimeofday())) { - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, nsi); } else if (status == NSE_STATUS_SUCCESS) { #if HAVE_OPENSSL @@ -2355,13 +2361,13 @@ static void servicescan_connect_handler(nsock_pool nsp, nsock_event nse, void *m // and move it to the finished bin. if (o.debugging) error("Got nsock CONNECT response with status %s - aborting this service", nse_status2str(status)); - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, nsi); break; case NSE_STATUS_KILL: /* User probably specified host_timeout and so the service scan is * shutting down */ - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, nsi); return; default: @@ -2392,7 +2398,7 @@ static void servicescan_write_handler(nsock_pool nsp, nsock_event nse, void *myd if (svc->target->timedOut(nsock_gettimeofday())) { - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, nsi); return; } @@ -2402,7 +2408,7 @@ static void servicescan_write_handler(nsock_pool nsp, nsock_event nse, void *myd if (status == NSE_STATUS_KILL) { /* User probably specified host_timeout and so the service scan is shutting down */ - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, nsi); return; } @@ -2415,7 +2421,7 @@ static void servicescan_write_handler(nsock_pool nsp, nsock_event nse, void *myd // on us unexpectedly? if (o.debugging) error("Got nsock WRITE response with status %s - aborting this service", nse_status2str(status)); - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, nsi); // We may have room for more probes! launchSomeServiceProbes(nsp, SG); @@ -2423,6 +2429,54 @@ static void servicescan_write_handler(nsock_pool nsp, nsock_event nse, void *myd return; } +/* Returns true if this is a new hard match, false if not a match or if a softmatch */ +static bool processMatch(const struct MatchDetails *MD, ServiceNFO *svc, + const char *probeName, const char *fallbackName) { + if (!MD || !MD->serviceName) { + return false; + } + // WOO HOO!!!!!! MATCHED! But might be soft + if (MD->isSoft && svc->probe_matched) { + if (strcmp(svc->probe_matched, MD->serviceName) != 0) + error("WARNING: Service %s:%hu had already soft-matched %s, but now soft-matched %s; ignoring second value", svc->target->targetipstr(), svc->portno, svc->probe_matched, MD->serviceName); + // No error if its the same - that happens frequently. For + // example, if we read more data for the same probe response + // it will probably still match. + return false; + } + if (o.debugging > 1 || o.versionTrace()) { + log_write(LOG_PLAIN, "Service scan %s match (Probe %s matched with %s line %d): %s:%hu is %s%s. Version: |%s|%s|%s|\n", + (MD->isSoft)? "soft" : "hard", + probeName, fallbackName, + MD->lineno, + svc->target->targetipstr(), svc->portno, (svc->tunnel == SERVICE_TUNNEL_SSL)? "SSL/" : "", + MD->serviceName, (MD->product)? MD->product : "", (MD->version)? MD->version : "", + (MD->info)? MD->info : ""); + } + svc->probe_matched = MD->serviceName; + svc->tcpwrap_possible = false; + if (MD->product) + Strncpy(svc->product_matched, MD->product, sizeof(svc->product_matched)); + if (MD->version) + Strncpy(svc->version_matched, MD->version, sizeof(svc->version_matched)); + if (MD->info) + Strncpy(svc->extrainfo_matched, MD->info, sizeof(svc->extrainfo_matched)); + if (MD->hostname) + Strncpy(svc->hostname_matched, MD->hostname, sizeof(svc->hostname_matched)); + if (MD->ostype) + Strncpy(svc->ostype_matched, MD->ostype, sizeof(svc->ostype_matched)); + if (MD->devicetype) + Strncpy(svc->devicetype_matched, MD->devicetype, sizeof(svc->devicetype_matched)); + if (MD->cpe_a) + Strncpy(svc->cpe_a_matched, MD->cpe_a, sizeof(svc->cpe_a_matched)); + if (MD->cpe_h) + Strncpy(svc->cpe_h_matched, MD->cpe_h, sizeof(svc->cpe_h_matched)); + if (MD->cpe_o) + Strncpy(svc->cpe_o_matched, MD->cpe_o, sizeof(svc->cpe_o_matched)); + svc->softMatchFound = MD->isSoft; + return !MD->isSoft; +} + static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *mydata) { nsock_iod nsi = nse_iod(nse); enum nse_status status = nse_status(nse); @@ -2432,14 +2486,12 @@ static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *myda ServiceGroup *SG = (ServiceGroup *) nsock_pool_get_udata(nsp); const u8 *readstr; int readstrlen; - const struct MatchDetails *MD; - int fallbackDepth=0; assert(type == NSE_TYPE_READ); if (svc->target->timedOut(nsock_gettimeofday())) { svc->tcpwrap_possible = false; - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, nsi); } else if (status == NSE_STATUS_SUCCESS) { // w00p, w00p, we read something back from the port. svc->tcpwrap_possible = false; @@ -2449,65 +2501,28 @@ static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *myda // now get the full version readstr = svc->getcurrentproberesponse(&readstrlen); - for (MD = NULL; probe->fallbacks[fallbackDepth] != NULL; fallbackDepth++) { - MD = (probe->fallbacks[fallbackDepth])->testMatch(readstr, readstrlen); + const struct MatchDetails *MD = NULL; + ServiceProbe *fallback = NULL; + for (int fallbackDepth=0; fallbackDepth < MAXFALLBACKS + 1; fallbackDepth++) { + fallback = probe->fallbacks[fallbackDepth]; + if (fallback == NULL) + break; + MD = fallback->testMatch(readstr, readstrlen); if (MD && MD->serviceName) break; // Found one! } - if (MD && MD->serviceName) { - // WOO HOO!!!!!! MATCHED! But might be soft - if (MD->isSoft && svc->probe_matched) { - if (strcmp(svc->probe_matched, MD->serviceName) != 0) - error("WARNING: Service %s:%hu had already soft-matched %s, but now soft-matched %s; ignoring second value", svc->target->targetipstr(), svc->portno, svc->probe_matched, MD->serviceName); - // No error if its the same - that happens frequently. For - // example, if we read more data for the same probe response - // it will probably still match. - } else { - if (o.debugging > 1 || o.versionTrace()) { - if (MD->product || MD->version || MD->info) - log_write(LOG_PLAIN, "Service scan match (Probe %s matched with %s line %d): %s:%hu is %s%s. Version: |%s|%s|%s|\n", - probe->getName(), (*probe->fallbacks[fallbackDepth]).getName(), - MD->lineno, - svc->target->targetipstr(), svc->portno, (svc->tunnel == SERVICE_TUNNEL_SSL)? "SSL/" : "", - MD->serviceName, (MD->product)? MD->product : "", (MD->version)? MD->version : "", - (MD->info)? MD->info : ""); - else - log_write(LOG_PLAIN, "Service scan %s match (Probe %s matched with %s line %d): %s:%hu is %s%s\n", - (MD->isSoft)? "soft" : "hard", - probe->getName(), (*probe->fallbacks[fallbackDepth]).getName(), - MD->lineno, - svc->target->targetipstr(), svc->portno, (svc->tunnel == SERVICE_TUNNEL_SSL)? "SSL/" : "", MD->serviceName); - } - svc->probe_matched = MD->serviceName; - if (MD->product) - Strncpy(svc->product_matched, MD->product, sizeof(svc->product_matched)); - if (MD->version) - Strncpy(svc->version_matched, MD->version, sizeof(svc->version_matched)); - if (MD->info) - Strncpy(svc->extrainfo_matched, MD->info, sizeof(svc->extrainfo_matched)); - if (MD->hostname) - Strncpy(svc->hostname_matched, MD->hostname, sizeof(svc->hostname_matched)); - if (MD->ostype) - Strncpy(svc->ostype_matched, MD->ostype, sizeof(svc->ostype_matched)); - if (MD->devicetype) - Strncpy(svc->devicetype_matched, MD->devicetype, sizeof(svc->devicetype_matched)); - if (MD->cpe_a) - Strncpy(svc->cpe_a_matched, MD->cpe_a, sizeof(svc->cpe_a_matched)); - if (MD->cpe_h) - Strncpy(svc->cpe_h_matched, MD->cpe_h, sizeof(svc->cpe_h_matched)); - if (MD->cpe_o) - Strncpy(svc->cpe_o_matched, MD->cpe_o, sizeof(svc->cpe_o_matched)); - svc->softMatchFound = MD->isSoft; - if (!svc->softMatchFound) { - // We might be able to continue scan through a tunnel protocol - // like SSL - if (scanThroughTunnel(nsp, nsi, SG, svc) == 0) - end_svcprobe(nsp, PROBESTATE_FINISHED_HARDMATCHED, SG, svc, nsi); - } + if (fallback && processMatch(MD, svc, probe->getName(), fallback->getName())) { + // hard match! + // We might be able to continue scan through a tunnel protocol + // like SSL + if (scanThroughTunnel(svc)) { + startNextProbe(nsp, nsi, SG, svc, true); + } + else { + end_svcprobe(PROBESTATE_FINISHED_HARDMATCHED, SG, svc, nsi); } } - - if (!MD || !MD->serviceName || MD->isSoft) { + else { // Didn't match... maybe reading more until timeout will help // TODO: For efficiency I should be able to test if enough data // has been received rather than always waiting for the reading @@ -2547,7 +2562,7 @@ static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *myda } if (svc->tcpwrap_possible && probe->isNullProbe() && readstrlen == 0 && svc->probe_timemsused(probe) < probe->tcpwrappedms) { // TODO: Perhaps should do further verification before making this assumption - end_svcprobe(nsp, PROBESTATE_FINISHED_TCPWRAPPED, SG, svc, nsi); + end_svcprobe(PROBESTATE_FINISHED_TCPWRAPPED, SG, svc, nsi); } else { // Perhaps this service didn't like the particular probe text. // We'll try the next one @@ -2564,7 +2579,7 @@ static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *myda // Jerk hung up on us. Probably didn't like our probe. We treat it as with EOF above. if (svc->tcpwrap_possible && probe->isNullProbe() && svc->probe_timemsused(probe) < probe->tcpwrappedms) { // TODO: Perhaps should do further verification before making this assumption - end_svcprobe(nsp, PROBESTATE_FINISHED_TCPWRAPPED, SG, svc, nsi); + end_svcprobe(PROBESTATE_FINISHED_TCPWRAPPED, SG, svc, nsi); } else { // Perhaps this service didn't like the particular probe text. We'll try the // next one @@ -2585,7 +2600,7 @@ static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *myda // That is funny. The port scanner listed the port as open. Maybe it got unplugged, or firewalled us, or did // something else nasty during the scan. Shrug. I'll give up on this port svc->tcpwrap_possible = false; - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, nsi); break; #ifdef ENOPROTOOPT case ENOPROTOOPT: // ICMP_PROT_UNREACH @@ -2625,7 +2640,7 @@ static void servicescan_read_handler(nsock_pool nsp, nsock_event nse, void *myda /* User probably specified host_timeout and so the service scan is shutting down */ svc->tcpwrap_possible = false; - end_svcprobe(nsp, PROBESTATE_INCOMPLETE, SG, svc, nsi); + end_svcprobe(PROBESTATE_INCOMPLETE, SG, svc, nsi); return; } else { fatal("Unexpected status (%d) in NSE_TYPE_READ callback.", (int) status); @@ -2751,6 +2766,7 @@ int service_scan(std::vector &Targets) { } if (SG->services_remaining.size() == 0) { + processResults(SG); delete SG; return 1; } diff --git a/service_scan.h b/service_scan.h index c1c1ec159..86bfb6161 100644 --- a/service_scan.h +++ b/service_scan.h @@ -273,6 +273,9 @@ class ServiceProbe { char *fallbackStr; ServiceProbe *fallbacks[MAXFALLBACKS+1]; + std::vector::const_iterator probablePortsBegin() const {return probableports.begin();} + std::vector::const_iterator probablePortsEnd() const {return probableports.end();} + bool notForPayload; private: void setPortVector(std::vector *portv, const char *portstr, diff --git a/traceroute.cc b/traceroute.cc index e13d56e35..b7a1703c7 100644 --- a/traceroute.cc +++ b/traceroute.cc @@ -713,8 +713,8 @@ public: : Probe(host, pspec, ttl) { } unsigned char *build_packet(const struct sockaddr_storage *source, u32 *len) const { - const char *payload; - size_t payload_length; + const u8 *payload; + int payload_length; payload = get_udp_payload(pspec.pd.udp.dport, &payload_length, 0); @@ -724,13 +724,13 @@ public: return build_udp_raw(&sin->sin_addr, host->target->v4hostip(), ttl, get_random_u16(), get_random_u8(), false, NULL, 0, token ^ global_id, pspec.pd.udp.dport, - payload, payload_length, len); + (char *) payload, payload_length, len); } else if (source->ss_family == AF_INET6) { const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) source; return build_udp_raw_ipv6(&sin6->sin6_addr, host->target->v6hostip(), 0, 0, ttl, token ^ global_id, pspec.pd.udp.dport, - payload, payload_length, len); + (char *) payload, payload_length, len); } else { fatal("Unknown address family %u in %s.", source->ss_family, __func__); }