主机IP地址探测-ICMP_Scapy

通过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))

你可能感兴趣的:(主机IP地址探测-ICMP_Scapy)