前面知道了在scapy中,不管是ip包,还是以太包,还有tcp包,或者它们集合在一起的包都是一个Packet,这是在数据包组织意义上讲的,另外从数据包最终组合的意义上讲,scapy最引人入胜的地方还在于Packet本身也是一个生成器,即generator,这是python中一个很重要的概念。Packet是一个生成器并不是为了方便或者美观,而是scapy本身要求的。
由于Packet表示的是一个单独层的数据包或者多层组合后的数据包,比如tcp数据段作为ip数据报的载荷(payload),因此如果设计的好一些,我们希望能按照协议栈本身理解数据包的方式去组合数据包,也就是说,完全按照分层协议的自解释机制,来一层一层从下往上将数据包构建好,比如在链路层的时候,看到上层是ip,那么就生成一个IP对象,然后在ip层,看到上层是tcp,那么生成一个TCP对象,依次类推,这样就会很方便,如果按照这个思路去设计,我觉得任何人都能想到递归和枚举,剩下的就是针对不同语言的编码问题了,scapy由python实现,将Packet本身作为一个generoter也是一个很自然的想法,这是因为对于一个自链路层开始向上构建的数据包,它只知道ip是它的payload,而不知道ip上面是什么,对于ip来讲也是一样,可是不管怎样,任何的payload都是一个Packet,因此如果我们能从链路层开始对其payload做for...in...操作的话,就能遍历到整个的协议层,将以太层的payload设置为payloadS(复数,因为这个payload还包含有更上层的payloadS...),然后第一次我们取出eth本身,第二次取出ip1,第三次取出tcp1...,针对于每一层的Packet,它本身又是一个生成器,生成器生成一个迭代器,该迭代器返回的next即是它本身,这样再通过递归就可以将所有层次的数据包组合在一起了。
所有这一切的开始都在str函数,在str中:
def __str__(self):
return self.__iter__().next().build()
self.__iter__().next()得到了Ether对象,调用它的build即可先构建以太头,再构建payload:
def do_build(self):
p=""
for f in self.fields_desc:
p = f.addfield(self, p, self.__getattr__(f))
pkt = p+str(self.payload)
return pkt
在do_build中,str(self.payload)又会开启一次针对payload的__str__()(间接的对payload的__iter__的调用)的调用,从而开始了构建IP对象的过程,依次类推。这样就需要将__iter__实现的非常好:
00def __iter__(self):
01 def loop(todo, done, self=self):
02 if todo:
03 eltname = todo.pop()
04 elt = self.__getattr__(eltname)
05 if not isinstance(elt, Gen):
06 if self.fieldtype[eltname].islist:
07 elt = SetGen([elt])
08 else:
09 elt = SetGen(elt)
10 for e in elt:
11 done[eltname] = e
12 for x in loop(todo[:], done):
13 yield x
14 else:
15 if isinstance(self.payload,NoPayload):
16 payloads = [None]
17 else:
18 payloads = self.payload
19 for payl in payloads:
20 done2 = done.copy()
21 for k in done2:
22 if isinstance(done2[k], RandNum):
23 done2[k] = int(done2[k])
24 pkt = self.__class__(**done2)
25 pkt.underlayer = self.underlayer
26 pkt.overload_fields = self.overload_fields.copy()
27 if payl is None:
28 yield pkt
29 else:
30 yield pkt/payl
31 return loop(map(lambda x:str(x), self.fields.keys()), {})
其实它只有一行,那就是第31行,它调用了一个子函数,首先map函数将所有我们手工设置的该层Packet的fields转化成一个list,然后调用loop,整个loop分为两大块,以17行的else做分割。在前半部分,将fields链表中的字段一个个pop出,比如对于IP对象而言就是src,dst,ttl之类,直到没有了的时候再次在12行递归调用loop的时候会进入后半部分else分支,此时处理它的payloadS(所有的上层数据),这个核心的实现尽在第19行,一个for...in的调用,这里就会对payloadS调用其__iter__方法,过程又回到了第31行,只是这次的self变了,也就是对象变了,变成了上一层数据的Packet对象了,然后一切如故...。
在L3PacketSocket的send中从str的调用开始构建整个以太帧,整个调用过程如下:
00 call Ethernet obj-__str__ 1
01 call Ethernet obj-__iter__ 2
02 call Ethernet obj-__iter__-loop 3
03 没有为Ether设置属性,因此直接进入else
04 call IP obj-__iter__ 4
05 call IP obj-__iter__-loop 5
06 取出dst
07 call IP obj-__iter__-loop 6
08 取出src
09 call IP obj-__iter__-loop 7
10 没有其它属性了,进入else
11 call TCP obj-__iter__ 8
12 call TCP obj-__iter__-loop 9
13 取出sport
14 call TCP obj-__iter__-loop 10
15 取出dport
16 call TCP obj-__iter__-loop 11
17 没有其它属性了,进入else
18 call None obj-__iter__ 12
19 11返回TCP obj
20 10返回TCP obj
21 9返回TCP obj
22 8返回IP obj
23 7返回IP obj
24 6返回IP obj
25 4返回Ether obj
26 2返回Ether obj
27 call Ethernet obj-__iter__-next 13
28 13返回Ether obj
29 call Ether obj-build 14
30 call Ether obj.payload-str 15
31 call IP obj-__str__
32 从第4行到第24行
33 ...
从32行可以看出,在从下到上的构建过程中,在构建上一层的时候也即是构建此层的payload的时候,需要对payload调用str函数,由于在第一次构建Ether obj的时候已经做过这件事了,也就是说,在构建链路层数据包的时候调用str(Ether obj),由于__iter__的实现有递归的性质,以上各层的Packet对象其实已经构造好了,实在没有必要再来一次,就是说,如果现在有4件事,分别分1,2,3,4,从1开始做,我们希望的是1-2-3-4这个顺序,或者1,2,3,4也可以,然而scapy的方式却是:1,2,3,4-2,3,4-3,4-4这实在是一个我认为可以改进的地方。不过既然scapy实现了如此复杂又美妙的__iter__以及数据包兼作generator的角色,我觉得已经可以抵消美中之不足矣!
分享到:
相关推荐
使用python来解析加密数据包,可通过pycharm安装Scapy-ssl_tls库文件,但库文件经常会安装失败,因此需要考虑直接安装python对应版本的Scapy-ssl_tls库文件
pcap-1.1-scapy-20090720.win32-py2.5
scapy-2.2.0是一款很有用的交互软件,功能很强大,下载后,在LINUX下解压,并安装,系统里要安装有PYTHON2.5以上版本~~
Python3 scapy模块 scapy-python3-0.14.tar
Scapy官方教程 没错,就是你要找的。Philippe Biondi and the Scapy community build your own tools with scapy
scapy交换机、路由器审计工具,支持自定义构造DHCP Discover、DHCP Offer、DHCP ACK 、DTP、802.1数据包
scapy最近版本源码,支持python版本2.7,3.4至3.8,不依赖python库;可用命令行交互及引用库形式,引用库需使用"from scapy import * "形式
scapy 的 ICAP/1.0 协议实现(从 invernizzi 的 scapy-http 复制代码) 用法 [root@user ~]$ scapy WARNING: No route found for IPv6 destination :: (no default route?) Welcome to Scapy (2.2.0-dev) >>> ...
虚假假货 使用Python和Scapy的伪无线接入点(AP)实现,旨在方便地测试802.11协议和实现。 该库正在开发中,目前仅支持开放的802.11网络。 动机 ...从那里开始,用scapy-fakeap设置基本AP非常简单,
基于python命令行修改数据包。基于python命令行修改数据包
则考虑将pip的安装替换源替换为内部替代源,具体的操作步骤可以查考介绍博客使用方法运行程序Linux下首先需要切换到程序目录下,然后用管理员权限运行cd SCAPY-GUI-MASTERsudo python3 mainGUI.pyWindows下用管理员...
Scapy-osx 为OSX修补的最新Scapy版本。 在10.10.3测试 安装 更新端口树并安装依赖项 port selfupdate port install libdnet py27-libdnet py-readline py-gnuplot py-crypto py-pyx swig gnuplot graphviz 然后从...
替补使用Scapy的小型python脚本使用Linux内置的Iptables进行ARP中毒和IP地址重定向,以执行MITM攻击。 目前,它的测试很有限,这意味着当心它不起作用。 另外,这会弄乱您的Iptable配置的规则,因此,如果您关心这种...
资源分类:Python库 所属语言:Python 资源全名:scapy_helper-0.1.12.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
About Scapy What is Scapy Scapy is a powerful interactive packet manipulation program. It is able to forge or decode packets of a wide number of protocols, send them on the wire, capture them, match ...
wifi-deauth-detector python scapy- nodejs -mongodb
r2scapy - 一个用Scapy解码数据包的radare2插件
scapy 英文本 python可以调用scapy库模拟各种网络报文
参考官方文档,win64 scapy2.3.2 安装全部以及软件
包含scapy在windows下的所有安装包和安装说明 scapy是一个强大的交互式(interactive)的包操作程序,用python写的,有一个python的命令行解释器界面,可直接运行,当然也可以作为第三库。