发包真香之:scapy工具

scapy – python 可自由组包

参考学习:初识Scapy–Python的Scapy/Kamene模块学习之路

scapy 介绍

Scapy是基于Python语言的网络报文处理程序,它可以让用户发送、嗅探、解析、以及伪造网络报文,运用Scapy可以进行网路侦测、端口扫描、路由追踪、以及网络攻击。Kamene是Scapy的分支,一开始的Scapy并不支持Python 3,为了支持Python 3就诞生了Scapy3k这个分支,为了方便区分就把Scapy3k更名为了Kamene。注意:最新的Scapy是支持Python 3的(Scapy 2.4.0+)。
Scapy 官网: https://scapy.net/
image.png
image.png
Scapy Pypi包主页: https://pypi.org/project/scapy/

:::info
官方指导文档:https://scapy.readthedocs.io/en/latest/
:::

如何选择Python和Scapy的版本?
这是Scapy版本的兼容列表:

scapy 安装

sudo apt install python3-scapy

运行 scapy 后,会进入到 python 的环境

sudo scapy


这就是一个Python shell,所以可以用exit()退出它。

scapy 的使用

ping = IP(dst="http://www.baidu.com") / ICMP()

Scapy中的斜杠’ / ‘就是用来区分网络层次的,一般来说把底层的协议写在左边,把高层的协议写在右边,就像下面这样:
数据链路层协议 / 网络层协议 / 传输层协议 / 应用层协议及数据
下面是TCP/IP协议族关系表:
image.png一般来说我们不需要关心数据链路层的协议Scapy会为我们自动配置。
Scapy定义了很多函数和类,通过这些函数和类我们就可以构造数据包。这里的IP可以用来生成一个IP的报文头。

IP()

ping = IP(dst="http://www.baidu.com") 

有基础的朋友可能会说:“这明明是域名,不是IP地址!“。对,这确实是域名,但是Scapy功能非常强大,当你把dst赋值为域名时Scapy会自动调用一个名为Net的函数来解析域名。

list()

还可以指定掩码位数:

list(Net('http://www.baidu.com/30'))


然后我们再来看看ICMP协议:
ICMP(互联网控制消息协议)是互联网协议族的核心协议之一。它用于TCP/IP网络中发送控制消息,提供可能发生在通信环境中的各种问题反馈,通过这些信息,使管理者可以对所发生的问题作出诊断,然后采取适当的措施解决(维基百科)。ping就是基于ICMP协议的。

ICMP()

生成一个ICMP报文头:

ICMP只有5个字段这些字段分别的意思是:

  • type:ICMP的类型,标识生成的错误报文。
  • code:进一步划分ICMP的类型,该字段用来查找产生错误的原因。例如,ICMP的目标不可达类型可以把这个位设为1至15等来表示不同的意思。
  • chksum:校验码部分,这个字段包含有从ICMP报头和数据部分计算得来的,用于检查错误的数据,其中此校验码字段的值视为0。
  • id:这个字段包含了ID值,在Echo Reply类型的消息中要返回这个字段。
  • Seq:这个字段包含一个序号,同样要在Echo Reply类型的消息中要返回这个字段。

以下是ICMP type code的对应表:
一般来说只用记住这2个,type为8、code为0是ping的请求,type为0、code为0是ping的响应。
知道这些之后我们就可以构造一个ICMP请求报文头。注意Scapy会为每个报文设定默认值,调用ICMP函数默认就是构造一个ICMP请求,所以下面两条是等价的:
ICMP()
ICMP(type=8, code=0)
也可以查看对象的type,code属性值

ls(<协议名>)

通过ls函数就可以查看默认值
也可以同时查看实际值和默认值

ls(IP(dst="http://www.baidu.com"))

没有括号的是实际值,有括号的是默认值

_.show()

show()方法获取报文字段信息(在Python shell中下划线’_’表示上条语句执行结果)

长度(len),校验和(chksum)、协议(proto)等字段Scapy都会自动计算,所以我们只有3个字段需要注意一下,ttl、src、dst。

  • ttl: 生存时间值(Time To Live),当数据包每进行进行一次转发时TLL值就会减一,TTL为0时数据包就会被丢弃,TTL的主要作用是避免IP包在网络中的无限循环和收发,节省了网络资源,并能使IP包的发送者能收到告警消息(路由追踪原理)。
  • src: 源地址(Source Address)数据发送者的地址
  • dst: 目的地址(Destination Address)数据接收者的地址

现在我们再回头看刚刚构造的ping请求包就应该可以明白其中的意思了:

ping = IP(dst="192.168.40.1") / ICMP()

注意: 为了方便演示我把地址换成了自己的网关
ICMP函数首先构造一个ping请求报文头,然后IP函数构造一个IP报文头设置目标为’192.168.40.1’,最后赋值给变量ping。
构造完数据包之后那我们就来发送数据包。

resultpkt = sr1(ping)

sr1函数发送一个数据包,再接收一个数据包,然后返回响应的数据包。发送成功会显示形如下面信息。

Received 3 packets意思是: 收到了3个包
got 1 answers意思是: 得到了一个应答。也就是我们需要的包。
rermaining 0 packets意思是: 剩余没有应答得包。
直接在命令行输入变量名就可以输出接收到的包信息了。

好了得到回显数据之后就可以通过一些方法来访问其中的数据了。通过下标访问每个报文数据:

这里可能有一点难理解,简单解释一下就是:对于IP协议来说ICMP报文头和Padding实际上就是一堆数据,当我们获取IP报文时它会把IP报文头和数据一起输出。对于获取ICMP报文也是如此,输出ICMP报文头和Padding数据**(报文实际上就是报文头加数据)**。

