通过scapy构建ICMP echo request数据包实现对一个网段的主机段地址探测。
虽然大部分windows主机防火墙都已经关闭了ICMP的访问,但是对于非windos主机设备的扫描,ICMP还是可以使用的。
-h 显示帮助信息
运行示例
核心功能为通过Scapy构造ICMP数据包:
def icmp_scan_scapy(ip_add):
#创建随机的 ip_id icmp_id icmp_seq
ip_id = randint(1, 65535)
icmp_id = randint(1, 65535)
icmp_seq = randint(1, 65535)
#通过scapy创建数据包
icmp_packet=IP(dst=ip_add,ttl=64,id=ip_id)/ICMP(id=icmp_id,seq=icmp_seq)/B'abc_Daboluo'
#发送三层数据包并接收返回结果
result = sr1(icmp_packet, timeout=1, verbose=False)
#如果有返回说明主机up
if result:
for rcv in result:
scan_ip = rcv[IP].src
#格式化输出,显示的时候比较整齐
print('%15s---> Host is UP'%scan_ip)
# 如果没有返回说明主机down
else:
pass
print('%15s---> Host is Down'%ip_add)...
添加了CMD参数、多线程的源码如下,仅供参考:
import argparse
from scapy.all import *
from random import randint
from scapy.layers.inet import IP, ICMP
import IPy
import logging
import threading
#*******************************************
#******修改命令行参数信息
prog_name='ICMP_Scan'
prog_description='Scan a subnet by ICMP'
prog_epilog='If any question, please contact Boluo +86 1851861****'
#命令行参数 输入-h可以显示帮助信息
def args_aprse():
# 创建一个分析器
# prog 即program objects use sys.argv[0]
parser = argparse.ArgumentParser(prog=prog_name,
description=prog_description,
epilog=prog_epilog)
# 添加一个参数
parser.add_argument('-i', '--ip',
metavar='',
# metavar=None,
dest='dest_ip',
# nargs='*',
help='the IP address or subnet you want to test , like "192.168.1.1","192.168.1.0/24')
parser.add_argument('-V', '--version',
action='version',
version='%(prog)s 1.0',
help='check the verion of this software')
# 解析获取到的参数并传入变量args
args = parser.parse_args()
return args
#构建数据包进行ICMP扫描
def icmp_scan_scapy(ip_add):
#占用一个线程资源
thread_max_num.acquire()
#创建随机的 ip_id icmp_id icmp_seq
ip_id = randint(1, 65535)
icmp_id = randint(1, 65535)
icmp_seq = randint(1, 65535)
#通过scapy创建数据包
icmp_packet=IP(dst=ip_add,ttl=64,id=ip_id)/ICMP(id=icmp_id,seq=icmp_seq)/B'abc_Daboluo'
#发送三层数据包并接收返回结果
result = sr1(icmp_packet, timeout=1, verbose=False)
#如果有返回说明主机up
if result:
for rcv in result:
scan_ip = rcv[IP].src
if scan_ip==ip_add:
#格式化输出,显示的时候比较整齐
print('%15s---> Host is UP' %ip_add)
# 如果没有返回说明主机down
else:
print('%15s---> Host is Down'%ip_add)
#释放线程资源
thread_max_num.release()
#主程序开始
if __name__=='__main__':
#用于存放线程的数组
threads = []
#记录程序运行开始时间
t1=time.time()
#消除Scapy的Waring提示信息
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
#获取命令行输入的参数
args_input=args_aprse()
#判断输入是否为合法的IP地址段
try:
ip_subnet=IPy.IP(args_input.dest_ip, make_net=True)
except Exception as e:
print(e)
print('参数错误,请确认参数后重新扫描')
#参数错误的话退出程序
sys.exit()
#线程数量控制在200个
thread_max_num = threading.Semaphore(200)
# 循环命令行输入的地址段进行地址扫描
for ip_add in ip_subnet:
#将IP地址转换为字符串
args=str(ip_add)
#多线程执行
t=threading.Thread(target=icmp_scan_scapy,args=(args,))
t.start()
threads.append(t)
for i in range(0,len(threads)):
threads[i].join()
#程序结束时打印程序执行时间
print('程序执行时间:{}秒'.format(time.time()-t1))