您的位置:首页 > 编程语言 > Python开发

python实现简单Nmap扫描

2012-08-19 20:45 666 查看
#!/usr/bin/env python
# _*_ coding:utf-8 _*_

import sys
import struct
import time
import array
import string
import getopt
import binascii
import threading
import socket
import select
import threading
import subprocess
from Queue import Queue

#设ICMP定包头字段初始值
ICMP_DATA_STR = 56
#total size of data
ICMP_TYPE = 8
#initital values of header variables
ICMP_TYPE_IP6 = 128
#ipv6
ICMP_CODE = 0
ICMP_CHECKSUM = 0
#校验和值
ICMP_ID = 0
ICMP_SEQ_NR = 0
#序列号值

def _construct(id , size , ipv6):
'''
构造一个ICMP echo 数据包
'''

if ipv6: #构建数据包头,ipv6和ipv4对应不同头部
header = struct.pack('BbHHh' , ICMP_TYPE_IP6 , ICMP_CODE , ICMP_CHECKSUM,\
ICMP_ID , ICMP_SEQ_NR + id)
else: #ipv4头部
header = struct.pack('bbHHh' , ICMP_TYPE,ICMP_CODE,ICMP_CHECKSUM,\
ICMP_ID , ICMP_SEQ_NR + id)
load = "__ Are you here?__" #填充数据字段内容

#space for time 去掉时间字符串后的包的大小
size -= struct.calcsize("d")
rest = ""
if size > len(load):
rest = load
size -= len(load)
rest += size * "x" #将数据位剩余位填充x

data = struct.pack('d' , time.time()) + rest #将时间填充到数据位中
packet = header + data #构建数据包
checksum = _in_cksum(packet) #做校验和错误

#costruct header with correct checksum 加入校验位后重新打包
if ipv6:
header = struct.pack('BbHHh' , ICMP_TYPE_IP6 , ICMP_CODE , checksum,\
ICMP_ID , ICMP_SEQ_NR + id)
else:
header = struct.pack('bbHHh' , ICMP_TYPE , ICMP_CODE , checksum,\
ICMP_ID , ICMP_SEQ_NR + id)
packet = header + data #新的packet
return packet

def _in_cksum(packet):
"""
校验数据段算法函数,
"""

if len(packet) & 1:
packet = packet + '\0'
words = array.array('h' , packet)
sum = 0
for word in words:
sum += (word & 0xffff)
hi = sum >> 16
lo = sum & 0xffff
sum = hi + lo
sum = sum + (sum >> 16)
return (~sum) & 0xffff

def _tcpConnect(IP = None,PORT = None):
'''
tcpConnect 用于扫描开放端口,采用的方法是通过向目标IP和PORT发送TCP
CONNECT链接,链接成功则返回1,不成功则继续进行连接,不成功返回flag=0
'''
data = "Are you ok"
ADDR = (IP , PORT)
tcpCliSock = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
tcpCliSock.settimeout(1)
try:
#print "####IP:%s,PORT:%s will connect....." % (IP,PORT)
#print "################################"
tcpCliSock.connect(ADDR)
flag = 1
#break
except Exception:
#print "####IP:%s,PORT:%s conect falise.....will agin" % (IP,PORT)
#print "################################"
flag = 0
tcpCliSock.close()
return flag

def usage():
'''
打印帮助信息
'''
print '''
Hellp information:
-n: the number of IP
-h: show help information
-a: alive,add -a host discovery prcess
'''
class scanThread(threading.Thread):
'''
从Thread派生出一个子类,
'''
def __init__(self , queue , alive , sel_port,inii):
'''
初始化
'''
threading.Thread.__init__(self)
self.queue = queue
self.alive = alive
self.sel_port = sel_port
self.num = inii
def run(self):
size = 56
timeout = 2
id_num = 1
global mutex
while True:
#从队列取值
ip = self.queue.get()
if alive == 1:
ret = subprocess.call("ping -c 1 %s" % ip,\
shell = True,\
stdout = open('/dev/null','w'),\
stderr = subprocess.STDOUT)
if ret == 0:
print "####IP:%s is alive,begining to scan" % ip
if sel_port != 0:
flag = _tcpConnect(ip , self.sel_port)
if flag == 1:
#print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
print "####IP:%s Port:%3s is connect success" %\
(ip , self.sel_port)
else:
#print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
print "####IP:%s Port:%3s is connect false" %\
(ip , self.sel_port)
else:
for PORT in (22 , 80 , 443):
flag = _tcpConnect(ip , PORT)
#print flag
if flag == 1:
#print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
print "####IP:%s Port:%3s is connect success" % (ip , PORT)
else:
#print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
print "####IP:%s Port:%3s is connect false" % (ip , PORT)
else:
print "####IP:%s is not alive##################" % ip
self.queue.task_done()
continue
else:
if sel_port != 0:
flag = _tcpConnect(ip , sel.sel_port)
if flag == 1:
#print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
print "####IP:%s Port:%3s is connect success" % (ip , sel.sel_port)
else:
#print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
print "####IP:%s Port:%3s is connect false" % (ip , sel.sel_port)
else:
for PORT in (22 , 80 , 443):
flag = _tcpConnect(ip , PORT)
#print flag
if flag == 1:
#print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
print "####IP:%s Port:%3s is connect success" % (ip , PORT)
else:
#print "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
print "####IP:%s Port:%3s is connect false" % (ip , PORT)
self.queue.task_done()

if __name__ == '__main__':
N = 1 #扫描IP数量,没有指定参数则只扫描本IP
alive = 0 #默认扫描不检测主机存活性
sel_port = 0 #默认端口号,没有制定端口好的情况下,扫描21 22 80 443 端口
try: #获取参数
#print sys.argv[1:]
opts , args = getopt.getopt(sys.argv[1:] , 'an:p:h')#-n后跟扫描IP数量
except getopt.GetoptError:
usage()#打印帮助信息
sys.exit(2)
if len(sys.argv) >= 2:#判断输入参数的个数
node = sys.argv[-1:][0]
else:
_error("NO arguments given")

for o,a in opts:
#提取参数
if o == '-h' or o == '--help':#display help and exit
usage()
sys.exit(0)
if o == '-a':#判断主机存活
alive = 1
if o == '-n':
try:
N = int(a)
except ValueError:
print "输入参数不合法 "
if o == '-p':#输入自定义扫描端口号
try:
sel_port =  int (a)
except ValueError:
print "输入端口参数不合法"

iplist = node.split(".")#将输入IP地址以点拆分
temp = iplist[-1]#提取IP地址最后一位
if temp == '*':
N = 254
temp = int(1)
else:
temp = int(temp)
b = []
#print iplist
for ip_list in range(N):
iplist[-1] = str(ip_list+temp)
IP = ''
IP = '.'.join(iplist)
b.append(IP)

print b
num_threads = 10 #开启的线程数目
queue = Queue() #获得一个队列实例
global mutex
mutex = threading.Lock()
worker = []
for inii in range(num_threads):
#worker = threading.Thread(target=scanThread,args=(queue,alive))
t = scanThread(queue,alive,sel_port,inii)
worker.append(t)
worker[inii].setDaemon(True)#设定daemon属性,主线程退出,不用等待子线程
worker[inii].start()
for ip in b:
queue.put(ip)
queue.join()
print "Done"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息