通过属性的形式获取字段
resultpkt[0].src

resultpkt[1].type

可以加下标也可以不加,但是推荐加上。例如我们想访问ICMP的校验和(chksum),不加标访问的是IP的校验和加下标[1]才可以访问ICMP的校验和

通过fields属性以字典的形式获取报文头
获取IP报文头:
resultpkt[0].fields

获取ICMP报文头 :
resultpkt[1].fields

获取Padding数据:
resultpkt[2].fields

既然是字典就可以通过键获取对应的值。
获取IP报文头的源地址:
resultpkt[0].fields[‘src’]

获取IP报文头的目标地址:
resultpkt[0].fields[‘dst’]

获取ICMP报文头的type值和code值:
resultpkt[0].fields[‘type’]
resultpkt[0].fields[‘code’]

还有一种高级的方法,通过协议下标来访问报文头:

就是把数字下标改为了对应协议的下标功能和数字下标基本一样,但是用协议下标可以增加程序的灵活性和可读性。

Scapy数据包收发机制

Scapy数据包发送函数:

  • sr1: 发送一个数据包并接收一个相匹配的数据包
  • srp1: 与sr1一样但是关注数据链路层(以后讲ARP协议时会用)
  • sr: 发送数据包并接收相匹配的数据包
  • srp: 与sr一样但是关注数据链路层(以后讲ARP协议时会用)
  • send: 只发送数据包不接收数据包
  • sendp: 与send一样但是关注数据链路层(以后讲ARP协议时会用)

下图就是Scapy sr函数发收流程图:

通过实例理解一下
生成一组数据包然后通过sr函数发送,timeout参数设置超时时间默认单位为秒,这里设置超时时间为10秒钟。

result = sr(IP(dst="10.72.1.0/24") / ICMP(), timeout=10)


直接输入变量名或用type函数就可以看到返回的数据是个元组

通过下标访问results中的数据

上图通过result[0],获取有响应的包的列表,用len函数获取长度,用display方法来展示数据。
result[0]里的每个素都是元组,每个元组都是由发送的包和它相匹配的应答包组成。

分别访问发送的包和接收的包
对于单个数据包的操作就和就前面的一样了
通过result[1]访问没有相应的请求数据表列表,里面的元素就是单个数据包。

scapy 实例

发送一个 RA 包

在Linux中,发送RA(Router Advertisement)包通常需要使用 scapy 这样的工具,它是一个强大的Python库,用于构建和发送网络数据包。以下是使用 scapy 发送RA包的命令示例:

sudo scapy

然后在 scapy 命令行中,你可以使用以下代码来构造和发送RA包:

from scapy.all import *

# 构造RA包
ra_packet = Ether(dst="00:C0:02:12:35:8A") / IPv6(dst="ff02::1") / ICMPv6ND_RA()

# 发送RA包
sendp(ra_packet, iface="你的网卡接口名")

在上述代码中:

  • Ether(dst=“00:C0:02:12:35:8A”) 指定了目的MAC地址。
  • IPv6(dst=“ff02::1”) 指定了IPv6的多播地址。
  • ICMPv6ND_RA() 构造了一个RA包。

请确保替换代码中的 “00:C0:02:12:35:8A” 为你的目的MAC地址,以及 “你的网卡接口名” 为你要发送数据包的网络接口名称(如 eth0wlan0 等)。

发送二层数据链路层包【MAC】

from scapy.all import Ether, sendp

# 构造以太网帧
eth_frame = Ether(dst="00:C0:02:12:35:89")

data = "hello mantic"
    
# 发送以太网帧
sendp(eth_frame/data, iface="你的网络接口名")

Screenshot from 2024-03-06 13-16-00.png

发送 IP 包【IP】

使用scapy发包工具,从192.168.3.2 的电脑发送一个二层协议包到IP是192.168.3.1,mac地址是00:C0:02:12:35:89的开发板,包的内容是hello mantic

from scapy.all import Ether, IP, sendp

# 构造以太网帧,指定目的 MAC 地址和源 MAC 地址
eth_frame = Ether(dst="00:C0:02:12:35:89")

# 构造 IP 数据包,指定目的 IP 地址和源 IP 地址
ip_packet = IP(dst="192.168.3.1", src="192.168.3.2")

# 自定义内容
data = "hello mantic"

# 构造数据帧
packet = eth_frame/ip_packet/data

# 发送数据帧
sendp(packet, iface="你的网络接口名")

开发一个ping扫描工具

下面代码的Git仓库地址: https://github.com/starunity/Sc

#!/usr/bin/env python3

from scapy.all import *

def pingscan(ip):
   """
   pingscan(ip)
   Ping the incoming IP.
   ip: Pass in an IP like 192.168.1.0 or 192.168.1.0/24
   """
   answer, uanswer = sr( \
       IP(dst=ip) / ICMP(), \
       timeout=10, verbose=False \
   )
 
   alive = []
 for send, recv in answer:
 if recv[ICMP].type == recv[ICMP].code == 0:
           alive.append(recv[IP].src)

 return alive


if __name__ == '__main__':
   ip = input("Enter IP address:")
   result = pingscan(ip)
   for i in result:
      print("{} is alive.".format(i))

第13行的sr函数里面的verbose参数是用来开启或关闭发收包详情的
verbose默认开启的效果:

verbose关闭的效果:

执行结果如下:

总结

scapy是一个很好用的发包工具,不过在使用中,是比较麻烦的,要自己组包需要写代码完成,不如hping3,下期介绍。

  • 30
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值