UDP 端口扫描
UDP扫描发送空的(没有数据)UDP报头到每个目标端口。 如果返回ICMP端口不可到达错误(类型3,代码3), 该端口是closed(关闭的)。 其它ICMP不可到达错误(类型3, 代码1,2,9,10,或者13)表明该端口是filtered(被过滤的)。 偶尔地,某服务会响应一个UDP报文,证明该端口是open(开放的)。
import queue
import optparse
from random import randint
from scapy.all import *
from scapy.layers.inet import IP, UDP
def title():
print("""
# #
# # ###### # # #### # # ###### ###### # # ##### ## # # ####
# # # # # # # # # # # # # # # # # # # #
# ##### # # # # # # ##### ##### # # # # # # # ####
# # # # # # # ## # # # # ## # # # ###### # #
# # # # # # ## ## # # ## ## # # # # # # #
# ###### ###### ###### #### # # # ###### # # ##### # # # ####
Author: 黄少天
""")
#创建端口扫描类
class PortScaner(threading.Thread):
def __init__(self,portqueue,ip,timeout=5):
threading.Thread.__init__(self)
self._portqueue = portqueue
self._timeout = timeout
self._ip = ip
def run(self):
while True:
# 判断端口列表是否为空
if self._portqueue.empty():
break
# 取出端口,超时时间为0.5秒
port = self._portqueue.get(timeout=0.5)
try:
packet = IP(dst=self._ip)/UDP(dport=port,sport=randint(1,65535)) # 随机src端口,让扫面不易被察觉
result = sr1(packet,timeout=5,verbose=0) # timeout=5 为数据包提供五秒等待时间,如果没有回复就放弃,verbose=0,不显示输
if result is None:
sys.stdout.write("[%d]open \n" % port)
except:
print("send error")
def get_information():
#创建命令解析模块 创造了一个对象OptionParser
parser = optparse.OptionParser()
# parser.add_option(...)待定义命令行参数
# ip 参数 -i
parser.add_option('-i', '--ip', dest='targetip', default='127.0.0.1', type='string', help='target IP')
# 端口参数 -p
parser.add_option('-p', '--port', dest='port', default='500', type='string', help='scan_port')
# 线程参数 -t
parser.add_option('-t', '--thread', dest='threadNum', default='100', type='int', help='thread number')
# options 是一个字典,其key字典中的关键字可能会是是我们所有的add_option()函数中的dest参数值,其对应的value值,是命令行输入的对应的add_option()函数的参数值。
# args,它是一个由 positional arguments 组成的列表。
# parser.parse_args()解析命令
(options, args) = parser.parse_args()
StartScan(options.targetip, options.port, options.threadNum)
#定义扫描函数
def StartScan(targetip,port,threadNum):
#端口列表
portList = []
# portNumb = port
#判断单端口还是范围端口
'''
eg:192.168.1.1-100
用split函数通过"-"将ip段划分为192.168.1.1和100,再将192.168.1.1进行分割,取出最后一位数字与100组成int型数字范围
for循环遍历
'''
if '-' in port:
for i in range(int(port.split('-')[0]),int(port.split('-')[1])+1):
portList.append(i)
else:
portList.append(int(port))
#目标ip地址
ip = targetip
#线程列表
threads = []
#线程数量
threadNumber = threadNum
#端口队列
portQueue = queue.Queue()
#生成端口,加入端口队列
for port in portList:
portQueue.put(port)
for t in range(threadNumber):
threads.append(PortScaner(portQueue,ip,timeout =5))
#启动线程
for thread in threads:
thread.start()
# 等待,直到线程终结。这会阻塞调用这个方法的线程,直到被调用 join() 的线程终结
for thread in threads:
thread.join()
# 启动和堵塞一起实现并发
#主函数
if __name__ =='__main__':
title()
get_information()
使用方法