一、环境

nmap-7.80


二、扫描前准备

2.1 初始化默认值

NmapOps o;//全局类对象

//构造函数
NmapOps::NmapOps() {
  datadir = NULL;
  xsl_stylesheet = NULL;
  Initialize(); 
}

//构造函数中调用 Initialize 函数,进行类对象成员初始化,设置默认值
void NmapOps::Initialize() {
     ...
     isr00t //是否为root权限运行
     randomize_ports = true; //随机端口
     fastscan = false; //禁止快速扫描
     ...
     osscan = false; //禁止扫描操作系统
     servicescan = false;
     ...
     pingtype = PINGTYPE_UNKNOWN;
     ...
     /*禁用各种扫描*/
     listscan = ackscan = bouncescan = connectscan = 0;
     nullscan = xmasscan = fragscan = synscan = windowscan = 0;
     maimonscan = idlescan = finscan = udpscan = ipprotscan = 0;
     noportscan = noresolve = false;
     sctpinitscan = 0;
     sctpcookieechoscan = 0;
     append_output = false;
     ...
     implicitARPPing = true;
     ...
     topportlevel = -1;
 }


2.2 解析用户参数,设置相应值

// -s(X) 设置各种扫描方式
 case 's':
     ...
      p = optarg;
      while (*p) {
        switch (*p) {
        ...
        case 'n':
          o.noportscan = true;
          break;
        case 'A':
          o.ackscan = true;
          break;
        ...
        case 'F':
          o.finscan = 1;
          break;
        case 'L':
          o.listscan = true;
          o.noportscan = true;
          o.pingtype |= PINGTYPE_NONE;
          break;
        case 'M':
          o.maimonscan = 1;
          break;
        case 'N':
          o.nullscan = 1;
          break;
        case 'O':
          o.ipprotscan = 1;
          break;
          /* Alias for -sV since March 2011. */
        case 'R':
          o.servicescan = true;
          delayed_options.warn_deprecated("sR", "sV");
          error("WARNING: -sR is now an alias for -sV and activates version detection as well as RPC scan.");
          break;
        case 'S':
          o.synscan = 1;
          break;
        case 'T':
          o.connectscan = 1;
          break;
        case 'U':
          o.udpscan++;
          break;
        case 'V':
          o.servicescan = true;
          break;
          ...
         }
       } 
       
       
  //指定端口
   case 'p':
      ...
      o.portlist = strdup(optarg);
      break;
      
      
  //指定ping端口,用于主机发现
  case 'P':
      ...
      else if (*optarg == 'S') {
        ...
        o.pingtype |= (PINGTYPE_TCP | PINGTYPE_TCP_USE_SYN);
        if (*(optarg + 1) != '\0') {
          getpts_simple(optarg + 1, SCAN_TCP_PORT, &ports.syn_ping_ports, &ports.syn_ping_count);
          ...
        } else {
          getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &ports.syn_ping_ports, &ports.syn_ping_count);
          ...
        }
      } else if (*optarg == 'T' || *optarg == 'A') {
        ...
        o.pingtype |= (PINGTYPE_TCP | PINGTYPE_TCP_USE_ACK);
        if (*(optarg + 1) != '\0') {
          getpts_simple(optarg + 1, SCAN_TCP_PORT, &ports.ack_ping_ports, &ports.ack_ping_count);
          ...
        } else {
          getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &ports.ack_ping_ports, &ports.ack_ping_count);
          ...
        }
      } else if (*optarg == 'U') {
           ...
        o.pingtype |= (PINGTYPE_UDP);
        if (*(optarg + 1) != '\0') {
          getpts_simple(optarg + 1, SCAN_UDP_PORT, &ports.udp_ping_ports, &ports.udp_ping_count);
         ...
        } else {
          getpts_simple(DEFAULT_UDP_PROBE_PORT_SPEC, SCAN_UDP_PORT, &ports.udp_ping_ports, &ports.udp_ping_count);
         ..
        }
      } else if (*optarg == 'Y') {
      ...
        o.pingtype |= (PINGTYPE_SCTP_INIT);
        if (*(optarg + 1) != '\0') {
          getpts_simple(optarg + 1, SCAN_SCTP_PORT, &ports.sctp_ping_ports, &ports.sctp_ping_count);
        ...
        } else {
          getpts_simple(DEFAULT_SCTP_PROBE_PORT_SPEC, SCAN_SCTP_PORT, &ports.sctp_ping_ports, &ports.sctp_ping_count);
         ...
        }
      } else if (*optarg == 'B') {
        ...
        o.pingtype = DEFAULT_IPV4_PING_TYPES;
        if (*(optarg + 1) != '\0') {
          getpts_simple(optarg + 1, SCAN_TCP_PORT, &ports.ack_ping_ports, &ports.ack_ping_count);
         ...
        } else {
          getpts_simple(DEFAULT_TCP_PROBE_PORT_SPEC, SCAN_TCP_PORT, &ports.ack_ping_ports, &ports.ack_ping_count);
          ...
        }
      } else if (*optarg == 'O') {
        ...
        o.pingtype |= PINGTYPE_PROTO;
        if (*(optarg + 1) != '\0') {
          getpts_simple(optarg + 1, SCAN_PROTOCOLS, &ports.proto_ping_ports, &ports.proto_ping_count);
         ...
        } else {
          getpts_simple(DEFAULT_PROTO_PROBE_PORT_SPEC, SCAN_PROTOCOLS, &ports.proto_ping_ports, &ports.proto_ping_count);
         ...
        }
      } else {
        fatal("Illegal Argument to -P, use -Pn, -PE, -PS, -PA, -PP, -PM, -PU, -PY, or -PO");
      }
      break;

    

2.3 端口处理

    (1)排除掉不扫描端口

 removepts(o.exclude_portlist, &ports);

    

    (2) 初始化 PortList 类

 if (o.ipprotscan)
    PortList::initializePortMap(IPPROTO_IP,  ports.prots, ports.prot_count);
  if (o.TCPScan())
    PortList::initializePortMap(IPPROTO_TCP, ports.tcp_ports, ports.tcp_count);
  if (o.UDPScan())
    PortList::initializePortMap(IPPROTO_UDP, ports.udp_ports, ports.udp_count);
  if (o.SCTPScan())
    PortList::initializePortMap(IPPROTO_SCTP, ports.sctp_ports, ports.sctp_count);


    (3) 将端口随机化

 case 'r':
      o.randomize_ports = false; //默认为true
      
 //如果没有设置-r 选项, 则将端口随机化
   if (ports.tcp_count) {
      shortfry(ports.tcp_ports, ports.tcp_count);
      // 将众所周知的端口移动到最前面
      random_port_cheat(ports.tcp_ports, ports.tcp_count);
    }
    if (ports.udp_count)
      shortfry(ports.udp_ports, ports.udp_count);
    if (ports.sctp_count)
      shortfry(ports.sctp_ports, ports.sctp_count);
    if (ports.prot_count)
      shortfry(ports.prots, ports.prot_count);