赞
踩
目录
scapy是一个可用作网络嗅探,独立运行的工具,它提供了一个和python相同的交互方式命令行环境,可以在kali内单独运行,该类库在网络安全领域有非常广泛用例,可用于漏洞利用开发、流量的分析捕获等等。我们使用这个库实现对网络数据包的发送、监听和解析,编写可以用进行网络探测扫描的脚本
scapy库pycharm内的导入
file → settings → project:pythonproject → python interpreter
点击“+”,搜索scapy,install package
在scapy中,使用了”类+属性”的方法来构造数据包,每一个网络协议都是一个类,所以只需要实例化一下这个类,就可以创建一个该协议的数据包,假设我们构造一个IP数据包,如下:
IP()
导入scapy库构造数据包
- from scapy.layers.inet import IP
-
- pkt = IP()
- print(pkt)
执行结果如图下所示,以字节格式显示了IP数据包的结果,由于bytes保存的就是原始的字节数据,可以直接在网络上进行传输
对于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)
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()则以十六进制显示数据包的内容
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())
刚才我们构造了一个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"))
以上两个函数的特点是只发不收,也就是说只会将数据包发送出去,但是不会管这个数据包是否会被目的地址接收,同样也不会处理该数据包的应答数据包,在实际应用中,我们不但要将制作好的数据包发送出去,同样需要接收响应数据包
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()
这个函数可以在自己的程序中捕获经过本机网卡的数据包
该函数的完整格式为:
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个及以上时停止监听
- 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')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。