mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Fix #2293: assertion failed probe->tryno == maxtries
When tying UDP payloads to tryno, we were exceeding the maxtries in order to send all available payloads, leading to assertion failures. Currently there are not more than 4 payloads for any given port; most have none, many have 1, very few have more. So we will send them all at the same time with the same source port/tryno.
This commit is contained in:
@@ -28,6 +28,10 @@
|
||||
# "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.
|
||||
#
|
||||
# Example:
|
||||
# udp 1234 "payloaddatapayloaddata"
|
||||
# "payloaddatapayloaddata"
|
||||
|
||||
19
payload.cc
19
payload.cc
@@ -267,6 +267,9 @@ static int load_payloads_from_file(FILE *fp) {
|
||||
portPayload.data = payload_data;
|
||||
portPayloadVector.push_back(portPayload);
|
||||
portPayloads[key] = portPayloadVector;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +315,7 @@ 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, u8 tryno) {
|
||||
const char *udp_port2payload(u16 dport, size_t *length, u8 index) {
|
||||
static const char *payload_null = "";
|
||||
std::map<struct proto_dport, std::vector<struct payload> >::const_iterator portPayloadIterator;
|
||||
std::vector<struct payload>::const_iterator portPayloadVectorIterator;
|
||||
@@ -325,17 +328,17 @@ const char *udp_port2payload(u16 dport, size_t *length, u8 tryno) {
|
||||
const std::vector<struct payload>& portPayloadVector = portPayloads.find(key)->second;
|
||||
portPayloadVectorSize = portPayloadVector.size();
|
||||
|
||||
tryno %= portPayloadVectorSize;
|
||||
index %= portPayloadVectorSize;
|
||||
|
||||
if (portPayloadVectorSize > 0) {
|
||||
portPayloadVectorIterator = portPayloadVector.begin();
|
||||
|
||||
while (tryno > 0 && portPayloadVectorIterator != portPayloadVector.end()) {
|
||||
tryno--;
|
||||
while (index > 0 && portPayloadVectorIterator != portPayloadVector.end()) {
|
||||
index--;
|
||||
portPayloadVectorIterator++;
|
||||
}
|
||||
|
||||
assert (tryno == 0);
|
||||
assert (index == 0);
|
||||
assert (portPayloadVectorIterator != portPayloadVector.end());
|
||||
|
||||
*length = portPayloadVectorIterator->data.size();
|
||||
@@ -354,16 +357,16 @@ const char *udp_port2payload(u16 dport, size_t *length, u8 tryno) {
|
||||
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 tryno) {
|
||||
const char *get_udp_payload(u16 dport, size_t *length, u8 index) {
|
||||
if (o.extra_payload != NULL) {
|
||||
*length = o.extra_payload_length;
|
||||
return o.extra_payload;
|
||||
} else {
|
||||
return udp_port2payload(dport, length, tryno);
|
||||
return udp_port2payload(dport, length, index);
|
||||
}
|
||||
}
|
||||
|
||||
size_t udp_payload_count(u16 dport) {
|
||||
u8 udp_payload_count(u16 dport) {
|
||||
std::map<struct proto_dport, std::vector<struct payload> >::const_iterator portPayloadIterator;
|
||||
const proto_dport key(IPPROTO_UDP, dport);
|
||||
size_t portPayloadVectorSize = 0;
|
||||
|
||||
10
payload.h
10
payload.h
@@ -66,9 +66,13 @@
|
||||
|
||||
#define PAYLOAD_FILENAME "nmap-payloads"
|
||||
|
||||
const char *get_udp_payload(u16 dport, size_t *length, u8 tryno);
|
||||
const char *udp_port2payload(u16 dport, size_t *length, u8 tryno);
|
||||
size_t udp_payload_count(u16 dport);
|
||||
// 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 char *udp_port2payload(u16 dport, size_t *length, u8 index);
|
||||
u8 udp_payload_count(u16 dport);
|
||||
int init_payloads(void);
|
||||
|
||||
#endif /* PAYLOAD_H */
|
||||
|
||||
@@ -2454,15 +2454,12 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
||||
do {
|
||||
probeI--;
|
||||
probe = *probeI;
|
||||
if (probe->timedout && !probe->retransmitted &&
|
||||
(maxtries > probe->tryno ||
|
||||
// We may exceed maxtries if this is UDP...
|
||||
((USI->udp_scan || (USI->ping_scan && USI->ptech.rawudpscan))
|
||||
// ...and we haven't exceeded the manually-set max_retries
|
||||
&& USI->perf.tryno_cap > probe->tryno
|
||||
// ...and there are more payloads we haven't tried.
|
||||
&& udp_payload_count(probe->dport()) > probe->tryno)
|
||||
) && !probe->isPing()) {
|
||||
if (probe->retransmitted || probe->isPing()) {
|
||||
// Don't retransmit these
|
||||
continue;
|
||||
}
|
||||
// Retransmit if timed out and there are still tries remaining
|
||||
if (probe->timedout && maxtries > probe->tryno) {
|
||||
/* For rate limit detection, we delay the first time a new tryno
|
||||
is seen, as long as we are scanning at least 2 ports */
|
||||
if (probe->tryno + 1 > (int) host->rld.max_tryno_sent &&
|
||||
|
||||
@@ -1368,8 +1368,12 @@ UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
|
||||
} else if (pspec->type == PS_UDP) {
|
||||
const char *payload;
|
||||
size_t 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);
|
||||
|
||||
payload = get_udp_payload(pspec->pd.udp.dport, &payload_length, tryno);
|
||||
for (u8 i=0; i < numpayloads; i++) {
|
||||
payload = get_udp_payload(pspec->pd.udp.dport, &payload_length, i);
|
||||
|
||||
if (hss->target->af() == AF_INET) {
|
||||
for (decoy = 0; decoy < o.numdecoys; decoy++) {
|
||||
@@ -1402,6 +1406,7 @@ UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
|
||||
free(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pspec->type == PS_SCTP) {
|
||||
switch (pspec->pd.sctp.chunktype) {
|
||||
case SCTP_INIT:
|
||||
|
||||
Reference in New Issue
Block a user