您当前的位置:首页 > 计算机 > 编程开发 > Python

scapy的基本用法

时间:09-05来源:作者:点击数:

不知道为何,网上有些把scapy跟scrapy搞混的。scapy是一个操作网络数据包的工具(Packet crafting),scrapy是一个屏幕抓取和web抓取框架(A Fast and Powerful Scraping and Web Crawling)...

scapy的基本用法还是参照scapy官网上的来做吧。翻译对我来说是一件困难的事,幸亏有人已经做过类似的工作,如这篇博客Scapy使用文档中文版。那对于一些我不确定的翻译,我就直接使用这篇博客的。我的文章也可以看作是对于Scapy使用文档中文版的转载;不过我会根据自己的理解,以及结合不同网络协议的学习,加一些注解。测试平台是linux centos7。

安装

python3 -m pip install scapy

或者尝试

python3

pip3 install scapy

开始使用scapy

scapy的交互式shell在终端会话中,发送数据包需要root权限,所以普通用户需要使用sudo命令

sudo ./scapy

我这root用户,直接使用scapy命令就好

配置终端显示颜色

将conf.color_theme设置为下列样式中的一种:

DefaultTheme, BrightTheme, RastaTheme, ColorOnBlackTheme, BlackAndWhite, HTMLTheme, LatexTheme

如:

conf.color_theme = BrightTheme()

交互式教程

新建一个包(packet),测一测以下代码

此处IP创建了一个默认的数据包,使用ls(IP())可以查看IP数据包的参数

叠层(Stacking layers)

“/”操作符在两个层之间起到一个组合的作用。当使用该操作符时,下层可以根据其上层,使它的一个或多个默认字段被重载。(您仍可以赋予您想要的值)一个字符串也可以被用作原始层。

每一个数据包都可以被建立或分解(注意:在Python中“_”(下划线)是上一条语句执行的结果):

被拆分的包保留了所有字段,如果这样显得太啰嗦,可以通过hide_defaults()方法删除重复的字段

读取PCAP文件

a=rdpcap("/spare/captures/isakmp.cap")

图形转储(PDF,PS)

如果你安装了PyX,你可以将一个包或者一系列包图形转储为PostScript/PDF文件(下面是比较丑的PNG图片,如果是PostScript/PDF格式的话质量要更好)

未安装pyx提示:ImportError: PyX and its dependencies must be installed

a[423].pdfdump(layer_shift=1)

a[423].psdump("/tmp/isakmp_pkt.eps",layer_shift=1)

命令 作用
raw(pkt) 组装数据包
hexdumo(pkt) 转换成16进制
ls(pkt) 列出字段值
pkt.summary() 查看数据包的一行摘要
pkt.show() 包的开发视图
pkt.show2() 和show一样,但是用于组装包上(例如,计算校验和(checksum))
pkt.sprintf() 用包字段值填充格式化字符串
pkt.decode_payload_as() 改变有效载荷的解码方式
pkt.psdump() 绘制一个解释说明的PostScript图表
pkt.pdfdump() 绘制一个解释说明的pdf
ptk.command 返回一个可以生成包的scapy命令

生成数据包的集合/生成一组包

目前我们只是生成一个数据包。让我们看看如何轻易地定制一组数据包。整个数据包的每一个字段(甚至是网络层次)都可以是一组。在这里隐含地定义了一组数据包的概念,意思是在所有字段中使用笛卡尔积来生成一组数据包。

某些操作(如修改一个数据包中的字符串)无法对一组数据包使用。在这些情况下,如果您忘记展开您的数据包集合,只有您忘记生成的列表中的第一个元素会被用于组装数据包。

(这里其实就是利用python的list生成一组数据包sets of packets)

命令 集合
summary() 显示每个包的摘要列表
nsummary() 跟前面的一样,并且带有包数量
conversations() 显示会话的图标
show() displays the preferred representation(通常用nsummary())
filter() 返回一个由lambda函数过滤的包列表
hexdump() 返回所有包的一个hexdump数据
haxraw() 返回所有包的Rawlayer的一个hexdump数据
padding() 返回一个带有填充的包的hexdump
nzpadding() 返回一个非0填充的包的hexdump
plot() 绘制应用于数据包列表的lambda函数
make table() 根据lambda函数显示一个表格

发送包

我们已经知道如何去修改包,现在让我们看看怎么发送它们。send()函数在第3层(网络层?)上发送包。这就是说,它将为你处理第2层数据和路由。sendp()函数工作在第2层(数据链路层?)。选择正确的接口和链接层协议(link layer protocol)完全取决于你。如果return_packets=True,则send()和sendp()将返回已发送的包列表。

ttl,即Time To Live的缩写,该字段指定IP包被路由器丢弃之前允许通过的最大网段数量,TTL是IPv4报头的一个8bit字段。虽然TTL从字面上翻译,是可以存活的时间,但实际上TTL是IP数据包在计算机网络中可以转发的最大跳数。TTL字段由IP数据包的发送者设置,在IP数据包从源到目的的整个转发路径上,每经过一个路由器,路由器都会修改这个TTL字段值,具体的做法是把该TTL的值减1,然后再将IP包转发出去。如果在IP包到达目的IP之前,TTL减少为0,路由器将会丢弃收到的TTL=0的IP包并向IP包的发送者发送 ICMP time exceeded消息。(百度百科)

错误提示:WARNING: Mac address to reach destination not found. Using broadcast.这个错误是因为应该用sendp发送而用了send

