前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python的无状态SYN快速扫描

Python的无状态SYN快速扫描

作者头像
FB客服
发布2018-02-09 16:48:07
2.5K0
发布2018-02-09 16:48:07
举报
文章被收录于专栏:FreeBuf

起因

freebuf中有一篇文章,讲述了基本的扫描原理并给出了简易的python代码,几种扫描方式中我发现SYN的扫描准确率高返回的信息明确,而且不会留下握手的痕迹,但是速度有些慢,因此我们可以使用无状态的扫描,提升扫描速度。

scapy

Scapy是一个python的库,是一个强大的操纵报文的交互程序。它可以伪造或者解析多种协议的报文,还具有发送、捕获、匹配请求和响应这些报文以及更多的功能。所以我们使用scapy编写扫描程序。

有状态的扫描

#! /usr/bin/python import logging logging.getLogger("scapy.runtime").setLevel(logging.ERROR) from scapy.all import * dst_ip = "10.0.0.1" src_port = RandShort() dst_port=80 stealth_scan_resp = sr1(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="S"),timeout=10) if(str(type(stealth_scan_resp))==""): print "Filtered" elif(stealth_scan_resp.haslayer(TCP)): if(stealth_scan_resp.getlayer(TCP).flags == 0x12): send_rst = sr(IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="R"),timeout=10) print "Open" elif (stealth_scan_resp.getlayer(TCP).flags == 0x14): print "Closed" elif(stealth_scan_resp.haslayer(ICMP)): if(int(stealth_scan_resp.getlayer(ICMP).type)==3 and int(stealth_scan_resp.getlayer(ICMP).code) in [1,2,3,9,10,13]): print "Filtered"

这是那篇文章中给出的syn扫描的代码,可以看到对dst_ip的dport端口发送了SYN,然后对返回的数据包进行了详细的处理。

代码中发送数据包的函数均为scapy包中的sr*发包函数,他们会等待服务器的回复,所以要设置timeout参数,当进行大量扫描时,这个等待的时间会成为提高扫描速度的瓶颈,不论timeout -1s还是减了几秒,还是使用多线程也还是很慢。因此考虑用异步的无状态的扫描提升速度。

无状态的扫描

前面我们知道了提升扫描速度的瓶颈在于发包后等待回复的时间,所以去掉这个等待时间我们就可以提升扫描速度,同时因为去掉了等待,我们需要另加一个收包的模块,用来收集扫描后返回的信息。

在无状态扫描中,收发是异步的,发包的模块不关心收包模块会不会收到回复、收包模块也不知道发包模块向谁发送了什么,也就是收发包模块间没有交互,发包的函数只负责发送,收包的模块接收特定tcp flags字段的数据包就好,这样就没有了等待回复的时间。

这也导致了:

1. 得到扫描结果的顺序和发包的顺序不一致,因为不同的目标可能有不同的响应时间。 2. 扫描的速度取决于带宽,我们可以一次发送大量的包出去,所以需要根据你的网络环境,选择合适的发包速度 (寝室的路由器就被搞崩过) 3. 使用扫描器时本机的网络环境需要很安静,因为收包的模块不知道这个数据包是被探测的服务器返回的,还是本机的程序进行的通信,比如mac会进行各种请求。。kali就是完全安静的。 4. 由于发包后不需要等待回复,所以可以用scapy包中的send函数,发包模块发包后拍拍屁股就可以走了。 5. 网络不好的时候,可能出现同一个目标的ip出现多次,所以必要时需要对结果进行去重,并且降低扫描速度。

python实现

发包部分

from scapy.all import * import netaddr ip = ['1.34.0.0/16', '1.33.0.0/16'] port = [80, 81, 82] ipArray = [] portArray = [] for i in ip: ipArray.extend([str(i) for i in netaddr.IPNetwork(i).subnet(24)]) portArray = [port[i:i+3] for i in range(0, len(port), 3)] for i in ipArray: for j in portArray: send(IP(dst=i)/TCP(dport=j, flags=2), verbose=False) print i, j

发包模块使用了scapy和netaddr包,ip 和port 两个列表定义了要被扫描的部分

netaddr包用于处理ip,由于scapy的send发包函数可以传入一个IP段为目的ip,而且实践证明这样比一个for循环一个一个发快的多的多,测试了几次之后发现一次探测一个c段比较好,能兼顾速度和准确率。所以将字符串的ip段"1.34.0.0/16"初始化一个IPNetwork类,并使用subnet函数分割为c段,返回一个列表,再将这些列表合并,就得到了由c段组成的所有需要扫描的ip地址。

同理端口一次只扫描三个,将端口分为三个一组,存进portArray中。

最后发包过程中,可以选择先遍历ip或先遍历端口,注意send函数verbose参数为False避免输出很多东西,构造的数据包TCP首部flags为2,也就是flags字段只有SYN标志。如下图

收包部分

from scapy.all import * iface = 'eth0' userIP = '192.168.205.160' def prn(pkt): print pkt.sprintf("%IP.src%:%IP.sport% %TCP.flags%") sniff(iface=iface, filter='tcp and dst %s and tcp[13:1] & 18==18'%userIP, prn=prn)

收包模块部分也需要导入scapy包,定义了用户的网卡名iface和本机ip userIP,传入本机ip的目的是过滤到目标为本机的数据包,在虚拟机上使用时需要格外注意。

sniff函数为scapy包的嗅探函数,用途为将iface网卡上的、符合filter的数据包传给prn回调函数进行处理,首先注意嗅探需要root权限,然后是filter函数,他也可以写成这样

sniff(iface=iface, lfilter=lambda x:x.haslayer(TCP) and x[IP].dst==userIP and x.flags==18, prn=prn)

lfilter参数传入一个函数,返回True则留下这个数据包,反之False则丢弃它, filter 传入的是tcpdump的过滤语法,有更高的效率,所以推荐使用filter

至于tcp[13:1] & 18==18是怎么来的,因为在syn扫描中,我们向目标端口发送SYN,如果它开放的话会回复SYN+ACK,也就是SYN ACK位均为1,在上面tcp首部的图中,ACK为高位,SYN为低位,2(SYN) + 16(ACK) = 18。

此外tcp[13:1]是tcpdump里的一个高级语法,意为取tcp数据包的下标为13的字节(也就是第14个字节)开始的1个字节,也就是上面图中flags所在的字节,这样用其值与18与一下,就过滤掉了别的包。

在回调函数prn中,可以对扫描结果进行处理,可以打印出来,也可以存入文件中。(sprintf是scapy包中的格式化输出函数)

组合起来

上面实际是两个文件,可以用多线程,主线程发包,另开一个线程sniff嗅探达到整合的目的。

当然也可以粗暴的开两个命令行,分别执行两个文件,在收包那里,就可以看到扫描结果很快的出来啦。

*本文原创作者:addadd,本文属FreeBuf原创奖励计划,未经许可禁止转载

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-01-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 起因
  • freebuf中有一篇文章,讲述了基本的扫描原理并给出了简易的python代码,几种扫描方式中我发现SYN的扫描准确率高返回的信息明确,而且不会留下握手的痕迹,但是速度有些慢,因此我们可以使用无状态的扫描,提升扫描速度。
  • scapy
  • 有状态的扫描
  • 无状态的扫描
  • python实现
    • 发包部分
      • 收包部分
        • 组合起来
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档