nmap_rpc.cc

来自「Ubuntu packages of security software。 相」· CC 代码 · 共 661 行 · 第 1/2 页

CC
661
字号
      close(tcp_rpc_socket);      tcp_rpc_socket = -1;      return -1;    }  }  return 0;}static int rpc_are_we_done(char *msg, int msg_len, Target *target, 		    struct portinfo *scan, struct scanstats *ss, 		    struct portinfolist *pil, struct rpcscaninfo *rsi) {  struct rpc_hdr_rcv *rpc_pack;  unsigned long scan_offset;  int trynum;  struct portinfo *current;  if (rsi->rpc_current_port->state == PORT_OPENFILTERED) {    /* Received a packet, so this port is actually open */     target->ports.addPort(rsi->rpc_current_port->portno, 			   rsi->rpc_current_port->proto, NULL, PORT_OPEN);  }  rpc_pack = (struct rpc_hdr_rcv *) msg;       if (msg_len < 24 || msg_len > 32 || (msg_len < 32 && rpc_pack->accept_stat == PROG_MISMATCH)) {    /* This is not a valid reply -- we kill the port        (from an RPC perspective) */     if (o.debugging > 1) {      log_write(LOG_PLAIN, "Port %hu/%s labelled NON_RPC because of invalid sized message (%d)\n", 		rsi->rpc_current_port->portno, 		proto2ascii(rsi->rpc_current_port->proto, true), msg_len);    }    rsi->rpc_status = RPC_STATUS_NOT_RPC;    ss->numqueries_outstanding = 0;    return 1;  }  /* Now it is time to decode the scan offset */  scan_offset = ntohl(rpc_pack->xid);  scan_offset -= rpc_xid_base;  if (((scan_offset >> 16) & 0x3FFF) != (unsigned long) (rsi->rpc_current_port->portno & 0x3FFF)) {    /* Doh -- this doesn't seem right */    if (o.debugging > 1) {      log_write(LOG_PLAIN, "Port %hu/%s labelled NON_RPC because ((scan_offset >> 16) & 0x3FFF) is %li\n", rsi->rpc_current_port->portno, proto2ascii(rsi->rpc_current_port->proto, true), ((scan_offset >> 16) & 0x3FFF));    }    rsi->rpc_status = RPC_STATUS_NOT_RPC;    ss->numqueries_outstanding = 0;    return 1;  }  trynum = scan_offset >> 30;  scan_offset &= 0xFFFF;  if (scan_offset >= rsi->rpc_number) {    error("Invalid scan_offset returned in RPC packet");    rsi->rpc_status = RPC_STATUS_NOT_RPC;    ss->numqueries_outstanding = 0;    return 1;  }  if (ntohl(rpc_pack->type_msg) != RPC_MSG_REPLY) {    error("Strange -- RPC type is %lu should be RPC_MSG_REPLY (1)", (unsigned long) ntohl(rpc_pack->type_msg));    return 0;  }  if (ntohl(rpc_pack->auth_flavor) != 0 /* AUTH_NULL */ ||      ntohl(rpc_pack->opaque_length != 0)) {    error("Strange -- auth flavor/opaque_length are %lu/%lu should generally be 0/0", rpc_pack->auth_flavor, rpc_pack->opaque_length);    rsi->rpc_status = RPC_STATUS_NOT_RPC;    ss->numqueries_outstanding = 0;    return 1;  }  /* OK, now that we know what this is a response to, we delete the      appropriate entry from our scanlist */  current = &scan[scan_offset];     if (current->state != PORT_TESTING && current->state != PORT_CLOSED &&      current->state != PORT_FILTERED) {    error("Supposed scan_offset refers to port in state %s (should be testing, closed, or filtered)", statenum2str(current->state));    rsi->rpc_status = RPC_STATUS_NOT_RPC;    ss->numqueries_outstanding = 0;    return 1;  }       if (trynum > current->trynum) {    error("Bogus trynum %d when we are only up to %d in %s", trynum, current->trynum, __func__);    rsi->rpc_status = RPC_STATUS_NOT_RPC;    ss->numqueries_outstanding = 0;    return 1;  }  if (current->next > -1) scan[current->next].prev = current->prev;  if (current->prev > -1) scan[current->prev].next = current->next;  if (current == pil->testinglist)    pil->testinglist = (current->next >= 0)?  &scan[current->next] : NULL;  current->next = -1;  current->prev = -1;          /* Adjust timeouts ... */  adjust_timeouts(current->sent[trynum], &(target->to));       /* If a non-zero trynum finds a port that hasn't been discovered, the	earlier packets(s) were probably dropped.  So we decrease our 	numqueries_ideal, otherwise we increase it slightly */  if (trynum == 0) {    ss->numqueries_ideal = MIN(ss->numqueries_ideal + (ss->packet_incr/ss->numqueries_ideal), ss->max_width);  } else  {    if (!ss->alreadydecreasedqueries) {      ss->alreadydecreasedqueries = 1;      ss->numqueries_ideal *= ss->fallback_percent;      if (ss->numqueries_ideal < 1.0) ss->numqueries_ideal = 1.0;      if (o.debugging) 	{ 	  log_write(LOG_STDOUT, "Lost a packet, decreasing window to %d\n", (int) ss->numqueries_ideal);	}    }  }  if (current->state == PORT_TESTING)    ss->numqueries_outstanding--;       if (ntohl(rpc_pack->accept_stat) == PROG_UNAVAIL) {    current->state = PORT_CLOSED;    if (o.debugging > 1) {      error("Port %hu/%s claims that it is not RPC service %li", 	    rsi->rpc_current_port->portno, 	    proto2ascii(rsi->rpc_current_port->proto, true),  current->portno);    }    rsi->valid_responses_this_port++;    return 0;  } else if (ntohl(rpc_pack->accept_stat) == PROG_MISMATCH) {    if (o.debugging > 1) {      error("Port %hu/%s claims IT IS RPC service %li", rsi->rpc_current_port->portno, proto2ascii(rsi->rpc_current_port->proto, true),  current->portno);    }    current->state = PORT_OPEN;    rsi->rpc_status = RPC_STATUS_GOOD_PROG;    rsi->rpc_program = current->portno;    rsi->rpc_lowver = ntohl(rpc_pack->low_version);    rsi->rpc_highver = ntohl(rpc_pack->high_version);    rsi->valid_responses_this_port++;    ss->numqueries_outstanding = 0;    return 1;  } else if (ntohl(rpc_pack->accept_stat) == SUCCESS) {    error("Umm -- RPC returned success for bogus version -- thats OK I guess");    rsi->rpc_status = RPC_STATUS_GOOD_PROG;    rsi->rpc_program = current->portno;    rsi->rpc_lowver = rsi->rpc_highver = 0;    rsi->valid_responses_this_port++;    ss->numqueries_outstanding = 0;    return 1;  } else {    fatal("Illegal rpc accept_stat");  }  return 0;}void get_rpc_results(Target *target, struct portinfo *scan,		     struct scanstats *ss, struct portinfolist *pil, 		     struct rpcscaninfo *rsi) {int max_sd = -1;fd_set fds_r; int sres;struct timeval tv;int res;static char readbuf[512];struct sockaddr_in from;recvfrom6_t fromlen = sizeof(struct sockaddr_in);char *current_msg;unsigned long current_msg_len;  if ((udp_rpc_socket == -1 && tcp_rpc_socket == -1) || ss->numqueries_outstanding <= 0)   return; FD_ZERO(&fds_r); if (udp_rpc_socket >= 0 && rsi->rpc_current_port->proto == IPPROTO_UDP) {   FD_SET(udp_rpc_socket, &fds_r);   max_sd = udp_rpc_socket; } else if (tcp_rpc_socket >= 0 && rsi->rpc_current_port->proto == IPPROTO_TCP) {   FD_SET(tcp_rpc_socket, &fds_r);   if (tcp_rpc_socket > max_sd)     max_sd = tcp_rpc_socket; } else {   error("Unable to find listening socket in %s", __func__);   return; } while (ss->numqueries_outstanding > 0) {   /* Insure there is no timeout ... */   gettimeofday(&tv, NULL);   if (target->timedOut(&tv))       return;   tv.tv_sec = target->to.timeout / 1000000;   tv.tv_usec = target->to.timeout % 1000000;   sres = select(max_sd + 1, &fds_r, NULL, NULL, &tv);   if (!sres)     break;   if (sres == -1 && socket_errno() == EINTR)     continue;   if (udp_rpc_socket >= 0 && FD_ISSET(udp_rpc_socket, &fds_r)) {     res = recvfrom(udp_rpc_socket, readbuf, sizeof(readbuf), 0, (struct sockaddr *) &from, &fromlen);        if (res < 0) {       /* Doh! */       if (o.debugging || o.verbose)	 gh_perror("recvfrom in %s", __func__);       ss->numqueries_outstanding = 0;       rsi->rpc_status = RPC_STATUS_NOT_RPC;       return;     }     if (o.debugging > 1)       log_write(LOG_PLAIN, "Received %d byte UDP packet\n", res);     /* Now we check that the response is from the expected host/port */     if (from.sin_addr.s_addr != target->v4host().s_addr ||	 from.sin_port != htons(rsi->rpc_current_port->portno)) {       if (o.debugging > 1) {	 log_write(LOG_PLAIN, "Received UDP packet from %d.%d.%d.%d/%hu when expecting packet from %d.%d.%d.%d/%hu\n", NIPQUAD(from.sin_addr.s_addr), ntohs(from.sin_port), NIPQUAD(target->v4host().s_addr), rsi->rpc_current_port->portno);       }       continue;     }     if (rpc_are_we_done(readbuf, res, target, scan, ss, pil, rsi) != 0) {       return;     }   } else if (tcp_rpc_socket >= 0 && FD_ISSET(tcp_rpc_socket, &fds_r)) {     do {            res = recv(tcp_rpc_socket, readbuf + tcp_readlen, sizeof(readbuf) - tcp_readlen, 0);     } while(res == -1 && socket_errno() == EINTR);     if (res <= 0) {       if (o.debugging) {	 if (res == -1)	   gh_perror("Failed to read() from tcp rpc socket in %s", __func__);	 else {	   error("Lamer on port %u closed RPC socket on me in %s", rsi->rpc_current_port->portno, __func__);	 }       }       ss->numqueries_outstanding = 0;       rsi->rpc_status = RPC_STATUS_NOT_RPC;       return;     }     tcp_readlen += res;     if (tcp_readlen < 28) {       /* This is suspiciously small -- I'm assuming this is not the first	  part of a valid RPC packet */       if (o.debugging > 1) {	 log_write(LOG_PLAIN, "Port %hu/%s labelled NON_RPC because tcp_readlen is %d (should be at least 28)\n", 		   rsi->rpc_current_port->portno, 		   proto2ascii(rsi->rpc_current_port->proto, true), 		   (int) tcp_readlen);       }       ss->numqueries_outstanding = 0;       rsi->rpc_status = RPC_STATUS_NOT_RPC;       return;     }     /* I'm ignoring the multiple msg fragment possibility for now */     current_msg_len = ntohl((*(unsigned long *)readbuf)) & 0x7FFFFFFF;						          if (current_msg_len > tcp_readlen - 4) {       if (o.debugging > 1) {	 log_write(LOG_PLAIN, "Port %hu/%s labelled NON_RPC because current_msg_len is %li while tcp_readlen is %d\n",		   rsi->rpc_current_port->portno, 		   proto2ascii(rsi->rpc_current_port->proto, true), 		   current_msg_len, (int) tcp_readlen);       }       ss->numqueries_outstanding = 0;       rsi->rpc_status = RPC_STATUS_NOT_RPC;       return;     }     current_msg = readbuf + 4;     do {       if (rpc_are_we_done(current_msg, current_msg_len, target, scan, ss, 			   pil, rsi) != 0) 	 return;       current_msg += current_msg_len;       if ((current_msg - readbuf) + 4UL < tcp_readlen) {       	 current_msg_len = ntohl(*(unsigned long *) current_msg) & 0x7FFFFFFF;	 current_msg += 4;       } else {	 if ((unsigned long) (current_msg - readbuf) < tcp_readlen) {	   tcp_readlen -= current_msg - readbuf;	   memmove(readbuf, current_msg, tcp_readlen);	 } else tcp_readlen = 0;	 break;	          }       if (current_msg_len < 24 || current_msg_len > 32) {	 ss->numqueries_outstanding = 0;	 if (o.debugging > 1) {	   log_write(LOG_PLAIN, "Port %hu/%s labelled NON_RPC because current_msg_len is %li\n", 		     rsi->rpc_current_port->portno, 		     proto2ascii(rsi->rpc_current_port->proto, true), 		     current_msg_len);	 }	 rsi->rpc_status = RPC_STATUS_NOT_RPC;	 return;       }       if ((current_msg - readbuf) + current_msg_len > tcp_readlen) {	 tcp_readlen -= current_msg - readbuf;	 memmove(readbuf +4 , current_msg, tcp_readlen);	 *(unsigned long *)&readbuf = htonl(current_msg_len);	 tcp_readlen += 4;	 break;       }     } while(1);   } } return;}void close_rpc_query_sockets() {  if (udp_rpc_socket != -1) {    close(udp_rpc_socket);    udp_rpc_socket = -1;  }  if (tcp_rpc_socket != -1) {    close(tcp_rpc_socket);    tcp_rpc_socket = -1;  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?