nmap

    xiaoxiao2025-11-17  2

    <span style="font-family: 'microsoft yahei'; background-color: rgb(255, 255, 255);">转载自 http://blog.csdn.net/xundh/article/details/46591361</span>

    学习要点:

    学习要点:

    程序在1650行,新建一个主机的单例对象,

    #ifndef NOLUA /* Only NSE scripts can add targets */ NewTargets *new_targets = NULL; /* Pre-Scan and Post-Scan script results datastructure */ ScriptResults *script_scan_results = NULL; #endif

    从1680行开始主体程序。

    int nmap_main(int argc, char *argv[]) { int i; std::vector<Target *> Targets; time_t now; struct hostent *target = NULL; time_t timep; char mytime[128]; addrset exclude_group; #ifndef NOLUA /* Only NSE scripts can add targets */ NewTargets *new_targets = NULL; /* Pre-Scan and Post-Scan script results datastructure */ ScriptResults *script_scan_results = NULL; #endif unsigned int ideal_scan_group_sz = 0; Target *currenths; char myname[MAXHOSTNAMELEN + 1]; int sourceaddrwarning = 0; /* Have we warned them yet about unguessable source addresses? */ unsigned int targetno; char hostname[MAXHOSTNAMELEN + 1] = ""; struct sockaddr_storage ss; size_t sslen; now = time(NULL); local_time = localtime(&now); if (o.debugging) nbase_set_log(fatal, error); else nbase_set_log(fatal, NULL); if (argc < 2) printusage(-1); Targets.reserve(100); #ifdef WIN32 win_pre_init(); #endif //命令行参数解析 parse_options(argc, argv); //linux平台设置只读非阻塞 tty_init(); // Put the keyboard in raw mode //延迟处理的操作 apply_delayed_options(); #ifdef WIN32 win_init(); #endif /* 这里用到的变量route_dst_hosts是由参数 --route-dst debugging模式定义的目标列表。定义如下: static std::vector<std::string> route_dst_hosts; 前面命令行解析后会对其赋值。 */ for (unsigned int i = 0; i < route_dst_hosts.size(); i++) { const char *dst; struct sockaddr_storage ss; struct route_nfo rnfo; size_t sslen; int rc; dst = route_dst_hosts[i].c_str(); //解析目标 rc = resolve(dst, 0, &ss, &sslen, o.af()); if (rc != 0) fatal("Can't resolve %s: %s.", dst, gai_strerror(rc)); printf("%s\n", inet_ntop_ez(&ss, sslen)); if (!route_dst(&ss, &rnfo, o.device, o.SourceSockAddr())) { printf("Can't route %s (%s).", dst, inet_ntop_ez(&ss, sslen)); } else { printf("%s %s", rnfo.ii.devname, rnfo.ii.devfullname); printf(" srcaddr %s", inet_ntop_ez(&rnfo.srcaddr, sizeof(rnfo.srcaddr))); if (rnfo.direct_connect) printf(" direct"); else printf(" nexthop %s", inet_ntop_ez(&rnfo.nexthop, sizeof(rnfo.nexthop))); } printf("\n"); } route_dst_hosts.clear(); if (delayed_options.iflist) { print_iflist(); exit(0); } /* If he wants to bounce off of an FTP site, that site better damn well be reachable! */ // FTP bounce scan模式,nmap -b参数定义 if (o.bouncescan) { if (!inet_pton(AF_INET, ftp.server_name, &ftp.server)) { if ((target = gethostbyname(ftp.server_name))) memcpy(&ftp.server, target->h_addr_list[0], 4); else { fatal("Failed to resolve FTP bounce proxy hostname/IP: %s", ftp.server_name); } } else if (o.verbose) { log_write(LOG_STDOUT, "Resolved FTP bounce attack proxy to %s (%s).\n", ftp.server_name, inet_ntoa(ftp.server)); } } fflush(stdout); fflush(stderr); timep = time(NULL); /* Brief info in case they forget what was scanned */ //扫描的简要信息 记录到xml Strncpy(mytime, ctime(&timep), sizeof(mytime)); chomp(mytime); char *xslfname = o.XSLStyleSheet(); xml_start_document("nmaprun"); if (xslfname) { xml_open_pi("xml-stylesheet"); xml_attribute("href", "%s", xslfname); xml_attribute("type", "text/xsl"); xml_close_pi(); xml_newline(); } std::string command; if (argc > 0) command += argv[0]; for (i = 1; i < argc; i++) { command += " "; command += argv[i]; } xml_start_comment(); xml_write_escaped(" %s %s scan initiated %s as: %s ", NMAP_NAME, NMAP_VERSION, mytime, join_quoted(argv, argc).c_str()); xml_end_comment(); xml_newline(); // 记录扫描日志 log_write(LOG_NORMAL | LOG_MACHINE, "# "); log_write(LOG_NORMAL | LOG_MACHINE, "%s %s scan initiated %s as: ", NMAP_NAME, NMAP_VERSION, mytime); log_write(LOG_NORMAL | LOG_MACHINE, "%s", command.c_str()); log_write(LOG_NORMAL | LOG_MACHINE, "\n"); xml_open_start_tag("nmaprun"); xml_attribute("scanner", "nmap"); xml_attribute("args", "%s", join_quoted(argv, argc).c_str()); xml_attribute("start", "%lu", (unsigned long) timep); xml_attribute("startstr", "%s", mytime); xml_attribute("version", "%s", NMAP_VERSION); xml_attribute("xmloutputversion", NMAP_XMLOUTPUTVERSION); xml_close_start_tag(); xml_newline(); output_xml_scaninfo_records(&ports); xml_open_start_tag("verbose"); xml_attribute("level", "%d", o.verbose); xml_close_empty_tag(); xml_newline(); xml_open_start_tag("debugging"); xml_attribute("level", "%d", o.debugging); xml_close_empty_tag(); xml_newline(); /* Before we randomize the ports scanned, lets output them to machine parseable output */ // 在随机端口扫描前,把可以解析的端口输出机器 if (o.verbose) output_ports_to_machine_parseable_output(&ports); #if defined(HAVE_SIGNAL) && defined(SIGPIPE) signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE so our program doesn't crash because of it, but we really shouldn't get an unexpected SIGPIPE */ #endif if (o.max_parallelism && (i = max_sd()) && i < o.max_parallelism) { error("WARNING: Your specified max_parallel_sockets of %d, but your system says it might only give us %d. Trying anyway", o.max_parallelism, i); } // 端口号是否溢出 if (o.debugging > 1) log_write(LOG_STDOUT, "The max # of sockets we are using is: %d\n", o.max_parallelism); // At this point we should fully know our timing parameters if (o.debugging) { log_write(LOG_PLAIN, "--------------- Timing report ---------------\n"); log_write(LOG_PLAIN, " hostgroups: min %d, max %d\n", o.minHostGroupSz(), o.maxHostGroupSz()); log_write(LOG_PLAIN, " rtt-timeouts: init %d, min %d, max %d\n", o.initialRttTimeout(), o.minRttTimeout(), o.maxRttTimeout()); log_write(LOG_PLAIN, " max-scan-delay: TCP %d, UDP %d, SCTP %d\n", o.maxTCPScanDelay(), o.maxUDPScanDelay(), o.maxSCTPScanDelay()); log_write(LOG_PLAIN, " parallelism: min %d, max %d\n", o.min_parallelism, o.max_parallelism); log_write(LOG_PLAIN, " max-retries: %d, host-timeout: %ld\n", o.getMaxRetransmissions(), o.host_timeout); log_write(LOG_PLAIN, " min-rate: %g, max-rate: %g\n", o.min_packet_send_rate, o.max_packet_send_rate); log_write(LOG_PLAIN, "---------------------------------------------\n"); } //端口与地址初始化 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); // 打乱端口顺序 if (o.randomize_ports) { if (ports.tcp_count) { shortfry(ports.tcp_ports, ports.tcp_count); // move a few more common ports closer to the beginning to speed scan //常见端口往前放 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); } //--exclude_group 命令行参数的排除地址处理 addrset_init(&exclude_group); /* lets load our exclude list */ if (o.excludefd != NULL) { load_exclude_file(&exclude_group, o.excludefd); fclose(o.excludefd); } if (o.exclude_spec != NULL) { load_exclude_string(&exclude_group, o.exclude_spec); } if (o.debugging > 3) dumpExclude(&exclude_group); //NES 环境 #ifndef NOLUA if (o.scriptupdatedb) { o.max_ips_to_scan = o.numhosts_scanned; // disable warnings? } // 版本扫描 if (o.servicescan) o.scriptversion = 1; if (o.scriptversion || o.script || o.scriptupdatedb) open_nse(); /* Run the script pre-scanning phase */ // 预分析脚本 if (o.script) { new_targets = NewTargets::get(); script_scan_results = get_script_scan_results_obj(); script_scan(Targets, SCRIPT_PRE_SCAN); printscriptresults(script_scan_results, SCRIPT_PRE_SCAN); while (!script_scan_results->empty()) { script_scan_results->front().clear(); script_scan_results->pop_front(); } } #endif // hstate 是一个list,初始为空,循环执行后保存各主机表达式字符串地址 HostGroupState hstate(o.ping_group_sz, o.randomize_hosts, argc, (const char **) argv); // 主程序循环 do { // 计算host group大小 ideal_scan_group_sz = determineScanGroupSize(o.numhosts_scanned, &ports); // 主机发现成功,同加入到host group,再后续处理 while (Targets.size() < ideal_scan_group_sz) { o.current_scantype = HOST_DISCOVERY; // 主机发现 currenths = nexthost(&hstate, &exclude_group, &ports, o.pingtype); //如果没有发现主机,就进行下一次循环 if (!currenths) break; if (currenths->flags & HOST_UP && !o.listscan) o.numhosts_up++; if ((o.noportscan && !o.traceroute #ifndef NOLUA && !o.script #endif ) || o.listscan) { /* We're done with the hosts */ // 如果 命令行参数-sn(不进行端口扫描) 且没有指定traceroute和脚本的话,扫描结束 // 如果 -sL(只列出ip),扫描也结束。 if (currenths->flags & HOST_UP || (o.verbose && !o.openOnly())) { xml_start_tag("host"); write_host_header(currenths); printmacinfo(currenths); // if (currenths->flags & HOST_UP) // log_write(LOG_PLAIN,"\n"); printtimes(currenths); xml_end_tag(); xml_newline(); log_flush_all(); } delete currenths; o.numhosts_scanned++; continue; } // -S ip (配置要伪造的IP地址) if (o.spoofsource) { o.SourceSockAddr(&ss, &sslen); currenths->setSourceSockAddr(&ss, sslen); } /* I used to check that !currenths->weird_responses, but in some rare cases, such IPs CAN be port successfully scanned and even connected to */ // 一些情况下,主机有返回状态,全状态为HOST_DOWN if (!(currenths->flags & HOST_UP)) { if (o.verbose && (!o.openOnly() || currenths->ports.hasOpenPorts())) { xml_start_tag("host"); write_host_header(currenths); xml_end_tag(); xml_newline(); } delete currenths; o.numhosts_scanned++; continue; } //RawScan ,如SYN/FIN/ARP if (o.RawScan()) { if (currenths->SourceSockAddr(NULL, NULL) != 0) { if (o.SourceSockAddr(&ss, &sslen) == 0) { //直接设置IP currenths->setSourceSockAddr(&ss, sslen); } else { //解析主机名 if (gethostname(myname, MAXHOSTNAMELEN) || resolve(myname, 0, &ss, &sslen, o.af()) != 0) fatal("Cannot get hostname! Try using -S <my_IP_address> or -e <interface to scan through>\n"); o.setSourceSockAddr(&ss, sslen); currenths->setSourceSockAddr(&ss, sslen); if (! sourceaddrwarning) { error("WARNING: We could not determine for sure which interface to use, so we are guessing %s . If this is wrong, use -S <my_IP_address>.", inet_socktop(&ss)); sourceaddrwarning = 1; } } } // 网络设备(网卡)名称 if (!currenths->deviceName()) fatal("Do not have appropriate device name for target"); /* Hosts in a group need to be somewhat homogeneous. Put this host in the next group if necessary. See target_needs_new_hostgroup for the details of when we need to split. */ //同一个组内主机要是同性质的,这里判断目标是否加到list列表内 if (target_needs_new_hostgroup(Targets, currenths)) { returnhost(&hstate); o.numhosts_up--; break; } o.decoys[o.decoyturn] = currenths->v4source(); } Targets.push_back(currenths); } //没有发现主机 if (Targets.size() == 0) break; /* Couldn't find any more targets */ // Set the variable for status printing o.numhosts_scanning = Targets.size(); // Our source must be set in decoy list because nexthost() call can // change it (that issue really should be fixed when possible) if (o.af() == AF_INET && o.RawScan()) o.decoys[o.decoyturn] = Targets[0]->v4source(); /* I now have the group for scanning in the Targets vector */ // 定义了端口扫描,进入扫描的主体 if (!o.noportscan) { // Ultra_scan sets o.scantype for us so we don't have to worry if (o.synscan) ultra_scan(Targets, &ports, SYN_SCAN); if (o.ackscan) ultra_scan(Targets, &ports, ACK_SCAN); if (o.windowscan) ultra_scan(Targets, &ports, WINDOW_SCAN); if (o.finscan) ultra_scan(Targets, &ports, FIN_SCAN); if (o.xmasscan) ultra_scan(Targets, &ports, XMAS_SCAN); if (o.nullscan) ultra_scan(Targets, &ports, NULL_SCAN); if (o.maimonscan) ultra_scan(Targets, &ports, MAIMON_SCAN); if (o.udpscan) ultra_scan(Targets, &ports, UDP_SCAN); if (o.connectscan) ultra_scan(Targets, &ports, CONNECT_SCAN); if (o.sctpinitscan) ultra_scan(Targets, &ports, SCTP_INIT_SCAN); if (o.sctpcookieechoscan) ultra_scan(Targets, &ports, SCTP_COOKIE_ECHO_SCAN); if (o.ipprotscan) ultra_scan(Targets, &ports, IPPROT_SCAN); /* These lame functions can only handle one target at a time */ if (o.idlescan) { for (targetno = 0; targetno < Targets.size(); targetno++) { o.current_scantype = IDLE_SCAN; keyWasPressed(); // Check if a status message should be printed idle_scan(Targets[targetno], ports.tcp_ports, ports.tcp_count, o.idleProxy, &ports); } } if (o.bouncescan) { for (targetno = 0; targetno < Targets.size(); targetno++) { o.current_scantype = BOUNCE_SCAN; keyWasPressed(); // Check if a status message should be printed if (ftp.sd <= 0) ftp_anon_connect(&ftp); if (ftp.sd > 0) bounce_scan(Targets[targetno], ports.tcp_ports, ports.tcp_count, &ftp); } } if (o.servicescan) { o.current_scantype = SERVICE_SCAN; service_scan(Targets); } } if (o.osscan) { OSScan os_engine; os_engine.os_scan(Targets); } if (o.traceroute) traceroute(Targets); #ifndef NOLUA if (o.script || o.scriptversion) { script_scan(Targets, SCRIPT_SCAN); } #endif //输出扫描结果 for (targetno = 0; targetno < Targets.size(); targetno++) { currenths = Targets[targetno]; /* Now I can do the output and such for each host */ if (currenths->timedOut(NULL)) { xml_open_start_tag("host"); xml_attribute("starttime", "%lu", (unsigned long) currenths->StartTime()); xml_attribute("endtime", "%lu", (unsigned long) currenths->EndTime()); xml_close_start_tag(); write_host_header(currenths); xml_end_tag(); /* host */ xml_newline(); log_write(LOG_PLAIN, "Skipping host %s due to host timeout\n", currenths->NameIP(hostname, sizeof(hostname))); log_write(LOG_MACHINE, "Host: %s (%s)\tStatus: Timeout\n", currenths->targetipstr(), currenths->HostName()); } else { /* --open means don't show any hosts without open ports. */ if (o.openOnly() && !currenths->ports.hasOpenPorts()) continue; xml_open_start_tag("host"); xml_attribute("starttime", "%lu", (unsigned long) currenths->StartTime()); xml_attribute("endtime", "%lu", (unsigned long) currenths->EndTime()); xml_close_start_tag(); write_host_header(currenths); printportoutput(currenths, ¤ths->ports); printmacinfo(currenths); printosscanoutput(currenths); printserviceinfooutput(currenths); #ifndef NOLUA printhostscriptresults(currenths); #endif if (o.traceroute) printtraceroute(currenths); printtimes(currenths); log_write(LOG_PLAIN | LOG_MACHINE, "\n"); xml_end_tag(); /* host */ xml_newline(); } } log_flush_all(); o.numhosts_scanned += Targets.size(); /* Free all of the Targets */ while (!Targets.empty()) { currenths = Targets.back(); delete currenths; Targets.pop_back(); } o.numhosts_scanning = 0; } while (!o.max_ips_to_scan || o.max_ips_to_scan > o.numhosts_scanned); // 循环条件 #ifndef NOLUA if (o.script) { script_scan(Targets, SCRIPT_POST_SCAN); printscriptresults(script_scan_results, SCRIPT_POST_SCAN); while (!script_scan_results->empty()) { script_scan_results->front().clear(); script_scan_results->pop_front(); } delete new_targets; new_targets = NULL; } #endif addrset_free(&exclude_group); if (o.inputfd != NULL) fclose(o.inputfd); printdatafilepaths(); printfinaloutput(); free_scan_lists(&ports); eth_close_cached(); if (o.release_memory) { nmap_free_mem(); } return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-1304296.html
    最新回复(0)