ITPub博客

首页 > 数据库 > 数据库开发技术 > 盘点一款Python发包收包利器——scapy

盘点一款Python发包收包利器——scapy

原创 数据库开发技术 作者:Python进阶者 时间:2021-04-29 09:00:00 0 删除 编辑
点击上方“Python爬虫与数据挖掘”,进行关注

回复“书籍”即可获赠Python从入门到进阶共10本电子书

今

日

鸡

汤

潮平两岸阔,风正一帆悬。

    大家好,我是黄伟。今天跟大家讲的是Python 用于发送接受网络数据包的模块-------scapy。

前言

众所周知,我们每天上网都会有很多数据包需要发送,然后处理在接受在发送,这样一个循环往复的过程,

这里就显示了很多数据包的发送接收数据。那么,什么是包呢?下面一起看看。

包(packet)是网络通信传输中的数据单位,一般称之为数据包,其主要由源地址,目标地址,净载数据组成。包括包头和包体,包头是固定长度,包体长度不变。简单了解下包的定义,下面我们来看看发包利器scapy的用法吧。(参考资料来源:百度百科-数据包)


一、常用命令

1、ls():显示所有支持的数据包对象,可带参数也可不带,参数可以是任意具体的包。

可以看出,它包含了全部的内容,如果我们想详细查看某个模块中的内容,比如说我想查看ARP ,tcp的话了,可以这样:

在这里要告诉大家的是,我们必须要注意大小写,ls(ARP)这样才可以得出正确结果,ls(arp)是错误的。


2、lsc():列出所有函数

满屏的英文,小编我头都是大的,不知道大家此时此刻是什么样的心情,哈哈哈哈。


3、hide_defaults():用来删除一些用户提供的那些和default value相同的项目

a=IP()print(a.hide_defaults())


4.display():可以简单查看当前packet的各个参数的取值情况,

a=IP()a.display()


5.更多命令

命令                                  作用show_interfaces()                  显示网卡信息
str(pkt) 组装数据包
hexdump(pkt) 十六进制转储
ls(pkt) 显示出字段值的列表
pkt.summary() 一行摘要
pkt.show() 针对数据包的展开视图
pkt.show2() 显示聚合的数据包(例如,计算好了的校验和)
pkt.sprintf() 用数据包字段填充格式字符串
pkt.decode_payload_as() 改变payload的decode方式
pkt.psdump() 绘制一个解释说明的PostScript图表
pkt.pdfdump() 绘制一个解释说明的PDF
pkt.command() 返回可以生成数据包的Scapy命令
nsummary() 同上,但规定了数据包数量
conversations() 显示一个会话图表
filter() 返回一个lambda过滤后的数据包列表
hexdump() 返回所有数据包的一个hexdump
import_hexcap() 将hexdump重新导入到Scapy中
hexraw() 返回所有数据包Raw layer的hexdump
padding() 返回一个带填充的数据包的hexdump
nzpadding() 返回一个具有非零填充的数据包的hexdump
plot() 规划一个应用到数据包列表的lambda函数
make table() 根据lambda函数来显示表格
traceroute("baidu.com") 查看IP路径的traceroute功能
export_object() 数据包转换成base64编码的Python数据结构
import_object() 可以将输出重新导入
save_session() 保存所有的session变量
load_session() 读取保存的session
fuzz() 更改一些默认的不被计算的值(比如校验和checksums),更改的值是随机的,但是是符合字段的值的。


二、嗅探数据包

from scapy.all import *pkt = sniff(iface = "Realtek PCIe GBE Family Controller",count = 3 ,filter='tcp',prn = lambda x: x.sprintf('{IP:%IP.src%->%IP.dst%\n}{Raw:%Raw.load%\n}'))
filter:过滤条件iface:网卡接口名称count:数据包数量prn:回调函数,通常与lambda搭配使用sprintf()函数控制输入信息
抓取源地址为192.168.3.3的端口为80的tcp报文:sniff(filter="ip src 192.168.3.3 and tcp and tcp port 80", prn=lambda x:x.summary())
抓取目的地址网段为192.168.3.3/24的报文:sniff(filter="dst net 192.168", prn=lambda x:x.summary())
抓取非ICMP的报文:sniff(filter="not icmp", prn=lambda x:x.summary())

将抓取到的报文的summary打印出来:sniff(filter="icmp", prn=lambda x:x.summary(), count=10)
将所有IP报文的源地址打印出来:sniff(filter="icmp", prn=lambda x:x[IP].src, count=10)


三、构造数据包

pkt= Ether()/IP(dst='192.168.1.2')/TCP(dport=80)

提到数据包,不得不说各个协议了,提到协议,又自然而然想到了osi七层模型。

以上便是各个网络协议对应的osi模型,那么各个协议的用法是怎样的了,下面我们一起来看下。


四、各个协议用法

1、构造一个 IP 包,并传入一些参数

#构造一个 IP 包,并传入一些参数pkt = IP(dst="192.168.1.2",ttl=10)ls(pkt)  version:版本号ihl:头长度tos:服务类型len:IP数据包总长id:标识符flags:标记flag:片偏移ttl:生存时间proto:协议类型chksum:头部校验src:源IP地址dst:目的IP地址options:可选项


