Python中Scapy使用方法,模块中的常用函数,简单的端口扫描编写

目录

scapy是什么

scapy的使用

IP()

src()和dst()

Ether()

采用分层的方式来构造数据包

raw()和hexdump()

summary()和show()

如何在scapy中发送和接收数据包

send()和sendp()

sr()、sr1()和srp()

简单的端口扫描

sniff()

使用scapy编写简单的端口扫描


scapy是什么

scapy是一个可用作网络嗅探,独立运行的工具,它提供了一个和python相同的交互方式命令行环境,可以在kali内单独运行,该类库在网络安全领域有非常广泛用例,可用于漏洞利用开发、流量的分析捕获等等。我们使用这个库实现对网络数据包的发送、监听和解析,编写可以用进行网络探测扫描的脚本

scapy的使用

scapy库pycharm内的导入

file → settings → project:pythonproject → python interpreter

点击“+”,搜索scapy,install package

IP()

在scapy中,使用了”类+属性”的方法来构造数据包,每一个网络协议都是一个类,所以只需要实例化一下这个类,就可以创建一个该协议的数据包,假设我们构造一个IP数据包,如下:

IP() 

导入scapy库构造数据包

from scapy.layers.inet import IP

pkt = IP()
print(pkt)

执行结果如图下所示,以字节格式显示了IP数据包的结果,由于bytes保存的就是原始的字节数据,可以直接在网络上进行传输

src()和dst()

对于IP来说,最重要的就是源ip和目的ip,这两个属性分别以src类和dst类来实现

比如我们想构造一个发往“192.168.200.1”的数据包

from scapy.layers.inet import IP
from scapy.all import ls

pkt = IP(dst="192.168.200.1")
ls(pkt)

执行结果如下图,src为源ip,dst则是目标ip,ls()类用来实现查看一个数据包的详细信息

以上是构造了一个最简单的数据包,IP类的属性非常复杂,除了最重要的源地址和目的地址外,还有TTL值,版本,长度,协议类型,校验等等

在了解了src和dst后,我们可以构造一个TTL值为22,源地址为192.168.200.140且目的地址为192.168.200.1的数据包

from scapy.layers.inet import *
from scapy.all import ls

pkt = IP(src="192.168.200.140",dst="192.168.200.1",ttl=22)
ls(pkt)

Ether()

scapy采用分层的方式来构造数据包,以最简单的TCP/IP协议簇为例,自顶而下分别为

应用层↓

        传输层↓

                网络层↓

                        链路层

通常最底层的协议为ether协议,⽤于实现链路层的数据传输和地址封装,然后是IP,然后是TCP、UDP,再然后是DNS、DHCP等,例如我们使用Ether(),这个类可以设置发送方和接收方的MAC地址,假设我们产生一个广布数据包,如下:

from scapy.layers.inet import *
from scapy.all import ls

pkt = Ether(dst="ff:ff:ff:ff:ff:ff")
ls(pkt)

采用分层的方式来构造数据包

分层是通过符号"/"实现的,如果一个数据包由多层协议组成,那么这些协议就需要使用"/"分开,并按照协议由底而上的顺序从左往右排列

构造一个Ether()/IP()/TCP()/数据包

from scapy.layers.inet import *
from scapy.all import *

pkt1 = Ether()/IP()/TCP()
ls(pkt1)

构造一个HTTP数据包

from scapy.layers.inet import *
from scapy.all import *

pkt2 = IP()/TCP()/"GET HTTP/1.0\r\n\r\n"
ls(pkt2)

raw()和hexdump()

raw()以字节格式来显示数据包的内容

而hexdump()则以十六进制显示数据包的内容

summary()和show()

summary()以不超过一行的摘要来简单描述数据包,而show()与summary()则相反(显示数据包的详细信息)

from scapy.layers.inet import *
from scapy.all import *

pkt2 = IP()/TCP()/"GET HTTP/1.0\r\n\r\n"
print(pkt2.summary())
print('--------------------------')
print(pkt2.show())

如何在scapy中发送和接收数据包

send()和sendp()

刚才我们构造了一个IP数据包,不过并没有将其发送出去,scapy内提供了多个用来发送数据包的函数(如:send()和sendp()),而两者的区别在于前者是发送IP数据包的,而后者是发送Ether数据包。

我们在网络中经常会使用到ICMP协议,比如使用的用于检查网络通不通的 Ping命令,这个“Ping”的过程实际上就是ICMP协议工作的过程。那么我们构造一个目标地址为192.168.2.46的ICMP数据包,并且将其发送出去

from scapy.layers.inet import *
from scapy.all import *

pkt = IP(dst = "192.168.2.46")/ICMP()
send(pkt)

