1 #!/usr/bin/env python 2 # -*- coding: utf_8 -*- 3 # Date: 2015年10月23日 4 # Author:蔚藍行 5 # 博客 http://www.cnblogs.com/duanv/ 6 7 from IPy import IP 8 import threading 9 import nmap 10 import time 11 import sys 12 import subprocess 13 from xml.dom import minidom 14 15 def usage(): 16 print 'The script requires root privileges!' 17 print 'example:python scan.py 192.168.0.1/24' 18 19 #生成xml文件的模板函數 20 def addResult(newresult): 21 global doc 22 global scan_result 23 24 ip = doc.createElement("ip") 25 ip.setAttribute("address", newresult["address"]) 26 27 osclass = doc.createElement("osclass") 28 osclass.appendChild(doc.createTextNode(newresult["osclass"])) 29 ip.appendChild(osclass) 30 31 port = doc.createElement("port") 32 33 tcp = doc.createElement("tcp") 34 tcp.appendChild(doc.createTextNode(newresult["tcp"])) 35 port.appendChild(tcp) 36 37 udp = doc.createElement("udp") 38 udp.appendChild(doc.createTextNode(newresult["udp"])) 39 port.appendChild(udp) 40 41 ip.appendChild(port) 42 scan_result.appendChild(ip) 43 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 59 60 #循環,遍歷未掃描的IP 61 def loop(): 62 global mutex 63 global ipx 64 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)) 77 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() 87 88 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 100 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) 112 113 #初始化參數 114 ipx=[] 115 nm=nmap.PortScanner() 116 mutex=threading.Lock() 117 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] 124 125 print("please wait...") 126 #計算時間 127 time_start=time.time() 128 #創建線程 129 creat_threads() 130 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 137 138 #xml文件操作 139 f = file("scan_result.xml","w") 140 f.write(doc.toprettyxml(indent = "\t", newl = "\n", encoding = "utf-8")) 141 f.close() 142 143 if __name__=='__main__': 144 start()