2、构造ARP包

#构造ARP包ARP(op=1, hwdst="ff:ff:ff:ff:ff:ff", pdst=ip_address)#arp类的构造函数列表:ls(ARP)hwtype     : XShortField          = (1)  值为1表示以太网地址,其它还可能表示令牌环地址ptype      : XShortEnumField      = (2048)  0x0800表示IP地址,其它还可能是ICMP/IGMPhwlen      : ByteField            = (6)   ARP报文中,它的值为6plen       : ByteField            = (4)  ARP报文中,它的值为4op         : ShortEnumField       = (1) 取值为1或者2,代表ARP请求或者响应包。1.ARP请求,2.ARP应答,3.RARP请求,4.RARP应答 hwsrc      : ARPSourceMACField    = (None) 发送方Mac地址。psrc       : SourceIPField        = (None) 发送方IP地址。hwdst      : MACField             = ('00:00:00:00:00:00') 目标Mac地址。pdst       : IPField              = ('0.0.0.0') 目标IP地址。


3、构造Ether

#构造EtherEther(dst="ff:ff:ff:ff:ff:ff")ls(Ether)dst        : DestMACField         = (None) 目的MACsrc        : SourceMACField       = (None) 源MACtype       : XShortEnumField      = (36864)构造一个以太网数据包通常需要指定目标和源MAC地址,如果不指定,默认发出的就是广播包ff:ff:ff:ff:ff:ff


4、构造TCP包

#构造TCP包sport      : ShortEnumField                      = 20              (20) 目标端口dport      : ShortEnumField                      = 80              (80)  源端口seq        : IntField                            = 0               (0)ack        : IntField                            = 0               (0)dataofs    : BitField (4 bits)                   = None            (None)reserved   : BitField (3 bits)                   = 0               (0)flags      : FlagsField (9 bits)                 = <Flag 2 (S)>    (<Flag 2 (S)>)window     : ShortField                          = 8192            (8192)chksum     : XShortField                         = None            (None)urgptr     : ShortField                          = 0               (0)options    : TCPOptionsField                     = []              (b'')


五、发包,收包

可分为两种情况,用法如下:

1、只发不收

send(pkt, inter=0, loop=0, count=1, iface=N) pkt:数据包inter:发包间隔时间count:发包数量iface:网卡接口名称
send(),在第三层发包,没有接收功能;send(IP(dst="",ttl=2)/ICMP())
sendp(),在第二层发包,没有接收功能。sr(Ether()/IP(dst=""))


2、发包且收包

sr()和sr1()都是在第三层发包,sr1表示只接收第一个回复。
sr(IP(dst="",ttl=(1,4))/TCP(dport=[21,23,80],flags="S")) 返回两个值
sr1(IP(dst="",ttl=(1,4))/ICMP())
srloop(IP(dst="",ttl=1)/ICMP()) #不停的ping百度
srloop(IP(dst="",ttl=1)/ICMP(),inter=3,count=2) #每隔3秒ping一次,一共执行两次
#inter表示间隔,count记录次数
srp()和srp1()都是根据第二层发包,srp1表示只接收第一个回复srp(Ether()/IP(dst=""))srp1(Ether()/IP(dst=""))


六、SYN半开式扫描

当TCP链接指定端口时,flags参数设为S时则为半开式扫描,若此时该端口处于监听状态,返回syn/ack,否则返回rst/ack.

sr1(IP(dst="192.168.1.2")/TCP(dport=80,flags="S"))


七、数据包序列化,反序列化

序列化:将数据包对象保存为pcap文件

反序列化:读取pcap文件中的内容

pkt= Ether()/IP(dst='192.168.1.2')/TCP(dport=80)#将嗅探到的数据包内容写到pcap文件中 wrpcap("hw.pcap",pkt)
#读取pcap文件。read=rdpcap('hw.pcap')print(read[1])#打印嗅探到的包的数据


八、数据包与字符串转换

更加直观清晰的分析数据。

zfc= str(pkts[0]) z= Ether(zfc)


九、导入导出base64编码

为了方便我们对数据进行加密而发明的一种方式。

export_object(str(pkts[0])) 导出数据包new_Pkt = import_object() #将上一步导出的字符串填入


十、离线数据包的解析

如果我们捕获到数据包,未联网的情况下如何解析呢?

现在就可以使用我们的离线数据包分析数据了:

sniff(offline = "hw.pcap")#离线数据包


总结

通过上面的学习,我们对scapy算是有了一个基础性的认识了,scapy的确很强大,简单的几行命令就能实现发包收包,极大的节省了我们的开发时间。如果你深入学习它的每个命令,你会发现更多有趣的事情,当然这么强大的工具可不要拿来做坏事哦!!

想要学习更多网络爬虫知识,请点击阅读原文前往爬虫网站。

------------------- End -------------------

往期精彩文章推荐:

欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

想加入Python学习群请在后台回复【入群】

万水千山总是情,点个【在看】行不行

/今日留言主题/

随便说一两句吧~

原文作者:Python爬虫与数据挖掘;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2024-12-18

  • 博文量
    913
  • 访问量
    379688