如下图所示,sent 1 packets为发送成功标记

如果需要将MAC地址作为目标时,则使用sendp()函数

from scapy.layers.inet import *
from scapy.all import *

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

以上两个函数的特点是只发不收,也就是说只会将数据包发送出去,但是不会管这个数据包是否会被目的地址接收,同样也不会处理该数据包的应答数据包,在实际应用中,我们不但要将制作好的数据包发送出去,同样需要接收响应数据包

sr()、sr1()和srp()

scary提供了三个用来发送和接收数据包的核心函数,sr()和sr1()主要用于IP地址,而srp()主要用于MAC地址

这里我们使用sr()函数,对“192.168.2.46”发送一个ICMP数据包,需要注意的是,这里的目的地址需要真实存活。首先当数据包产生后被发送出去,scapy会监听接收到的数据包,然后筛选出需要的。sr1()函数跟sr()函数作用基本一样,但是前者只返回一个应答的包,而后者的返回值是两个列表,第一个列表包含了收到的应答数据包,第二个列表包含未收到的数据包

from scapy.layers.inet import *
from scapy.all import *

pkt = IP(dst = "192.168.2.46")/ICMP()
ans,uans = sr(pkt)
ans.summary()
print("------------------------------------------")
ans = sr1(pkt)
ans.summary()

如下图,ans和uans分别保存sr()函数的返回值,使用summary()查看数据包内容,Reveived表示收到的数据包的个数,answers表示发送数据包的应答个数

简单的端口扫描

使用sr1()函数来测试目标的mysql数据库端口是否开放,采用SYN扫描方法

(注意:测试时仍需要3306端口开放)

from scapy.layers.inet import *
from scapy.all import *

pkt = IP(dst="192.168.2.46")/TCP(dport=3306,flags="S")
ans = sr1(pkt)
ans.summary()

sniff()

这个函数可以在自己的程序中捕获经过本机网卡的数据包

该函数的完整格式为:

suiff(filter="",iface="",count=""prn="")

第一个参数为filter,可以表示需要过滤或筛选的数据包;第二个参数为iface,表示指定使用的网卡;count表示用来指定监听到的数据包数量;prn表示对捕获的数据包进行处理

例如,我们捕获与192.168.2.46有关的数据包

from scapy.layers.inet import *
from scapy.all import *

pkt = sniff(filter="host 192.168.2.46")
pkt.summary()

正常情况下,是不会有去往或者来自192.168.2.46的数据包的,所以这时候可以打开一个新的终端,然后在里面执行命令“ping -c 3 192.168.202.10”

在执行完毕脚本后,按暂停键结束捕获,这时可以看到已经捕获到了三个分别来和往的数据包  

常见的filter实例

  • host 192.168.2.46【筛选源地址或目的地址为192.168.2.46的数据包】

  • dst host 192.168.2.46【筛选目的地址为192.168.2.46的数据包】

  • src host 192.168.2.46【筛选源地址为192.168.2.46的数据包】

  • ether host ff:ff:ff:ff:ff:ff【筛选以太网源地址或目的地址为192.168.2.46的数据包】

  • ether dst ff:ff:ff:ff:ff:ff【筛选以太网目的地址为192.168.2.46的数据包】

  • ether src ff:ff:ff:ff:ff:ff【筛选以太网源地址为192.168.2.46的数据包】

  • dst port 8080【筛选目的地址为8080端口的数据包】

  • src port 8080【筛选源地址为8080端口的数据包】

  • port 8080【筛选源地址和目的地址为8080的数据包,所有port前面都可以加上TCP和UDP】

  • 比如在网卡eth0上监听源地址或目的地址为192.168.2.46的ICMP数据包,当接收到10个及以上时停止监听

    使用scapy编写简单的端口扫描

    import time
    from scapy.layers.inet import IP, TCP
    from scapy.sendrecv import sr1
    
    def scan(ip):
        try:
            packet = IP(dst=ip)/TCP(flags="A", dport=3306)  # 构造标志为ACK的数据包,通过调用TCP将构造好的请求包发送到目的地址,并根据目的地址的响应数据包中的flags字段值判断主机是否存活,若flags字段为R,其整型数值为4时表示接收
            response = sr1(packet)
            if response:
                if int(response[TCP].flags) == 4:
                    time.sleep(0.1)
                    print(ip + ' ' + 'is up')
                else:
                    print(ip + ' ' + 'is down')
            else:
                print(ip + ' ' + 'is down')
        except:
            pass
            
    scan('192.168.2.46')
    物联沃分享整理
    物联沃-IOTWORD物联网 » Python中Scapy使用方法,模块中的常用函数,简单的端口扫描编写

    发表评论