Python程序设计-安全渗透测试模块-Scapy模块

简介

  • Scapy是一个由Python语言编写的强大工具,它是大量程序编写人员最喜爱的一个网络模块。目前很多优秀的网络扫描和攻击工具都使用了这个模块。
  • 也可以在自己的程序中使用这个模块来实现对网络数据包的发送、监听和解析。
  • 这个模块相比起Nmap来说,更为底层。可以更为直观地了解到网络中的各种扫描和攻击行为,例如,要检测某一个端口是否开放,只需提供给Nmap一个端口号,而Nmap就会给出一个开放或者关闭的结果,但是并不知道Nmap是怎么做的。
  • 如果想对网络中的各种问题进行深入研究,Scapy无疑是一个更好的选择,可以利用它来产生各种类型的数据包并发送出去,Scapy也只会把收到的数据包展示给你,而并不会告诉你这意味着什么,一切都将由你来判断。

基本用法

Scapy提供了和Python一样的交互式命令行。Scapy可以作为Python的一个模块存在,但是Scapy本身就是一个可以运行的工具,它自己具备一个独立的运行环境,因而可以不在Python环境下运行。
Python程序设计-安全渗透测试模块-Scapy模块_第1张图片

基本操作

  • 在Scapy中,每一个协议就是一个类。
  • 只需要实例化一个协议类,就可以创建一个该协议的数据包。例如,如果要创建一个IP类型的数据包,就可以使用如下命令。
ip = IP()

Python程序设计-安全渗透测试模块-Scapy模块_第2张图片

  • IP数据包最重要的属性就是源地址和目的地址,这两个属性可以使用src和dst来设置。
  • 例如,要构造一个发往“192.168.1.101”的IP数据包,可以使用如下语句。
ip = IP(dst="192.168.1.101")

Python程序设计-安全渗透测试模块-Scapy模块_第3张图片

  • 这个目标dst的值可以是一个IP地址,也可以是一个IP范围,
  • 例如192.168.1.0/24,这时产生的就不是1个数据包,而是256个数据包。
    Python程序设计-安全渗透测试模块-Scapy模块_第4张图片
  • 如果要查看其中每一个数据包,可以使用
p for p in ip

在这里插入图片描述

采用分层形式来构造数据包

  • 通常最下面的一个协议为Ether,然后是IP,再之后是TCP或者是UDP。
  • IP()函数无法用来构造ARP请求和应答数据包,可以使用Ether(),
  • 这个函数可以设置发送方和接收方的MAC地址。
  • 产生一个广播数据包,执行命令如下
Ether(dst="ff:ff:ff:ff:ff:ff")

在这里插入图片描述

  • Scapy中的分层通过符号“/”实现,一个数据包是由多层协议组合而成,这些协议之间就可以使用“/”分开,按照协议由底而上的顺序从左向右排列
  • 例如,可以使用以下命令来完成一个TCP数据包,
Ether()/IP()/TCP()	

在这里插入图片描述

  • 如果构造一个HTTP数据包,可以使用以下方式
IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"

在这里插入图片描述

ls()函数查看一个类所拥有的属性

  • 使用ls(Ether())来查看Ether类属性
    在这里插入图片描述
  • 使用ls(IP())来查看IP类的属性
    Python程序设计-安全渗透测试模块-Scapy模块_第5张图片
  • 可以对这里面的属性进行设置
  • 例如:将ttl的值设置为32,可以使用如下方式
IP(src="192.168.1.1", dst="192.168.1.101", ttl=32)

在这里插入图片描述

发送函数

send() 工作在第三层,发送IP数据包
sendp() 工作在第二层,发送Ether数据包

  • 例如,构造一个目的地址为"192.168.1.101"的ICMP数据包,并将其发送出去,可以使用一下语句
send(IP(dst="192.168.1.101")/ICMP())

在这里插入图片描述

sendp(Ether(dst="ff:ff:ff:ff:ff:ff"))

在这里插入图片描述

  • 注:这两个函数只发不收

fuzz()函数

  • 如果希望发送一个内容是随机填充的数据包,而且又要保证这个数据包的正确性,那么可以是fuzz()函数。
  • 例如,可以使用如下命令来创建一个发往192.168.1.101的TCP数据包。
