一、安装scapy:
完整安装,会安装ipython和scapy等模块,命令如下:
pip install --pre scapy【complete】
python导入scapy使用下面语句:
from scapy.all import
一些工具、方法和用途:
summary() 显示一个关于每个数据包的摘要列表
nsummary() 同上,但规定了数据包数量
conversations() 显示一个会话图表
show() 显示首选表示(通常用nsummary())
filter() 返回一个lambda过滤后的数据包列表
hexdump() 返回所//代码效果参考:http://www.lyjsj.net.cn/wz/art_23222.html
有数据包的一个hexdumphexraw() 返回所以数据包Raw layer的hexdump
padding() 返回一个带填充的数据包的hexdump
nzpadding() 返回一个具有非零填充的数据包的hexdump
plot() 规划一个应用到数据包列表的lambda函数
make table() 根据lambda函数来显示表格
Route() 实例Route类,返回本机路由表
Route6() 实例化Route6类,返回本机v6路由表
arping 模拟arping函数
查看到目标ip的路由,返回出口网卡名、本机ip、网关ip的元组:
Help on method route in module //代码效果参考:http://www.lyjsj.net.cn/wx/art_23220.html
scapy.route:route(dst=None, verbose=2) method of scapy.route.Route instance
Returns the IPv4 routes to a host.
parameters:
- dst: the IPv4 of the destination host
returns: (iface, output_ip, gateway_ip)
- iface: the interface used to connect to the host
- output_ip: the outgoing IP that will be used
- gatewayip: the gateway IP that will be used
('\Device\NPF{C441126F-2ECC-4D58-A270-68EFE089BB09}',
'192.168.8.14',
'192.168.8.1')
对于Route类,还有增加、删除路由,以及改变网卡接口地址等功能
二、、功能:
1、读写报文:
rdpcap函数、wrpcap函数
使用wrpcap()函数可以把构造报文写到文件中,
//代码效果参考:http://www.lyjsj.net.cn/wx/art_23218.html<p
p]] pkt=Ether()/IP(dst='192.168.8.1')/TCP(dport=80)'Ether / IP / TCP 192.168.8.14:ftp_data > 192.168.8.1:http S'
使用rdpcap()函数可以把文件中的报文读到列表中,然后对每个报文可以按协议分层访问各层字段:
'192.168.8.14'
'192.168.8.1'
2、抓包:
(1) 抓包用sniff函数,函数定义:sniff(filter:str,count:int,iface:str,prn:func)更多更纤细的参数看help(sniff).
其中参数prn为回调函数,每抓到一个符合过滤器规则的包就以其为参数传入执行一次prn函数,通常用lambda写prn;
参数filter,和wireshark的capture filter规则一样。
Ether / IP / ICMP 192.168.8.14 > 192.168.8.1 echo-request 0 / Raw
Ether / IP / ICMP 192.168.8.1 > 192.168.8.14 echo-reply 0 / Raw
Ether / IP / ICMP 192.168.8.14 > 192.168.8.1 echo-request 0 / Raw
Ether / IP / ICMP 192.168.8.1 > 192.168.8.14 echo-reply 0 / Raw
Ether / IP / ICMP 192.168.8.14 > 192.168.8.1 echo-request 0 / Raw
'Ether / IP / ICMP 192.168.8.14 > 192.168.8.1 echo-request 0 / Raw'
'Ether / IP / ICMP 192.168.8.14 > 192.168.8.1 echo-request 0 / Raw'
(2)也可以离线抓包,就是从文件中读取报文,功能和rdpcap相同,不过对匹配的报文可以过滤,调用回调函数,控制更灵活:
sniff(offline = "hw.pcap");
(3)sprintf()方法可以控制输出信息,该方法是scapy自己定义的替换控制符,替换变量用%括起来,如下:
sniff(prn=lambda pkt:pkt.sprintf("{IP:%IP.src% -> %IP.dst%\n}{Raw:%Raw.load%\n}"))
3、构造报文:
(1)报文根据协议层次构造,使用”/”堆加层次,注意字母大小写,如:
'IP / TCP 127.0.0.1:ftp_data > 127.0.0.1:http S'
每个层次具有的协议字段可以通过ls命令查看如:
构造报文时可以根据自己的需要设置协议的某些字段,如:
ipPacket = IP(dst='8.8.8.8')/TCP(dport=53)
上面是构造单个报文,可以利用通配符、元组和列表等方式一次构造一系列报文,
如果用元组,则表示范围(包含边界值),如下:
【
......
Sent 6 packets.
【
如果用列表,则表示用列表中的每个元素构建,如下:
【
..
Sent 2 packets.
也可以混合使用,如:
【
对于ip地址访问,可以使用列表方式指定,也可以指定掩码方式构造一系列不同报文,这对于构造扫描报文很有用,如:
【
【
ip地址也可以使用域名,scapy会自动通过Net函数进行地址解析:
【
注意:Net函数不在接收通配符和范围操作符-,因此IP的dst和src不能再用dst=‘192.168.8.1-254’或dst=‘192.168.1.’进行表示了。
堆叠数据层,构建系列数据包:
【
(2)报文的查看:
针对报文,可以查看概要信息,分层字段信息,16进制偏移格式等,
summary(),show(),hexdump()
0000 45 00 00 28 00 01 00 00 40 06 E9 6F C0 A8 08 0E E..(....@..o....
0010 C0 A8 08 01 27 10 00 50 00 00 00 00 00 00 00 00 ....'..P........
0020 50 02 20 00 D7 22 00 00 P. .."..
(3)查看报文有指定的协议层使用haslayer函数,获取指定层使用getlayer函数,如下:
True
10000
4、发送和接收报文:
sendp,send,srp,sr,srp1,sr1,srloop等函数
数字1表示只发送1个报文,带有字母p表示发送构造了二层帧的报文,没有字母p的函数表示发送三层报文,有字母r表示发送报文后还会接收报文。
没有数字1表示可以发送1个或多个报文(报文列表)
.
Sent 1 packets.
..
Sent 2 packets.
<br]] send(pkt 10)
..........
Sent 10 packets.
发送tcp/udp报文:
报文构造中,很多地方都要用到随机数,scapy也定义了相应随机函数,如RandInt(),RandShort(), RandNum()和Fuzz()等用来生成随机数。
RandInt(),顾名思义,产生一个32位随机整数,通常用在tcp的seq或ack中:
3023505333
RandShort(),产生一个16位随机整数,范围1~65535,通常用在tcp/udp的sport或dport中。
53905
RandNum(),可以生成指定范围内的一个随机数
3709
pkt=IP(dst='192.168.8.1')/TCP(sport=RandNum(30000,30010),dport=80,flags='S')
fuzz(),通常情况下,如果你构建tcp层没有指定sport或dport时,发包时会自动使用知名端口如20,80。这可能并不是你想要的。
而fuzz()函数能够在忘记写sport或dport情况下,自动帮你随机生成sport或dport
如下:
循环发送报文:
srloop(pkts, args, **kargs)
Send a packet at layer 3 in loop and print the answer each time
srloop(pkts, 【prn】, 【inter】, 【count】, ...) --> None
srloop(IP(dst="192.168.8.1")/TCP(),count=2,inter=0.5)
发送dns查询报文,注意里面的RR等构造需要借助DNSQR等方法:
Begin emission:
Finished sending 1 packets.
...
Received 4 packets, got 1 answers, remaining 0 packets
###【 DNS Question Record 】###
qname = ''
qtype = A
qclass = IN
注意:对于sr之类的同时收发报文的函数,返回的一个2元组,结构类似为 ( ((s,r),(s,r),...),(p1,p2,...) ),其第一个元素是由每个发送报文和响应报文一对一构成元组的元组,第2个报文为剩下的发送报文(没有收到响应报文)构成的元组。因此,获取收到的报文通常由ans,unans=sr();s,r=ans方式进行解包获取到列表或进行遍历。