diff --git a/CHANGELOG b/CHANGELOG index 36936129b..c738098eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,12 @@ #Nmap Changelog ($Id$); -*-text-*- +o [GH#1859] Allow multiple UDP payloads to be specified for a port in + nmap-payloads. If the first payload does not get a response, the remaining + payloads are tried round-robin. [Paul Miseiko, Rapid7] + o [GH#1616] New option --discovery-ignore-rst tells Nmap to ignore TCP RST responses when determining if a target is up. Useful when firewalls are - spoofing RST packets. [Tom Sellers] + spoofing RST packets. [Tom Sellers, Rapid7] o [Ncat][GH#2087][GH#1927][GH#1928][GH#1974] It is now possible to override the value of TLS SNI via --ssl-servername [Hank Leininger, nnposter] diff --git a/payload.cc b/payload.cc index d6109d8b8..efc67ec51 100644 --- a/payload.cc +++ b/payload.cc @@ -171,7 +171,7 @@ struct proto_dport { } }; -static std::map payloads; +static std::map > portPayloads; /* Newlines are significant because keyword directives (like "source") that follow the payload string are significant to the end of the line. */ @@ -307,11 +307,35 @@ static int load_payloads_from_file(FILE *fp) { } for (int p = 0; p < count; p++) { + std::map >::iterator portPayloadIterator; + std::vector portPayloadVector; + std::vector::iterator portPayloadVectorIterator; struct proto_dport key(IPPROTO_UDP, ports[p]); - struct payload payload; + struct payload portPayload; + bool duplicate = false; - payload.data = payload_data; - payloads[key] = payload; + portPayloadIterator = portPayloads.find(key); + + if (portPayloadIterator != portPayloads.end()) { + portPayloadVector = portPayloadIterator->second; + portPayloadVectorIterator = portPayloadVector.begin(); + + while (portPayloadVectorIterator != portPayloadVector.end()) { + if (portPayloadVectorIterator->data == payload_data) { + log_write(LOG_STDERR, "UDP port payload duplication found on port: %u\n", ports[p]); + duplicate = true; + break; + } + + portPayloadVectorIterator++; + } + } + + if (!duplicate) { + portPayload.data = payload_data; + portPayloadVector.push_back(portPayload); + portPayloads[key] = portPayloadVector; + } } free(ports); @@ -356,15 +380,39 @@ int init_payloads(void) { /* 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) { +const char *udp_port2payload(u16 dport, size_t *length, u8 tryno) { static const char *payload_null = ""; - std::map::iterator it; - proto_dport pp(IPPROTO_UDP, dport); + std::map >::iterator portPayloadIterator; + std::vector portPayloadVector; + std::vector::iterator portPayloadVectorIterator; + proto_dport key(IPPROTO_UDP, dport); + int portPayloadVectorSize; - it = payloads.find(pp); - if (it != payloads.end()) { - *length = it->second.data.size(); - return it->second.data.data(); + portPayloadIterator = portPayloads.find(key); + + if (portPayloadIterator != portPayloads.end()) { + portPayloadVector = portPayloads.find(key)->second; + portPayloadVectorSize = portPayloadVector.size(); + + tryno %= portPayloadVectorSize; + + if (portPayloadVectorSize > 0) { + portPayloadVectorIterator = portPayloadVector.begin(); + + while (tryno > 0 && portPayloadVectorIterator != portPayloadVector.end()) { + tryno--; + portPayloadVectorIterator++; + } + + assert (tryno == 0); + assert (portPayloadVectorIterator != portPayloadVector.end()); + + *length = portPayloadVectorIterator->data.size(); + return portPayloadVectorIterator->data.data(); + } else { + *length = 0; + return payload_null; + } } else { *length = 0; return payload_null; @@ -375,11 +423,11 @@ const char *udp_port2payload(u16 dport, size_t *length) { 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) { +const char *get_udp_payload(u16 dport, size_t *length, u8 tryno) { if (o.extra_payload != NULL) { *length = o.extra_payload_length; return o.extra_payload; } else { - return udp_port2payload(dport, length); + return udp_port2payload(dport, length, tryno); } } diff --git a/payload.h b/payload.h index e368da082..ee1fee02b 100644 --- a/payload.h +++ b/payload.h @@ -134,9 +134,8 @@ #define PAYLOAD_FILENAME "nmap-payloads" -const char *get_udp_payload(u16 dport, size_t *length); -const char *udp_port2payload(u16 dport, size_t *length); +const char *get_udp_payload(u16 dport, size_t *length, u8 tryno); +const char *udp_port2payload(u16 dport, size_t *length, u8 tryno); int init_payloads(void); #endif /* PAYLOAD_H */ - diff --git a/scan_engine_raw.cc b/scan_engine_raw.cc index f74974698..88a2fdc8f 100644 --- a/scan_engine_raw.cc +++ b/scan_engine_raw.cc @@ -1393,7 +1393,7 @@ UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss, const char *payload; size_t payload_length; - payload = get_udp_payload(pspec->pd.udp.dport, &payload_length); + payload = get_udp_payload(pspec->pd.udp.dport, &payload_length, tryno); if (hss->target->af() == AF_INET) { for (decoy = 0; decoy < o.numdecoys; decoy++) { diff --git a/traceroute.cc b/traceroute.cc index 726dc0b72..4d430a2f8 100644 --- a/traceroute.cc +++ b/traceroute.cc @@ -785,7 +785,7 @@ public: const char *payload; size_t payload_length; - payload = get_udp_payload(pspec.pd.udp.dport, &payload_length); + payload = get_udp_payload(pspec.pd.udp.dport, &payload_length, 0); /* For UDP we encode the token in the source port. */ if (source->ss_family == AF_INET) {