15 def usage(): 16 print ' The script requires root privileges! ' 17 print ' example:python scan.py 192.168.0.1/24 ' 19 # 生成xml文件的模板函数 20 def addResult(newresult): 21 global doc 22 global scan_result 24 ip = doc.createElement( " ip " ) 25 ip.setAttribute( " address " , newresult[ " address " ]) 27 osclass = doc.createElement( " osclass " ) 28 osclass.appendChild(doc.createTextNode(newresult[ " osclass " ])) 29 ip.appendChild(osclass) 31 port = doc.createElement( " port " ) 33 tcp = doc.createElement( " tcp " ) 34 tcp.appendChild(doc.createTextNode(newresult[ " tcp " ])) 35 port.appendChild(tcp) 37 udp = doc.createElement( " udp " ) 38 udp.appendChild(doc.createTextNode(newresult[ " udp " ])) 39 port.appendChild(udp) 41 ip.appendChild(port) 42 scan_result.appendChild(ip) 44 # 扫描函数,调用nmap库 45 def ip_scan(ip): 46 global nm 47 # 这里调用系统ping命令来判断主机存活 48 p = subprocess.Popen( " ping -c 1 -t 1 " +ip,stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True) 49 out = p.stdout.read() 50 # 如过没有100%丢包则主机存活,对是否丢包的判断是抓取系统回显内容,测试用的是‘MAC OS X’系统,抓取内容为‘100.0% packet loss’ 51 if ' 100.0% packet loss ' not in out: 52 try : 53 # 调用nmap扫描主机操作系统,同时进行SYN扫描和UDP扫描探测开放的端口 54 nm.scan(ip,arguments= ' -O -sS -sU -F ' ) 55 sr={ ' address ' :ip, ' osclass ' :str(nm[ip][ ' osclass ' ])[1:-1], ' tcp ' :str(nm[ip].all_tcp())[1:-1], ' udp ' :str(nm[ip].all_udp())[1:-1 ]} 56 addResult(sr) 57 except : 58 pass 60 # 循环,遍历未扫描的IP 61 def loop(): 62 global mutex 63 global ipx 65 while 1 : 66 # 线程锁,扫描一个IP就将IPX列表中的该IP移除 67 mutex.acquire() 68 # 如果列表中没有IP,则跳出循环结束该线程 69 if len(ipx)<= 0: 70 mutex.release() 71 break 72 ip= ipx[0] 73 ipx.remove(ipx[0]) 74 mutex.release() 75 # 调用扫描函数 76 ip_scan(str(ip)) 78 # 创建线程的函数,默认创建40个 79 def creat_threads(): 80 threads= [] 81 for i in range(40 ): 82 threads.append(threading.Thread(target= loop,)) 83 for t in threads: 84 t.start() 85 for t in threads: 86 t.join() 89 def start(): 90 # mutex:线程锁 91 global mutex 92 # ipx:存储要扫描的IP地址段列表 93 global ipx 94 # nm:nmap模块扫描对象 95 global nm 96 # doc:xml文档对象 97 global doc 98 # scan_result:xml文档的根元素 99 global scan_result 101 if ' -h ' == sys.argv[1 ]: 102 usage() 103 exit() 104 else : 105 # 获取命令行输入的要扫描的IP段 106 ip=sys.argv[1 ] 107 # xml文档一些对象的初始化 108 doc = minidom.Document() 109 doc.appendChild(doc.createComment( " scan_result xml. " )) 110 scan_result = doc.createElement( " scan_result " ) 111 doc.appendChild(scan_result) 113 # 初始化参数 114 ipx= [] 115 nm= nmap.PortScanner() 116 mutex= threading.Lock() 118 # 调用IPy模块的IP函数,将IP地址段的每个IP存入列表 119 ipp=IP(ip, make_net= True) 120 for x in ipp: 121 ipx.append(x) 122 # 去掉首尾代表子网和全部主机的IP 123 ipx=ipx[1:-1 ] 125 print ( " please wait... " ) 126 # 计算时间 127 time_start= time.time() 128 # 创建线程 129 creat_threads() 131 time_end= time.time() 132 t=time_end- time_start 133 print ' * ' *48 134 print ' \nTime: ' +str(t)+ ' s ' 135 print ' Scan results have been saved to scan_result.xml.\n ' 136 print ' * ' *48 138 # xml文件操作 139 f = file( " scan_result.xml " , " w " ) 140 f.write(doc.toprettyxml(indent = " \t " , newl = " \n " , encoding = " utf-8 " )) 141 f.close() 143 if __name__ == ' __main__ ' : 144 start()