nmap_dns.cc

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

CC
1,321
字号
  std::list<request *>::iterator nextI;  dns_server *tpserv;  request *tpreq;  struct timeval now;  int tp, min_timeout = INT_MAX;  memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval));  if (keyWasPressed())    SPM->printStats((double) (stat_ok + stat_nx + stat_dropped) / stat_actual, &now);  for(servI = servs.begin(); servI != servs.end(); servI++) {    tpserv = *servI;    nextI = tpserv->in_process.begin();    if (nextI == tpserv->in_process.end()) continue;    do {      reqI = nextI++;      tpreq = *reqI;      tp = TIMEVAL_MSEC_SUBTRACT(tpreq->timeout, now);      if (tp > 0 && tp < min_timeout) min_timeout = tp;      if (tp <= 0) {        tpserv->capacity = (int) (tpserv->capacity * CAPACITY_MINOR_DOWN_SCALE);        check_capacities(tpserv);        tpserv->in_process.erase(reqI);        tpserv->reqs_on_wire--;        // If we've tried this server enough times, move to the next one        if (read_timeouts[read_timeout_index][tpreq->tries] == -1) {          tpserv->capacity = (int) (tpserv->capacity * CAPACITY_MAJOR_DOWN_SCALE);          check_capacities(tpserv);          servItemp = servI;          servItemp++;          if (servItemp == servs.end()) servItemp = servs.begin();          tpreq->curr_server = *servItemp;          tpreq->tries = 0;          tpreq->servers_tried++;          if (tpreq->curr_server == tpreq->first_server || tpreq->servers_tried == SERVERS_TO_TRY) {            // Either give up on the IP            // or, for maximum reliability, put the server back into processing            // Note it's possible that this will never terminate.            // FIXME: Find a good compromise            // **** We've already tried all servers... give up            if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: *DR*OPPING <%s>\n", tpreq->targ->targetipstr());            output_summary();            stat_dropped++;            total_reqs--;            delete tpreq;            // **** OR We start at the back of this server's queue            //(*servItemp)->to_process.push_back(tpreq);          } else {            (*servItemp)->to_process.push_back(tpreq);          }        } else {          tpserv->to_process.push_back(tpreq);        }    }    } while (nextI != tpserv->in_process.end());  }  if (min_timeout > 500) return 500;  else return min_timeout;}// After processing a DNS response, we search through the IPs we're// looking for and update their results as necessary.// Returns non-zero if this matches a query we're looking forstatic int process_result(u32 ia, char *result, int action, u16 id) {  std::list<dns_server *>::iterator servI;  std::list<request *>::iterator reqI;  dns_server *tpserv;  request *tpreq;  for(servI = servs.begin(); servI != servs.end(); servI++) {    tpserv = *servI;    for(reqI = tpserv->in_process.begin(); reqI != tpserv->in_process.end(); reqI++) {      tpreq = *reqI;      if (id == tpreq->id) {        if (ia != 0 && tpreq->targ->v4host().s_addr != ia)          continue;        if (action == ACTION_CNAME_LIST || action == ACTION_FINISHED) {        tpserv->capacity += CAPACITY_UP_STEP;        check_capacities(tpserv);        if (result) {          tpreq->targ->setHostName(result);          addto_etchosts(tpreq->targ->v4hostip()->s_addr, result);        }        tpserv->in_process.remove(tpreq);        tpserv->reqs_on_wire--;        total_reqs--;          if (action == ACTION_CNAME_LIST) cname_reqs.push_back(tpreq);          if (action == ACTION_FINISHED) delete tpreq;        } else {          memcpy(&tpreq->timeout, nsock_gettimeofday(), sizeof(struct timeval));          deal_with_timedout_reads();        }        do_possible_writes();        // Close DNS servers if we're all done so that we kill        // all events and return from nsock_loop immediatley        if (total_reqs == 0)          close_dns_servers();        return 1;      }    }  }  return 0;}// Gets an IP address from a X.X.X.X.in-addr.arpa DNS// encoded string inside a packet.// maxlen is the very maximum length (in total bytes)// that should be processedstatic u32 parse_inaddr_arpa(unsigned char *buf, int maxlen) {  u32 ip=0;  int i, j;  if (maxlen <= 0) return 0;  for (i=0; i<=3; i++) {    if (buf[0] < 1 || buf[0] > 3) return 0;    maxlen -= buf[0] + 1;    if (maxlen <= 0) return 0;    for (j=1; j<=buf[0]; j++) if (!isdigit(buf[j])) return 0;    ip |= atoi((char *) buf+1) << (8*i);    buf += buf[0] + 1;  }  if (maxlen < 14) return 0; // length of the following string  if (strcasecmp((char *) buf, "\x07in-addr\004arpa\0")) return 0;  return ntohl(ip);}// Turns a DNS packet encoded name (see the RFC) and turns it into// a normal decimal separated hostname.// ASSUMES NAME LENGTH/VALIDITY HAS ALREADY BEEN VERIFIEDstatic int encoded_name_to_normal(unsigned char *buf, char *output, int outputsize){  while (buf[0]) {    if (buf[0] >= outputsize-1) return -1;    memcpy(output, buf+1, buf[0]);    outputsize -= buf[0];    output += buf[0];    buf += buf[0]+1;    if (buf[0]) {      *output++ = '.';      outputsize--;    } else {      *output = '\0';    }  }  return 0;}// Takes a pointer to the start of a DNS name inside a packet. It makes// sure that there is enough space in the name, deals with compression, etc.static int advance_past_dns_name(u8 *buf, int buflen, int curbuf, 			  int *nameloc) {  int compression=0;  if (curbuf <= 0 || curbuf >= buflen) return -1;  if ((buf[curbuf] & 0xc0)) {    // Need 2 bytes for compression info    if (curbuf + 1 >= buflen) return -1;    // Compression is OK    compression = curbuf+2;    curbuf = (buf[curbuf+1] + (buf[curbuf] << 8)) & 0x3FFF;    if (curbuf < 0 || curbuf >= buflen) return -1;  }  if (nameloc != NULL) *nameloc = curbuf;  while(buf[curbuf]) {    if (curbuf + buf[curbuf] >= buflen || buf[curbuf] <= 0) return -1;    curbuf += buf[curbuf] + 1;  }  if (compression) return compression;  else return curbuf+1;}// Nsock read handler. One nsock read for each DNS server exists at each// time. This function uses various helper functions as defined above.static void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) {  u8 *buf;  int buflen, curbuf=0;  int i, nameloc, rdlen, atype, aclass;  int errcode=0;  int queries, answers;  u16 packet_id;  if (total_reqs >= 1)    nsock_read(nsp, nse_iod(evt), read_evt_handler, -1, NULL);  if (nse_type(evt) != NSE_TYPE_READ || nse_status(evt) != NSE_STATUS_SUCCESS) {    if (o.debugging)      log_write(LOG_STDOUT, "mass_dns: warning: got a %s:%s in %s()\n",        nse_type2str(nse_type(evt)),        nse_status2str(nse_status(evt)), __func__);    return;  }  buf = (unsigned char *) nse_readbuf(evt, &buflen);  // Size of header is 12, and we must have additional data as well  if (buflen <= 12) return;  packet_id = buf[1] + (buf[0] << 8);  // Check that this is a response, standard query, and that no truncation was performed  // 0xFA == 11111010 (we're not concerned with AA or RD bits)  if ((buf[2] & 0xFA) != 0x80) return;  // Check that the zero field is all zeros and there is no error condition.  // We don't care if recursion is available or not since we might be querying  // an authoritative DNS server.  if (buf[3] != 0x80 && buf[3] != 0) {    if ((buf[3] & 0xF) == 2) errcode = 2;    else if ((buf[3] & 0xF) == 3) errcode = 3;    else return;  }  queries = buf[5] + (buf[4] << 8);  answers = buf[7] + (buf[6] << 8);  // With a normal resolution, we should have 1+ queries and 1+ answers.  // If the domain doesn't resolve (NXDOMAIN or SERVFAIL) we should have  // 1+ queries and 0 answers:  if (errcode) {    int found;    // NXDomain means we're finished (doesn't exist for sure)    // but SERVFAIL might just mean a server timeout    found = process_result(0, NULL, errcode == 3 ? ACTION_FINISHED : ACTION_TIMEOUT, packet_id);    if (errcode == 2 && found) {      if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: SERVFAIL <id = %d>\n", packet_id);      stat_sf++;    } else if (errcode == 3 && found) {      if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: NXDOMAIN <id = %d>\n", packet_id);      output_summary();      stat_nx++;  }    return;  }  if (queries <= 0 || answers <= 0) return;  curbuf = 12;  // Need to safely skip past QUERY section  for (i=0; i<queries; i++) {    curbuf = advance_past_dns_name(buf, buflen, curbuf, &nameloc);    if (curbuf == -1) return;    // Make sure we have the QTYPE and QCLASS fields    if (curbuf + 4 >= buflen) return;    curbuf += 4;      }  // We're now at the ANSWER section  for (i=0; i<answers; i++) {    curbuf = advance_past_dns_name(buf, buflen, curbuf, &nameloc);    if (curbuf == -1) return;    // Make sure we have the TYPE (2), CLASS (2), TTL (4), and    // RDLENGTH (2) fields    if (curbuf + 10 >= buflen) return;    atype = buf[curbuf+1] + (buf[curbuf+0] << 8);    aclass = buf[curbuf+3] + (buf[curbuf+2] << 8);    rdlen = buf[curbuf+9] + (buf[curbuf+8] << 8);    curbuf += 10;    if (atype == 12 && aclass == 1) {      // TYPE 12 is PTR      struct in_addr ia;      char outbuf[512];      ia.s_addr = parse_inaddr_arpa(buf+nameloc, buflen-nameloc);      if (ia.s_addr == 0) return;      curbuf = advance_past_dns_name(buf, buflen, curbuf, &nameloc);      if (curbuf == -1 || curbuf > buflen) return;      if (encoded_name_to_normal(buf+nameloc, outbuf, sizeof(outbuf)) == -1) return;      if (process_result(ia.s_addr, outbuf, ACTION_FINISHED, packet_id)) {        if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: OK MATCHED <%s> to <%s>\n", inet_ntoa(ia), outbuf);        output_summary();        stat_ok++;      }    } else if (atype == 5 && aclass == 1) {      // TYPE 5 is CNAME      struct in_addr ia;      ia.s_addr = parse_inaddr_arpa(buf+nameloc, buflen-nameloc);      if (ia.s_addr == 0) return;      if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: CNAME found for <%s>\n", inet_ntoa(ia));      process_result(ia.s_addr, NULL, ACTION_CNAME_LIST, packet_id);    } else {      if (rdlen < 0 || rdlen + curbuf >= buflen) return;      curbuf += rdlen;    }    if (curbuf >= buflen) return;  }}// nsock connect handler - Empty because it doesn't really need to do anything...static void connect_evt_handler(nsock_pool nsp, nsock_event evt, void *servers) {}// Adds DNS servers to the dns_server list. They can be separated by// commas or spaces - NOTE this doesn't actually do any connecting!static void add_dns_server(char *ipaddrs) {  std::list<dns_server *>::iterator servI;  dns_server *tpserv;  char *hostname;  struct sockaddr_in addr;  size_t addr_len = sizeof(addr);  for (hostname = strtok(ipaddrs, " ,"); hostname != NULL; hostname = strtok(NULL, " ,")) {    if (!resolve(hostname, (struct sockaddr_storage *) &addr, &addr_len, PF_INET)) continue;    for(servI = servs.begin(); servI != servs.end(); servI++) {      tpserv = *servI;      // Already added!      if (memcmp(&addr, &tpserv->addr, sizeof(addr)) == 0) break;    }    // If it hasn't already been added, add it!    if (servI == servs.end()) {      tpserv = new dns_server;      tpserv->hostname = strdup(hostname);      memcpy(&tpserv->addr, &addr, sizeof(addr));      servs.push_front(tpserv);      if (o.debugging) log_write(LOG_STDOUT, "mass_rdns: Using DNS server %s\n", hostname);    }  }}void free_dns_servers() {  std::list<dns_server *>::iterator servI;  dns_server *tpserv;  for(servI = servs.begin(); servI != servs.end();servI++){    tpserv = *servI;    if(tpserv){      if(tpserv->hostname)        free(tpserv->hostname);      delete tpserv;    }  }  servs.clear();}// Creates a new nsi for each DNS serverstatic void connect_dns_servers() {  std::list<dns_server *>::iterator serverI;  dns_server *s;  for(serverI = servs.begin(); serverI != servs.end(); serverI++) {    s = *serverI;    s->nsd = nsi_new(dnspool, NULL);    s->reqs_on_wire = 0;    s->capacity = CAPACITY_MIN;    s->write_busy = 0;    nsock_connect_udp(dnspool, s->nsd, connect_evt_handler, NULL, (struct sockaddr *) &s->addr, sizeof(struct sockaddr), 53);    nsock_read(dnspool, s->nsd, read_evt_handler, -1, NULL);    s->connected = 1;  }}#ifdef WIN32void win32_read_registry(char *controlset) {  HKEY hKey;  HKEY hKey2;  char keybasebuf[2048];  char buf[2048], keyname[2048], *p;  DWORD sz, i;  Snprintf(keybasebuf, sizeof(keybasebuf), "SYSTEM\\%s\\Services\\Tcpip\\Parameters", controlset);  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keybasebuf,                    0, KEY_READ, &hKey) != ERROR_SUCCESS) {    if (firstrun) error("mass_dns: warning: Error opening registry to read DNS servers. Try using --system-dns or specify valid servers with --dns-servers");    return;  }

⌨️ 快捷键说明

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