目录功能:
docs :相关文档 
 libdnet-stripped :开源网络接口库 
 liblinear:开源大型线性分类库 
 liblua:开源Lua脚本语言库 
 libnetutil:基本的网络函数 
 libpcap:开源抓包库 
 libpcre:开源正则表达式库 
 macosx:xcode项目文件 
 mswin32:vs项目文件 
 nbase:Nmap封装的基础使用函数库 
 ncat:netcat网络工具,由Nmap实现 
 ndiff:比较Nmap扫描结果的实用命令 
 nmap-update:负责Nmap更新操作 
 nping:Nmap项目组实现的新版的Hping,探测与构建包 
 nselib:Nmap的Lua脚本 
 nsock:Nmap实现的并行的SocketEvent处理库 
 scripts:Nmap提供常用的扫描检查的lua脚本 
 todo:开发任务 
 zenmap:python的图形界面程序
主体程序逻辑
入口程序在main.cc,主要功能
- 检查环境变量NMAP_ARGS
 - 检查有没有–resume参数
 - 判断是resume之前扫描,还是新请求
 
然后是根据传入参数去调用 nmap.cc的nmap_main()函数。下面是精简后的源码:
int main(int argc, char *argv[]) {
  char command[2048];
  int myargc;
  char **myargv = NULL;
  char *cptr;
  int ret;
  int i;
  set_program_name(argv[0]);
  if ((cptr = getenv("NMAP_ARGS"))) {
    if (Snprintf(command, sizeof(command), "nmap %s", cptr) >= (int) sizeof(command)) {
        error("Warning: NMAP_ARGS variable is too long, truncated");
    }
    /* copy rest of command-line arguments */
    for (i = 1; i < argc && strlen(command) + strlen(argv[i]) + 1 < sizeof(command); i++) {
      strcat(command, " ");
      strcat(command, argv[i]);
    }
    myargc = arg_parse(command, &myargv);
    if (myargc < 1) {
      fatal("NMAP_ARGS variable could not be parsed");
    }
    ret = nmap_main(myargc, myargv);
    arg_parse_free(myargv);
    return ret;
  }
  if (argc == 3 && strcmp("--resume", argv[1]) == 0) {
    if (gather_logfile_resumption_state(argv[2], &myargc, &myargv) == -1) {
      fatal("Cannot resume from (supposed) log file %s", argv[2]);
    }
    return nmap_main(myargc, myargv);
  }
  return nmap_main(argc, argv);
}然后程序教育nmap_main(). 
 nmap_main里,表面看起来扫描的循环是从2065行开始:
for (targetno = 0; targetno < Targets.size(); targetno++) { 
 currenths = Targets[targetno]; 
 前后的代码都比较多,下次再抽时间细致分析。
这里引用一个别人做的流程图: 
引用网址: 
                
                










