scapy用法整理

导入scapy:

from scapy.all import *

常用的查看命令:

ls() - 不带参数则查看所有可持的layer,也可以指定一个layer名称从而查询此layer的详细详细,例如ls(TCP)
lsc() - 查看当前scapy的所有功能列表
help() - 查看功能的帮助,例如help(hexdump)可以查看hexdump的作用和参数介绍
conf - 查看当前的配置信息,有些scapy功能没有指定参数时,默认值都取自这里

实时捕获报文:

过滤参数 - filter,可以wireshark支持的形式设定相关参数,例如filter='tcp port 80'
自定义过滤函数 - lfilter,可以指定一个函数,用来实现自己的过滤,例如lfilter=lambda p: p.haslayer(Raw),指定过滤所有带有data的包。filter和lfilter可以同时存在
包个数 - count,例如count=20,捕获20个包之后停止
接口 - iface,例如iface='eth1',多个接口可以通过list方式指定,例如iface=['eth0','eth1','lo']
自定义停止捕获函数 - stop_filter,可以指定一个函数,返回true则停止捕获,例如stop_filter=lambda p: p.haslayer(Raw) and 'stop flag' in p.getlayer(Raw).load,就可以指定在接收到'stop flag'字符之后停止抓包。

示例:
pcap=sniff(filter='tcp port 80',count=10, iface='lo')

存储/加载捕获的数据:

wrpcap('my.pcap',pcap)

读取捕获的pcap或者pcapng文件

pcap=rdpcap('my.pcap')
通过sniff也可以读取离线文件:
pcap=sniff(offline='/home/jma/Desktop/scapy/scapy_test.pcap')

显示捕获报文的内容:

show - 例如pcap.show,或者pcap[0].show
show() - 例如pcap.show(),或者pcap[0].show()
sniff获取的数据可以列表的方式操作,每一个元素都是一条捕获的消息,show可以显示概要信息,show()则会显示详细的内容,或者格式化显示内容

判断某一消息中是否含有相关的layer,用haslayer()方法:

pcap[0].haslayer(UDP) - 判断是否含有UDP层
pcap[3].haslayer(Raw) - 判断是否含有payload

数据包结构和构造

数据包的构造,scapy里面数据可以按照协议层来分别构造,基本上按下面的层次关系来的:
Ether层/IP网络层/TCP-UDP传输层/应用层数据
例如: pkt=Ether()/IP()/TCP()/'hello world!' 便可以构造一个最原始的数据包,通过pkt.show()便可以查看scapy为我们构造出来的包数据。

每一层的参数都可以自由定义,下面简单梳理一些常用层的设置字段:

Ether以太层:

dst - 目的MAC地址
src - 源MAC地址
type - 类型IPv4是0x0800
例如:
Ether(dst='00:00:00:00:00:00',src='00:00:00:00:00:00',type=0x800)

IP层:

version - 版本,4表示IPv4,6表示IPv6
proto - 协议,TCP,UDP
chksum - 校验和
src - 源地址
dst - 目的地址
例如:
IP(version=4,ihl=5, tos=84, id=19450, flags=0, ttl=64, proto=1,chksum=0xf090, src='192.168.1.6',dst='192.168.1.6')

TCP层:

sport - 源端口
dport - 目标端口
seq - sequence值
ack - acknowledgement值
flags - S,A,SA,F,P
window - 窗口大小
chksum - 校验和
例如:
TCP(sport=45486,dport=8888,seq=31,ack=31,window=342,flags='PA')

UDP层:

sport:源端口
dport:目的端口
len:包长度
chksum:校验和
例如:
UDP(sport=1971,dport=9527,len=10,chksum=0)

示例1:构造一个loopback地址的DNS查询消息:

pkt=Ether(dst='00:00:00:00:00:00',src='00:00:00:00:00:00',type=0x800)/IP(version=4,ihl=5, tos=107, id=23666, flags=0, ttl=64, proto=17,chksum=0xdf7a, src='127.0.0.1',dst='127.0.0.1')/UDP(sport=53,dport=47679,len=55,chksum=0xff6a)/bytes.fromhex('9c170100000100000000000012636f6e6e65637469766974792d636865636b067562756e747503636f6d00001c0000')
sendp(pkt, iface='lo')

示例2:构造一个loopback地址的TCP-SYN消息:

pkt=Ether(dst='00:00:00:00:00:00',src='00:00:00:00:00:00',type=0x800)/IP(version=4,ihl=5,tos=60,id=0xd263, flags='DF',frag=0,ttl=64, proto='tcp',chksum=0x6a56, src='127.0.0.1',dst='127.0.0.1')/TCP(sport=41169,dport=9999,seq=3824436007,ack=0,dataofs=10,reserved=0,flags='S',window=65495,chksum=0xfe30,urgptr=0,options=[('MSS', 65495), ('SAckOK', b''), ('Timestamp', (105920987, 0)), ('NOP', None), ('WScale', 7)])
sendp(pkt, iface='lo')

数据包的发送和接收

scapy提供的发送和接收数据功能有很多种方式,需要区分的是带p的一般都是layer2发送,不带p的都是layer3发送。例如:
send - 在层3发送数据
pkt=IP(version=4,ihl=6,src='192.168.1.6',dst='192.168.1.6',proto='tcp')/TCP(sport=45486,dport=8888,seq=0,ack=0,flags='S')/b'aaaaaaaaaa'
send(pkt)

sendp - 在层2发送数据
pkt=Ether(dst='e8:4e:06:33:48:c8',src='00:00:00:00:00:00',type=0x800)/IP(version=4,ihl=6,src='192.168.1.6',dst='192.168.1.6',proto='tcp')/TCP(sport=45486,dport=8888,seq=0,ack=0,flags='S')/b'aaaaaaaaaa'
sendp(pkt)

也可以不加任何参数,直接发送已经捕获的数据包
sendp(rdpcap("/home/jma/Desktop/scapy/scapy_test.pcap"))

在python3上测试这种方法达不到真正的replay效果,只是在wireshark中捕获的报文看起来像是回放了一次,但是以这种方式去和真实的系统进行交互是不行的(因为没有正真的握手嘛)。

其他发送接口的可选参数:
iface - 指定网卡,例如iface='eth1'
loop - 开启循环发送,例如loop=1
inter - 设置间隔时间,

例如:inter=0.2 指定每0.2秒发送一次
sendp("I'm travelling on Ethernet", iface="lo", loop=1, inter=0.2)

其他的发送接口,可以通过lsc()查看

Fuzz,scapy中还包含一个fuzz功能

fuzz - 通过随机数值替换某一层的内容将其fuzz,可以fuzz协议值,也可以fuzz数据
例如:
fuzz(TCP()),fuzz(TCP()/Raw()),fuzz(UDP()),fuzz(UDP()/NTP())
pkt=Ether(dst='00:00:00:00:00:00',src='00:00:00:00:00:00',type=0x800)/IP(version=4,ihl=5, tos=107, id=23666, flags=0, ttl=64, proto=17,chksum=0xdf7a, src='127.0.0.1',dst='127.0.0.1')/UDP(sport=53,dport=47679,len=55,chksum=0xff6a)/fuzz(DNS())

 

 

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据