IP(dst="192.168.1.101")/fuzz(TCP())

在这里插入图片描述

sr(),sr1()和srp()

  • 在网络的各种应用中,需要做的不仅是将创建好的数据包发送出去,也需要接收这些数据包的应答数据包,这一点在网络扫描中尤为重要。
  • 在Scapy中提供了三个用来 发送和接收数据包的函数,分别是sr()、sr1()和srp(),其中,sr()和sr1()主要用于第三层,例如IP和ARP等。而srp()用于第二层。
  • 仍然向192.168.1.101发送一个ICMP数据包来比较一下sr()和send()的区别。
sr(IP(dst="192.168.1.101")/ICMP())

Python程序设计-安全渗透测试模块-Scapy模块_第6张图片

  • 当产生的数据包发送出去之后,Scapy就会监听接收到的数据包,并将其中对应的应答数据包筛选出来,显示在下面。Reveived表示收到的数据包个数,answers表示对应的应答数据包。
  • sr()函数是Scapy的核心,它的返回值是两个列表,第一个列表是收到了应答的包和对应的应答,第二个列表是未收到应答的包。所以可以使用两个列表来保存sr()的返回值
  • sr()函数是Scapy的核心,它的返回值是两个列表
  • 第一个列表是收到了应答的包和对应的应答,
  • 第二个列表是未收到应答的包。所以可以使用两个列表来保存sr()的返回值
    在这里插入图片描述
  • 使用ans和unans来保存sr()的返回值,因为发出去的是一个ICMP的请求数据包,而且也收到了一个应答包,所以这个发送的数据包和收到的应答包都被保存到了ans列表中
  • 使用ans.summary()可以查看两个数据包的内容,而unans列表为空。
  • sr1()函数跟sr()函数作用基本一样,但是只返回一个应答的包。只需要使用一个列表就可以保存这个函数的返回值。
  • 例如,使用p来保存sr1(IP(dst=“192.168.26.6”)/ICMP())的返回值,如图所示。
    Python程序设计-安全渗透测试模块-Scapy模块_第7张图片
  • 可以利用sr1()函数来测试目标的某个端口是否开放,采用半开扫描(SYN)的办法。
sr1(IP(dst="192.168.26.101")/TCP(dport=80,flags="S"))

Python程序设计-安全渗透测试模块-Scapy模块_第8张图片
Python程序设计-安全渗透测试模块-Scapy模块_第9张图片

  • 192.168.26.101回应了发出的设置了SYN标志位的TCP数据包,这表明这台主机的80端口是开放的

sniff()

这个函数可以在自己的程序中捕获经过本机网卡的数据包
在这里插入图片描述

  • 比如先在终端开一个sniff() scapy 就处于一个捕获网卡数据包的状态

  • 如果有流量经过网卡(比如在另一个终端上 ping一下别的主机)

  • 在 ctrl+c的时候获取sniff()的结果

  • 这个函数最强大的地方在于可以使用参数filter对数据包进行过滤。

  • 例如,指定只捕获与192.168.1.102有关的数据包,可以使用“host 192.168.1.102”:

sniff(filter=" host 192.168.1.102")
  • 同样,也可以使用filter来过滤指定协议,例如,icmp类型的数据包:
sniff(filter="icmp")
  • 如果要同时满足多个条件可以使用“and”“or”等关系运算符来表达:
sniff(filter=" host 192.168.1.102 and icmp")
  • iface参数
    指定所要进行监听的网卡
    例如,指定eth1作为监听网卡sniff(iface="eth1")
  • count参数
    用来指定监听到的数据包的数量,达到指定数量就会监听停止
    例如,只希望监听到三个数据包就停止sniff(count=3)
  • 设计一个综合性的监听器,它会在网卡eth0上监听源地址或者目的地址为192.168.1.102的icmp数据包,当收到了三个这样的数据包之后,就会停止监听。
  • 首先在Scapy中创建如下监听器:
