您当前的位置:首页 > 计算机 > 编程开发 > Python

Python-Scapy使用介绍

时间:03-30来源:作者:点击数:

介绍

Scapy可作为python模块运行,也可以单独运行,scapy在kali自带,可以直接输入scapy进入交互命令行。

Scapy可对网络数据包进行发送、监听、解析等操作,类似于python-nmap模块,只不过scapy更偏向于底层操作。

函数

下面简单了解下scapy的基本使用,这里以kali系统为例,输入scapy进入交互命令行,如下图:

以上是一个小例子,我们简单了解下,首先scapy构造数据包时使用到的底层协议,创建时函数名称和协议名一样,只不过函数名要大写,创建后可以赋值给一个变量,例如上面的ip = IP()就创建了一个ip数据包。类似的还有TCP(),UDP()等。

随后函数中可传入相关参数,键值对形式,例如源地址设置使用src,目标地址使用dst。

很多时候一个数据包是由多个协议组成的,组成形式使用/分割,协议顺序由底层逐渐向上,例如构造一个tcp数据包:tcp = Ether()/IP()/TCP(),这样。

而协议函数中需要传入的属性,例如ip,包含了源地址、目标地址、版本、长度、协议类型、校验和等等,我们可以使用ls来查看,如下图。

下面再看下scapy的一些函数,当构造好数据包后我们要进行发送,发送函数有send和sendp,send工作在第三层,用来发送ip数据包,sendp工作在第二层,用来发送ether数据包。例如构造一个目标地址为192.168.150.135的icmp数据包,如下图。

上面的send和sendp发送数据包但不会接收返回的内容,scapy提供了接收内容的函数,分别是sr、sr1、srp,其中sr、sr1主要用于第三层,srp用于第二层,例如以下示例我们使用sr还向192.168.150.135发送一个icmp包,看下与send的区别,如下图。

可以看到接收到了返回结果,received收到两个包,got获取一个包,remaining剩0个包,结果是两个列表,results是应答包,unanswered是未收到的应答包。所以我们可以把结果存到变量中,然后使用summary函数查看详细内容,如下图。

而sr1和sr的区别在于sr1返回的只有应答包,没有未应答包。

三次握手

做一些示例前,需要对数据包的请求三次握手有一个简单的了解,否则我们无法构造数据包以及判断响应结果。

首先,需要了解下数据包中的flag标志代表的意义,如下表。

缩写 全写 意义
F FIN 结束会话
S SYN 开始会话
R RST 复位,中断连接
P PUSH 推送,立即发送数据包
A ACK 应答
U URG 紧急
E ECE 显示拥塞提醒回应
W CWR 拥塞窗口减少

三次握手:例如A和B通信,A首先发送数据包,其中flag字段值为SYN,即开始会话,(第一次)。B收到后会响应A一个包,其中flag为SYN/ACK,即应答会话,(第二次)。A接收到响应包后返回一个ACK,即应答,(第三次)。

全开扫描:即完成整个三次握手的扫描请求,以此判断目标机的情况。

半开扫描:即没有完成三次握手,自己只向目标机发一个syn,目标机返回syn/ack后,自己不发送ack响应,即为半开。

示例

示例1:一个简单的利用半开来判断目标某个端口情况,示例如下:

我们通过ip和tcp组合发送了一个数据包请求,端口为22,flags为S,即SYN开始会话,返回的数据包中可以看到flags的值为SA,即SYN/ACK响应包,此为正常返回,证明目标机22端口开放,此时知道目标机情况后我们没有发送后续也就是第三次握手的ack响应包,所以为半开扫描。

我们这时换一个端口,例如1234,响应如下。

可以发现返回的flags为RA,即RST/ACK,代表中断响应,可以判定目标1234端口为关闭状态。

示例2:

示例2我们简单看下sniff函数的应用,此函数功能可以捕获经过本机网卡的数据包,此函数有filter参数可以对数据包进行过滤,例如filter host过滤指定ip数据包,filter icmp过滤指定协议,其中需要过滤多个条件时也可以使用and、or运算符。

还有一个iface参数,可以指定要监听的网卡,count参数用来指定监听多少个数据包,监听够就停止。

例如这里我们需要一个监听器,监听有关192.168.150.136的icmp数据包,监听够三个就停止,如下。

Ping命令走的icmp协议,我们通过ping去触发了icmp的发送,可以看到sniff捕获到了,随后使用_符号来获取上一条命令的执行结果,然后通过nsummary来查看,这里nsummary和summary的区别在于:nsummary可以获取多个数据包,而summary只能获取单个。

示例3

这里依然来判断一个端口的情况,我们使用sr函数,sr会返回两个列表,一个是应答包一个是未应答包,我们可以通过结果来判断端口是开放、关闭、屏蔽等情况。发送一个syn后,如果返回syn/ack就是开放,rst/ack则关闭,如果是屏蔽状态则不会返回任何响应,屏蔽我们可以直接看未应答包的内容。

这里我们创建一个python脚本,代码如下。

from scapy.all import fuzz,TCP,IP,sr

ans, unans = sr(IP(dst="192.168.150.135")/fuzz(TCP(dport=80,flags="S")))

for s,r in ans:
    if r[TCP].flags == 18:
        print "This port is open"
    if r[TCP].flags == 20:
        print "This port is closed"

先来看下运行效果:

代码解析:

首先我们导入了scapy模块,因为scapy模块中有一个all文件,里面导入了所有的子模块,所以我们导入时需要写成scapy.all,随后sr发送构造的数据包,这里用到了一个新函数是fuzz,fuzz会随机填充内容然后发送,因为有些服务器碰到空数据包可能会不响应,fuzz填充来保证正确率。

然后我们使用了for遍历了ans变量,此变量存的是应答包,遍历后赋值给了s和r,这里之所以要赋值给两个变量的原因:我们在命令行看下运行结果:

ans返回的包的整体数量,并没有包详细信息,我们需要用res来查看包具体内容,例如TCP包:

可以发现有两个包,一个是我们发送的syn,一个是应答的syn/ack,而我们for遍历时,s存的就是send发送出去的包,r存的就是reply应答的包。

最后我们通过判断应答包flags的值来确定端口状态,这里注意的是不能通过S、SA去判断,而要通过他们的数值,具体为什么18就是open,20就是close,我们可以通过wireshark抓一个包来辅助理解,一个包的flags结构如下,其中数值从下往上依次是1,2,4,8,16,32,64,128,以此类推,字段值为1说明有返回,例如下图。

上图中syn为1有值,其数为2,ack有值数为16,16+2为18,所以18代表syn/ack,同理rst+ack等于4+16,所以20代表rst/ack,也就是重置关闭的意思。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门