关于返回值的测试

Fuzzing

fuzz()函数可以通过一个具有随机值、数据类型合适的对象,来改变任何默认值,但该值是不能被计算的(像校验和那样)。这使得可以快速建立循环模糊化测试模板。在下面的例子中,IP层是正常的,UDP层和NTP层被fuzz。UDP的校验和是正确的,UDP的目的端口被NTP重载为123,而且NTP的版本被更变为4.其他所有的端口将被随机分组:

备注:Fuzzing是模糊测试,通过函数随机生成大量测试用例来测试程序。

发送并且接收包

现在,我们来做一些有趣的事,src()函数用来发送包并且接收响应。这个函数返回包及其响应,以及没有响应的包。函数sr1()是一个变体,它只返回一个响应包(不管是发送一个包还是一组包)。这些包必须是第三层的包(IP包,ARP包等)。函数srp()做类似的事,不过它是发送第二层包(如以太包,802.3等),如果没有应答,或者超时,会返回一个空值(比如,构建包字段填写错误,返回空值)。

一个DNS查询(rd=recursion desired)。主机192.168.5.1是我的DNS服务器。注意从我Linksys来的非空填充具有Etherleak缺陷:

>>>sr1(IP(dst="192.168.5.1")/UDP()/DNS(rd=1,qd=DNSQR(qname="www.slashdot.org")))Begin emission:Finished to send 1 packets...*Received 3 packets, got 1 answers, remaining 0 packets<IP version=4L ihl=5L tos=0x0 len=78 id=0 flags=DF frag=0L ttl=64 proto=UDP chksum=0xaf38src=192.168.5.1 dst=192.168.5.21 options='' |<UDP sport=53 dport=53 len=58 chksum=0xd55d|<DNS id=0 qr=1L opcode=QUERY aa=0L tc=0L rd=1L ra=1L z=0L rcode=ok qdcount=1 ancount=1nscount=0 arcount=0 qd=<DNSQR qname='www.slashdot.org.' qtype=A qclass=IN |>an=<DNSRR rrname='www.slashdot.org.' type=A rclass=IN ttl=3560L rdata='66.35.250.151' |>ns=0 ar=0 |<Padding load='\xc6\x94\xc7\xeb' |>>>>

发送和接受函数族(function family)是scapy的核心。它们返回两个列表。第一个就是发送的数据包及其应答组成的列表,第二个是无应答数据包组成的列表。为了更好地呈现它们,它们被封装成一个对象,并且提供了一些便于操作的方法:

>>>sr(IP(dst="192.168.8.1")/TCP(dport=[21,22,23]))Received 6 packets, got 3 answers, remaining 0 packets(<Results: UDP:0 TCP:3 ICMP:0 Other:0>, <Unanswered: UDP:0 TCP:0 ICMP:0 Other:0>)>>>ans,unans=_>>>ans.summary()IP / TCP 192.168.8.14:20 > 192.168.8.1:21 S ==> Ether / IP / TCP 192.168.8.1:21 > 192.168.8.14:20 RA / PaddingIP / TCP 192.168.8.14:20 > 192.168.8.1:22 S ==> Ether / IP / TCP 192.168.8.1:22 > 192.168.8.14:20 RA / PaddingIP / TCP 192.168.8.14:20 > 192.168.8.1:23 S ==> Ether / IP / TCP 192.168.8.1:23 > 192.168.8.14:20 RA / Padding

如果对于应答数据包有速度限制,你可以通过“inter”参数来设置两个数据包之间等待的时间间隔。如果有些数据包丢失了,或者设置时间间隔不足以满足要求,你可以重新发送所有无应答数据包。你可以简单地对无应答数据包列表再调用一遍函数,或者去设置“retry”参数。如果retry设置为3,scapy会对无应答的数据包重复发送三次。如果retry设为-3,scapy则会一直发送无应答的数据包,直到“timeout”参数等待最后一个数据包已发送的时间。

SYN Scans

经典的SYN扫描可以通过执行下面的提示符命令初始化

上面向Google的80端口(我这里改成能ping通的其他主机地址了)发送单个SYN包,在接受单个响应时退出。

从上面的输出可以看出,目标主机返回一个“SA”或者SYN-ACK标志标明端口是开放的。

使用其他标志位扫描一下系统的440到443端口:

>>>sr(IP(dst="192.168.1.1")/TCP(sport=666,dport=(440,443),flags="S"))

或者:

>>>sr(IP(dst="192.168.1.1")/TCP(sport=RandShort(),dport=[440,441,442,443],flags="S"))

可以对收集的数据包进行摘要(summary),来快速地浏览响应:

>>>ans,unans=_>>>ans.summary()IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:440 S ======> IP / TCP 192.168.1.1:440 > 192.168.1.100:ftp-data RA / PaddingIP / TCP 192.168.1.100:ftp-data > 192.168.1.1:441 S ======> IP / TCP 192.168.1.1:441 > 192.168.1.100:ftp-data RA / PaddingIP / TCP 192.168.1.100:ftp-data > 192.168.1.1:442 S ======> IP / TCP 192.168.1.1:442 > 192.168.1.100:ftp-data RA / PaddingIP / TCP 192.168.1.100:ftp-data > 192.168.1.1:https S ======> IP / TCP 192.168.1.1:https > 192.168.1.100:ftp-data SA / Padding

进度......20%

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门