sniff(filter="icmp and host 192.168.26.100“,count=3,iface="eth0")
  • 正常情况下,是不会有去往或者来自192.168.1.102的icmp数据包的,所以这时候可以打开一个新的终端,然后在里面执行命令“ping 192.168.1.102”
  • 然后在Scapy中使用组合键Ctrl+C结束捕获,这时可以看到已经捕获到三个数据包
    在这里插入图片描述
  • 如果需要查看这三个数据包内容,可以使用“_”,在Scapy中这个符号表示是上一条语句执行的结果,
  • 例如刚刚使用sniff捕获到的数据包,就可以用“_”表示。
a =_
a.nsummary()

在这里插入图片描述

  • 刚刚使用过的函数pkt.summary()用来以摘要的形式显示pkt的内容,这个摘要的长度为一行
p = IP(dst="www.baidu.com")     
p.summary()     "192.168.169.130>Net('www.baidu.com') hopopt"

常用简单实例

  • 使用Scapy来实现一次ACK类型的端口扫描
  • ACK扫描:扫描主机向目标主机发送ACK数据包。根据返回的RST数据包- 有两种方法可以得到端口的信息。方法一是:
    若返回的RST数据包的TTL值小于或等于64,则端口开放,反之端口关闭
  • 例如,对192.168.1.102 的 21、23、135、443、445 这5个端口是否被屏蔽进行扫描,注意是屏蔽不是关闭,采用ACK扫描模式,可以构造如下的命令方式。
ans,unans = sr(IP(dst="192.168.1.102")/TCP(dport=[21,23,135,443,445],flags="A"))
  • 正常的时候,如果一个开放的端口会回应ack数据包,而关闭的端口会回应rst数据包。
  • 在网络中,一些网络安全设备会过滤掉一部分端口,这些端口不会响应来自外界的数据包,一切发往这些端口的数据包都如同石沉大海。注意这些端口的状态并非是开放或者关闭,而是被屏蔽。
    在这里插入图片描述
  • 向目标发送了5个标志位置为“A”的TCP数据包。按照TCP三次握手的规则,如果目标端口没有被过滤,发出的数据包就会得到回应,否则没有回应。另外,根据Scapy的设计,ans列表中的数据包就是得到了回应的数据包,而unans中的则是没有得到回应的数据包,只需要分两次来读取这两个列表就可以得到端口的过滤结果
    Python程序设计-安全渗透测试模块-Scapy模块_第10张图片
  • 也可以用类似的方法来查看被过滤的端口:
    在这里插入图片描述
  • 下面在Python中编写程序来实现一个查看端口是否被屏蔽的简单程序。首先导入需要使用的scapy模块中的函数:
from scapy.all import IP,TCP,sr
  • 这里需要IP()和TCP()来产生所需要的数据包,sr()函数来发送,然后发送构造好的数据包,在Python交互式命令行中执行这个程序的结果如图所示。
    Python程序设计-安全渗透测试模块-Scapy模块_第11张图片

  • 下面使用Scapy强大的包处理功能来设计一个端口是否开放的扫描器。

  • 如果一个端口处于屏蔽状态,那么它将不会产生任何响应报文。

  • 如果一个端口处于开放状态,那么它在收到syn数据包之后,就会回应一个ack数据包。

  • 反之,如果一个端口处于关闭状态,那么它在收到syn数据包之后,就会回应一个rst数据包。

  • 先导入需要使用的模块文件,这次需要使用IP()、TCP()来创建数据包,使用fuzz()来填充数据包,使用sr()来发送数据包。

from scapy.all import fuzz,TCP,IP,sr
  • 接下来产生一个目标为“192.168.26.100”的80端口的syn数据包,将标志位设置为“S”:
ans,unans = sr(IP(dst="192.168.26.100")/fuzz(TCP(dport=80,flags="S")))
  • 接下来使用循环来查看,
  • 如果r[TCP].flags==18,则表示返回数据包flags的值为0x012 (SYN,ACK)目标端口为开放状态。
  • 如果r[TCP].flags==20,则表示返回数据包flags的值为0x014 (RST, ACK) 目标端口为关闭状态。
    Python程序设计-安全渗透测试模块-Scapy模块_第12张图片
    Python程序设计-安全渗透测试模块-Scapy模块_第13张图片

你可能感兴趣的:(Python程序设计-安全渗透测试模块-Scapy模块)