本文主要是利用scapy包编写了一个简易扫描工具,支持ARP、ICMP、TCP、UDP发现扫描,支持TCP SYN、UDP端口扫描,如下:
usage: python scan.py <-p ping扫描类型> <-s 端口发现类型> [-t target] [--port ports] 简单扫描工具,可以进行存活扫描及端口扫描. 存活扫描包括:ARP扫描、ICMP扫描、TCP扫描、UDP扫描. 端口扫描包括:TCP SYN扫描、TCP ACK扫描、TCP FIN扫描. optional arguments: -h, --help show this help message and exit -v, --version show program's version number and exit target group: 用于设置IP、PORT参数 --target TARGET target为IP或IP段,如192.168.1.1,192.168.1.x,或1 92.168.1.1-254 --port PORT port为待扫描的端口,如21,80,...或21-80 ping group: 用于开启存活扫描相关选项 -p 开启存活扫描 --ARP 启动ARP扫描 --ICMP 启动ICMP扫描 --TCP 启动TCP扫描 --UDP 启动UDP扫描 port scan group: 用于开启端口扫描相关选项 -s 开启端口扫描 --SYN 开启SYN扫描 --ACK 开启ACK扫描 --FIN 开启FIN扫描 --UPORT 开启UDP端口扫描 utils group: 用于开启扫描过程中的一些实用选项 --timeout TIMEOUT 设置发包超时时间,默认0.5秒 --retry RETRY 设置发包重试次数,默认不重试 以上做为说明,祝好运!
一、发现扫描
1.首先进行ARP扫描
python scan.py -p --target 192.168.1.1-254 --ARP [+]IP: 192.168.1.1 => MAC: 14:75:90:xx:xx:xx [+]IP: 192.168.1.111 => MAC: c6:36:55:xx:xx:xx [+]总共耗时9.84091806412秒.
通过retry参数增加发包尝试次数,如下:
python scan.py -p --target 192.168.1.1-254 --ARP --retry 2
[+]IP: 192.168.1.1 => MAC: 14:75:90:xx:xx:xx
[+]IP: 192.168.1.111 => MAC: c6:36:55:xx:xx:xx
[+]IP: 192.168.1.102 => MAC: 58:1f:28:xx:xx:xx
[+]IP: 192.168.1.114 => MAC: 6c:8d:c1:xx:xx:xx
[+]IP: 192.168.1.103 => MAC: 84:38:38:xx:xx:xx
[+]总共耗时20.429942131秒.
2.使用ICMP扫描,若没有指定任何扫描类型参数,默认会启用ICMP扫描,如下:
python scan.py -p --target 192.168.1.1-254 [+]没有指定任何ping扫描方式,默认选择ICMP扫描 [+]IP:主机192.168.1.1 echo-reply. [+]IP:主机192.168.1.111 echo-reply. [+]总共耗时10.7177450657秒.
通过timeout参数,设置较长的超时,可以防止网络状况不好造成的丢包,如下:
python scan.py -p --target 192.168.1.1-254 --timeout 2 [+]没有指定任何ping扫描方式,默认选择ICMP扫描 [+]IP:主机192.168.1.1 echo-reply. [+]IP:主机192.168.1.111 echo-reply. [+]IP:主机192.168.1.114 echo-reply. [+]总共耗时10.7566649914秒.
3.使用TCP扫描
python scan.py -p --target 192.168.1.100-120 --TCP --timeout 1 [+]请稍等,时间较长! [!]扫描... 192.168.1.100 [!]扫描... 192.168.1.101 [!]扫描... 192.168.1.102 [!]扫描... 192.168.1.103 [!]扫描... 192.168.1.104 [!]扫描... 192.168.1.105 [!]扫描... 192.168.1.106 [!]扫描... 192.168.1.107 [!]扫描... 192.168.1.108 [!]扫描... 192.168.1.109 [!]扫描... 192.168.1.110 [!]扫描... 192.168.1.111 [!]扫描... 192.168.1.112 [!]扫描... 192.168.1.113 [!]扫描... 192.168.1.114 [!]扫描... 192.168.1.115 [!]扫描... 192.168.1.116 [!]扫描... 192.168.1.117 [!]扫描... 192.168.1.118 [!]扫描... 192.168.1.119 [!]扫描... 192.168.1.120 [+]正在处理扫描信息. ==================== [+]主机 192.168.1.102 在线. [+]主机 192.168.1.103 在线. [+]主机 192.168.1.111 在线. [+]主机 192.168.1.114 在线. [+]总共耗时16.4359779358秒.
4.使用UDP扫描
python scan.py -p --target 192.168.1.100-120 --UDP --retry 3 [+]请稍等,时间较长! [!]扫描... 192.168.1.100 [!]扫描... 192.168.1.101 [!]扫描... 192.168.1.102 [!]扫描... 192.168.1.103 [!]扫描... 192.168.1.104 [!]扫描... 192.168.1.105 [!]扫描... 192.168.1.106 [!]扫描... 192.168.1.107 [!]扫描... 192.168.1.108 [!]扫描... 192.168.1.109 [!]扫描... 192.168.1.110 [!]扫描... 192.168.1.111 [!]扫描... 192.168.1.112 [!]扫描... 192.168.1.113 [!]扫描... 192.168.1.114 [!]扫描... 192.168.1.115 [!]扫描... 192.168.1.116 [!]扫描... 192.168.1.117 [!]扫描... 192.168.1.118 [!]扫描... 192.168.1.119 [!]扫描... 192.168.1.120 [+]正在处理扫描信息. ==================== [+]主机 192.168.1.102 在线. [+]主机 192.168.1.103 在线. [+]主机 192.168.1.111 在线. [+]主机 192.168.1.114 在线. [+]总共耗时33.5198891163秒.
二、端口扫描
1、TCP SYN端口扫描,不设置端口参数,则默认扫描1-1024端口
python scan.py --target 192.168.1.110-115 -s --SYN [+]没有指定任何扫描端口,默认扫描1-1024 [!]扫描... 192.168.1.110 [!]扫描... 192.168.1.111 [!]扫描... 192.168.1.112 [!]扫描... 192.168.1.113 [!]扫描... 192.168.1.114 [!]扫描... 192.168.1.115 [+]正在处理扫描信息. ==================== [+]主机 192.168.1.111 开放的TCP端口有:[80] [+]总共耗时165.125555992秒.
扫描指定端口:
python scan.py --target 192.168.1.1-254 -s --SYN --port 80 --timeout 1 [!]扫描... 192.168.1.1 [!]扫描... 192.168.1.2 [!]扫描... 192.168.1.3 [!]扫描... 192.168.1.4 ... [!]扫描... 192.168.1.253 [!]扫描... 192.168.1.254 [+]正在处理扫描信息. ==================== [+]主机 192.168.1.111 开放的TCP端口有:[80] [+]主机 192.168.1.1 开放的TCP端口有:[80] [+]总共耗时9.72222185135秒.
2、扫描UDP端口
python scan.py --target 192.168.1.1 -s --UPORT --timeout 1 [+]没有指定任何扫描端口,默认扫描1-1024 [!]扫描... 192.168.1.1 [+]正在处理扫描信息. ==================== [+]主机 192.168.1.1 开放的UDP端口有:[520] [+]总共耗时27.4742250443秒.
也可同时进行发现扫描与端口扫描,如下:
python scan.py --target 192.168.1.1-254 -p --ARP -s --SYN --port 80 --timeout 1 --retry 2 [+]IP: 192.168.1.1 => MAC: 14:75:90:xx:xx:xx [+]IP: 192.168.1.102 => MAC: 58:1f:28:xx:xx:xx [+]IP: 192.168.1.114 => MAC: 6c:8d:c1:xx:xx:xx [+]IP: 192.168.1.103 => MAC: 84:38:38:xx:xx:xx [+]IP: 192.168.1.101 => MAC: 5c:f7:e6:xx:xx:xx [!]扫描... 192.168.1.1 [!]扫描... 192.168.1.2 ... [!]扫描... 192.168.1.253 [!]扫描... 192.168.1.254 [+]正在处理扫描信息. ==================== [+]主机 192.168.1.1 开放的TCP端口有:[80] [+]主机 192.168.1.111 开放的TCP端口有:[80] [+]总共耗时45.2775988579秒.
OK,最后附上源码:
import argparse import re import time import threading from scapy.all import * import logging logging.getLogger('scapy.runtime').setLevel(logging.ERROR) class Discovery_Scan(object): ''' 说明:用于发现扫描 ''' def __init__(self,args,timeout=0.5,retry=0): self.targets = parse_target(args) self.timeout = timeout self.retry = retry def arp_scan(self,pdst): #ARP发现扫描 ans = sr1(ARP(pdst=pdst),timeout=self.timeout,retry=self.retry,verbose=False) if ans: if ans[ARP].op == 2: #操作码为2是is-at,是ARP响应 print '[+]IP: %s => MAC: %s' % (pdst,ans[ARP].hwsrc) def icmp_scan(self,dst): #ICMP发现扫描 ans = sr1(IP(dst=dst)/ICMP(),timeout=self.timeout,retry=self.retry,verbose=False) if ans: if ans[ICMP].type == 0: #ICMP type为0表示是ICMP echo-reply print '[+]IP:主机%s echo-reply.' % dst tcp_info = {} def tcp_scan(self,dst,port): #TCP SYN,发送TCP SYN包,有响应表示端口开放 ans,unans = sr(IP(dst=dst)/TCP(sport=RandShort(),dport=port,flags='S'), timeout=self.timeout,retry=self.retry,verbose=False) if ans.res: if ans.res[0][0][IP].dst not in Discovery_Scan.tcp_info: Discovery_Scan.tcp_info[ans.res[0][0][IP].dst] = True udp_info = {} def udp_scan(self,dst,port): #UDP,发送UDP包,有响应表示端口开放 ans,uans = sr(IP(dst=dst)/UDP(sport=RandShort(),dport=port), timeout=self.timeout,retry=self.retry,verbose=False) if ans.res: if ans.res[0][0][IP].dst not in Discovery_Scan.udp_info: Discovery_Scan.udp_info[ans.res[0][0][IP].dst] = True class Port_Scan(object): ''' 说明:用于进行端口扫描,判断端口是否开放 ''' def __init__(self,args,timeout=0.5,retry=0): self.targets = parse_target(args) self.timeout = timeout self.retry = retry syn_port_dict = {} def syn_port_scan(self,dst,port): #TCP SYN端口扫描,若SYN包返回携带SYN、ACK(即TCP.flags=18)标志的包,则表明此端口打开。 ans,uans = sr(IP(dst=dst)/TCP(sport=RandShort(),dport=port,flags='S'), timeout=self.timeout,retry=self.retry,verbose=False) if ans: first_respons_pkt = ans.res[0][1] if first_respons_pkt[TCP] and first_respons_pkt[TCP].flags == 18: if first_respons_pkt[IP].src not in Port_Scan.syn_port_dict: Port_Scan.syn_port_dict[first_respons_pkt[IP].src] = [first_respons_pkt[TCP].sport] else: Port_Scan.syn_port_dict[first_respons_pkt[IP].src].append(first_respons_pkt[TCP].sport) udp_port_dict = {} def udp_port_scan(self,dst,port): #UDP端口扫描,若UDP端口返回ICMP port-unreachable,则表示端口打开。(排除某些主机对任何UDP端口的探测都响应为ICMP port-unrechable) ans,uans = sr(IP(dst=dst)/UDP(sport=RandShort(),dport=port), timeout=self.timeout, retry=self.retry, verbose=False) if ans.res and ans.res[0][1].haslayer(UDPerror): first_respons_pkt = ans.res[0][1] if first_respons_pkt[IP].src not in Port_Scan.udp_port_dict: Port_Scan.udp_port_dict[first_respons_pkt[IP].src] = [first_respons_pkt[UDPerror].dport] else: Port_Scan.udp_port_dict[first_respons_pkt[IP].src].append(first_respons_pkt[UDPerror].dport) def parse_opt(): ''' @说明:通过argparse模块解析程序传入的参数 @return:args ''' usage = 'python %(prog)s <-p ping扫描类型> <-s 端口发现类型> [-t target] [--port ports]' description = '简单扫描工具,可以进行存活扫描及端口扫描.\n' '存活扫描包括:ARP扫描、ICMP扫描、TCP扫描、UDP扫描.\n' '端口扫描包括:TCP SYN扫描、TCP ACK扫描、TCP FIN扫描.' epilog = '以上做为说明,祝好运!' parser = argparse.ArgumentParser(usage=usage,description=description,epilog=epilog,version='v1.0') target_group = parser.add_argument_group('target group',description='用于设置IP、PORT参数') target_group.add_argument('--target',dest='target',action='store', help='target为IP或IP段,如192.168.1.1,192.168.1.x,或192.168.1.1-254') target_group.add_argument('--port',dest='port',action='store', help='port为待扫描的端口,如21,80,...或21-80') ping_group = parser.add_argument_group('ping group',description='用于开启存活扫描相关选项') ping_group.add_argument('-p',dest='ping',action='store_true',help='开启存活扫描') ping_group.add_argument('--ARP',dest='ARP',action='store_true',help='启动ARP扫描') ping_group.add_argument('--ICMP',dest='ICMP',action='store_true',help='启动ICMP扫描') ping_group.add_argument('--TCP',dest='TCP',action='store_true',help='启动TCP扫描') ping_group.add_argument('--UDP',dest='UDP',action='store_true',help='启动UDP扫描') port_scan_group = parser.add_argument_group('port scan group',description='用于开启端口扫描相关选项') port_scan_group.add_argument('-s',dest='scan',action='store_true',help='开启端口扫描') port_scan_group.add_argument('--SYN',dest='SYN',action='store_true',help='开启SYN扫描') port_scan_group.add_argument('--ACK',dest='ACK',action='store_true',help='开启ACK扫描') port_scan_group.add_argument('--FIN',dest='FIN',action='store_true',help='开启FIN扫描') port_scan_group.add_argument('--UPORT', dest='UPORT', action='store_true', help='开启UDP端口扫描') utils_group = parser.add_argument_group('utils group',description='用于开启扫描过程中的一些实用选项') utils_group.add_argument('--timeout',dest='timeout',action='store',type=float,help='设置发包超时时间,默认0.5秒') utils_group.add_argument('--retry',dest='retry',action='store',type=int,help='设置发包重试次数,默认不重试') args = parser.parse_args() if not args.ping and not args.scan: print '[-]必须通过-p/-s选项开启一种扫描' print '\n' parser.print_help() exit(1) elif not args.target: print '[-]必须通过--target选项指定扫描的对象' print '\n' parser.print_help() exit(1) if args.ping: if not args.ARP and not args.ICMP and not args.TCP and not args.UDP: args.ICMP = True #若没有指定任何ping扫描方式,则默认选择ICMP扫描 print '[+]没有指定任何ping扫描方式,默认选择ICMP扫描' if args.scan: if not args.SYN and not args.ACK and not args.FIN and not args.UPORT: args.SYN = True #若没有指定任何端口扫描方式,则默认选择SYN扫描 print '[+]没有指定任何端口扫描方式,默认选择SYN扫描' if not args.port: args.port = '1-1024' #若没有指定任何扫描端口,则默认扫描1-1024 print '[+]没有指定任何扫描端口,默认扫描1-1024' return args def parse_target(args): ''' @说明:用于解析如'192.168.1.1,192.168.1.x,...或192.168.1.1-254'格式的IP为单独的IP,用于解析如'21,80,...或21-80'格式的端口为单独的端口 @param: args,一个namespace对象 @return: (ip_list,port_list) ''' pattern1 = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$' pattern2 = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}$' pattern3 = r'\d{1,5}$' pattern4 = r'\d{1,5}-\d{1,5}$' ip_list,port_list = None,None if args.target: if re.search(pattern1,args.target): ip_list = args.target.split(',') elif re.match(pattern2,args.target): _split = args.target.split('-') first_ip = _split[0] ip_split = first_ip.split('.') ipdot4 = range(int(ip_split[3]), int(_split[1]) + 1) ip_list = [ip_split[0] + '.' + ip_split[1] + '.' + ip_split[2] + '.' + str(p) for p in ipdot4] else: print '[-]target格式输入有误,请查看帮助!' exit(1) if args.port: if re.match(pattern4,args.port): _split = args.port.split('-') port_list = range(int(_split[0]),int(_split[1])+1) elif re.search(pattern3,args.port): port_list = args.port.split(',') else: print '[-]port格式输入有误,请查看帮助!' exit(1) return ip_list,port_list def main(): ''' @说明:扫描的主程序,首先根据条件创建Ping扫描或端口扫描对象,然后调用相关的扫描方法进行扫描。 ''' args = parse_opt() if args.ping: #是否启动Ping扫描 if not args.timeout and not args.retry: obj_ping = Discovery_Scan(args) elif args.timeout and not args.retry: obj_ping = Discovery_Scan(args,timeout=args.timeout) elif not args.timeout and args.retry: obj_ping = Discovery_Scan(args,retry=args.retry) else: obj_ping = Discovery_Scan(args,args.timeout,args.retry) ip_list = obj_ping.targets[0] if ip_list: #ARP扫描 if args.ARP: for pdst in ip_list: t = threading.Thread(target=obj_ping.arp_scan,args=(pdst,)) t.start() while threading.activeCount() != 1: #避免线程还没有运行完就提前输出不全的结果 time.sleep(1) #ICMP扫描 elif args.ICMP: for dst in ip_list: t = threading.Thread(target=obj_ping.icmp_scan,args=(dst,)) t.start() while threading.activeCount() != 1: #避免线程还没有运行完就提前输出不全的结果 time.sleep(1) #TCP扫描 elif args.TCP: port_list = [80,443,21,22,23,25,53,135,139,137,445,1158,1433,1521,3306,3389,7001,8000,8080,9090] print '[+]请稍等,时间较长!' for dst in ip_list: print '[!]扫描...',dst for port in port_list: t = threading.Thread(target=obj_ping.tcp_scan,args=(dst,port)) t.start() print '[+]正在处理扫描信息.' while threading.activeCount() != 1: #避免线程还没有运行完就提前输出不全的结果 time.sleep(1) if not obj_ping.tcp_info: print '\n' print '=' * 20 print '[+]未发现在线主机.' else: print '\n' print '=' * 20 for ip_a in sorted(obj_ping.tcp_info.keys()): print '[+]主机 %s 在线.' % ip_a #UDP扫描 elif args.UDP: port_list = [7,9.13,15,37,53,67,68,69,135,137,138,139,445,520] print '[+]请稍等,时间较长!' for dst in ip_list: print '[!]扫描...',dst for port in port_list: t = threading.Thread(target=obj_ping.udp_scan,args=(dst,port)) t.start() print '[+]正在处理扫描信息.' while threading.activeCount() != 1: #避免线程还没有运行完就提前输出不全的结果 time.sleep(1) if not obj_ping.udp_info: print '\n' print '=' * 20 print '[+]未发现在线主机.' else: print '\n' print '=' * 20 for ip_a in sorted(obj_ping.udp_info.keys()): print '[+]主机 %s 在线.' % ip_a if args.scan: #是否启动端口扫描 if not args.timeout and not args.retry: obj_port = Port_Scan(args) elif args.timeout and not args.retry: obj_port = Port_Scan(args,timeout=args.timeout) elif not args.timeout and args.retry: obj_port = Port_Scan(args,retry=args.retry) else: obj_port = Port_Scan(args,args.timeout,args.retry) ip_list,port_list = obj_port.targets if ip_list and port_list: if args.SYN: for dst in ip_list: print '[!]扫描...',dst for port in port_list: t = threading.Thread(target=obj_port.syn_port_scan,args=(dst,int(port))) t.start() print '[+]正在处理扫描信息.' while threading.activeCount() != 1: #避免线程还没有运行完就提前输出不全的结果 time.sleep(1) if not obj_port.syn_port_dict: print '\n' print '=' * 20 print '[+]未发现开放TCP端口.' else: print '\n' print '=' * 20 for k,v in obj_port.syn_port_dict.items(): print '[+]主机 %s 开放的TCP端口有:%s' % (k,str(v)) elif args.ACK: pass #基本不能使用 elif args.FIN: pass #基本不能使用 elif args.UPORT: for dst in ip_list: print '[!]扫描...',dst for port in port_list: t = threading.Thread(target=obj_port.udp_port_scan,args=(dst,int(port))) t.start() print '[+]正在处理扫描信息.' while threading.activeCount() != 1: #避免线程还没有运行完就提前输出不全的结果 time.sleep(1) if not obj_port.udp_port_dict: print '\n' print '=' * 20 print '[+]未发现开放UDP端口.' else: print '\n' print '=' * 20 for k,v in obj_port.udp_port_dict.items(): print '[+]主机 %s 开放的UDP端口有:%s' % (k,str(v)) if __name__ == '__main__': try: start_time = time.time() main() stop_time = time.time() print '[+]总共耗时'+str(stop_time-start_time)+'秒.' except Exception,e: print '[-]执行出错,具体错误见下面信息.' print e
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件!
如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
白云城资源网 Copyright www.dyhadc.com
暂无“python如何编写类似nmap的扫描工具”评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
2024年12月24日
2024年12月24日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]