scapy像一把瑞士军刀一样,可以用过网络分析的多种场景,主要用于网络报文分析、捕获及自定义协议报文等。
我们可以通过命令行或是python脚本两种方式来使用scapy。
scapy的安装知道参考:https://scapy.readthedocs.io/en/latest/
1. scapy命令:
ls(): 列出scapy所支持的所有协议
>>> ls()
AH : AH
AKMSuite : AKM suite
ARP : ARP
ASN1P_INTEGER : None
ASN1P_OID : None
ASN1P_PRIVSEQ : None
ASN1_Packet : None
ATT_Error_Response : Error Response
ATT_Exchange_MTU_Request : Exchange MTU Request
ATT_Exchange_MTU_Response : Exchange MTU Response
ATT_Execute_Write_Request : Execute Write Request
ATT_Execute_Write_Response : Execute Write Response
ATT_Find_By_Type_Value_Request : Find By Type Value Request
ATT_Find_By_Type_Value_Response : Find By Type Value Response
lsc(): 列出scapy所支持的命令和功能
>>> lsc()
IPID_count : Identify IP id values classes in a list of packets
arpcachepoison : Poison target's cache with (your MAC,victim's IP) couple
arping : Send ARP who-has requests to determine which hosts are up
arpleak : Exploit ARP leak flaws, like NetBSD-SA2017-002.
bind_layers : Bind 2 layers on some specific fields' values.
bridge_and_sniff : Forward traffic between interfaces if1 and if2, sniff and return
chexdump : Build a per byte hexadecimal representation
computeNIGroupAddr : Compute the NI group Address. Can take a FQDN as input parameter
corrupt_bits : Flip a given percentage or number of bits from a string
corrupt_bytes : Corrupt a given percentage or number of bytes from a string
defrag : defrag(plist) -> ([not fragmented], [defragmented],
defragment : defragment(plist) -> plist defragmented as much as possible
dhcp_request : Send a DHCP discover request and return the answer
dyndns_add : Send a DNS add message to a nameserver for "name" to have a new "rdata"
dyndns_del : Send a DNS delete message to a nameserver for "name"
conf:列出所有的配置选项
>>> conf
ASN1_default_codec = <ASN1Codec BER[1]>
AS_resolver = <scapy.as_resolvers.AS_resolver_multi object at 0x0000029009D3...
BTsocket = <BluetoothRFCommSocket: read/write packets on a connected L2CAP...
L2listen = <L2pcapListenSocket: read packets at layer 2 using libpcap>
L2socket = <L2pcapSocket: read/write packets at layer 2 using only libpcap>
L3socket = <L3pcapSocket: read/write packets at layer 3 using only libpcap>
L3socket6 = functools.partial(<L3pcapSocket: read/write packets at layer 3 ...
USBsocket = None
auto_crop_tables = True
auto_fragment = True
bufsize = 65536
cache_iflist = {'\\Device\\NPF_{A7D888CC-A2FE-40C2-8A59-C340127ACF3E}': ('Nd...
checkIPID = False
checkIPaddr = True
checkIPinIP = True
checkIPsrc = True
check_TCPerror_seqack = False
help():列出一个具体命令的帮助命令,例如,help(sniff)
>>> help(sniff)
Help on function sniff in module scapy.sendrecv:
sniff(*args, **kwargs)
Sniff packets and return a list of packets.
Args:
count: number of packets to capture. 0 means infinity.
store: whether to store sniffed packets or discard them
prn: function to apply to each packet. If something is returned, it
is displayed.
--Ex: prn = lambda x: x.summary()
session: a session = a flow decoder used to handle stream of packets.
e.g: IPSession (to defragment on-the-flow) or NetflowSession
filter: BPF filter to apply.
lfilter: Python function applied to each packet to determine if
further action may be done.
--Ex: lfilter = lambda x: x.haslayer(Padding)
offline: PCAP file (or list of PCAP files) to read packets from,
show():列出一个具体报文的详细信息,例如,Newpacket.show()
scapy支持大约300种网络协议。可以在ls()命令参数种指定查看具体的协议细节。例如:
ls(TCP):
>>> ls(TCP)
sport : ShortEnumField = (20)
dport : ShortEnumField = (80)
seq : IntField = (0)
ack : IntField = (0)
dataofs : BitField (4 bits) = (None)
reserved : BitField (3 bits) = (0)
flags : FlagsField (9 bits) = (<Flag 2 (S)>)
window : ShortField = (8192)
chksum : XShortField = (None)
urgptr : ShortField = (0)
options : TCPOptionsField = (b'')
scapy可以创建TCP/IP协议中的任何一层的包。下面这张图是scapy管理的层结构图:
scapy中通常一个层代表一种协议,一个网络报文包含多个层。网络报文必须是符合标准协议的。
默认的,IP层配置的目的IP是127.0.0.1,代表本地机器。如果我们想要发送到另一个IP,我们需要配置一些IP层。以下面例子说明:
创建一个IP和ICMP层报文:
>>> icmp = IP(dst='google.com')/ICMP()
创建其他层报文:
>>>tcp=IP(dst='google.com')/TCP(dport=80)
>>> packet = Ether()/IP(dst='google.com')/ICMP()/"ABCD"
我么可以通过show和show2功能来查看发送的报文,通过ls来查看报文结构:
>>> packet.show()
###[ Ethernet ]###
dst = ff:ff:ff:ff:ff:ff
src = 10:5b:ad:a2:20:bd
type = IPv4
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = icmp
chksum = None
src = 192.168.0.106
dst = Net('google.com')
\options \
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
###[ Raw ]###
load = 'ABCD'
>>> ls(packet)
dst : DestMACField = 'ff:ff:ff:ff:ff:ff' (None)
src : SourceMACField = '10:5b:ad:a2:20:bd' (None)
type : XShortEnumField = 2048 (36864)
--
version : BitField (4 bits) = 4 (4)
ihl : BitField (4 bits) = None (None)
tos : XByteField = 0 (0)
len : ShortField = None (None)
id : ShortField = 1 (1)
flags : FlagsField (3 bits) = <Flag 0 ()> (<Flag 0 ()>)
frag : BitField (13 bits) = 0 (0)
ttl : ByteField = 64 (64)
proto : ByteEnumField = 1 (0)
chksum : XShortField = None (None)
src : SourceIPField = '192.168.0.106' (None)
dst : DestIPField = Net('google.com') (None)
options : PacketListField = [] ([])
--
type : ByteEnumField = 8 (8)
code : MultiEnumField (Depends on type) = 0 (0)
chksum : XShortField = None (None)
id : XShortField (Cond) = 0 (0)
seq : XShortField (Cond) = 0 (0)
ts_ori : ICMPTimeStampField (Cond) = 7774012 (7774012)
ts_rx : ICMPTimeStampField (Cond) = 7774012 (7774012)
ts_tx : ICMPTimeStampField (Cond) = 7774012 (7774012)
gw : IPField (Cond) = '0.0.0.0' ('0.0.0.0')
ptr : ByteField (Cond) = 0 (0)
reserved : ByteField (Cond) = 0 (0)
length : ByteField (Cond) = 0 (0)
addr_mask : IPField (Cond) = '0.0.0.0' ('0.0.0.0')
nexthopmtu : ShortField (Cond) = 0 (0)
unused : ShortField (Cond) = 0 (0)
unused : IntField (Cond) = 0 (0)
--
load : StrField = b'ABCD' (b'')
scapy一层一层的来创建及分析报文。scapy中的报文是字典形式,因此每个包都是一个嵌套字典,每一层是上一层的一个孩子字典。通过summary()方法能够查看每个包的各个层的细节。
>>> packet[0].summary()
"Ether / IP / ICMP 192.168.0.106 > Net('google.com') echo-request 0 / Raw"
>>> packet[1].summary()
"IP / ICMP 192.168.0.106 > Net('google.com') echo-request 0 / Raw"
>>> packet[2].summary()
"ICMP 192.168.0.106 > Net('google.com') echo-request 0 / Raw"
>>> packet[3].summary()
'Raw'
2. scapy报文发送:
scapy中发送报文,有两种方法:
1)send(): 发送三层报文
2)sendp():发送二层报文
send命令的主要参数整理如下:
iface:发送报文的接口
Inter:两个报文之间的发送间隔(秒数)
loop:如果需要一直发送下去,设置该项为1. 否则设置0
packet:待发送的报文列表
verbose:允许我们改变log级别或者完成不使能log(设置为0)
例如:里面的packet报文,三层发送为send(packet),而对于二层发送可以指定以太网接口。二层接口和三层功能类似,不同的是报文不会经过路由,只在本地网络内通信。
上述两个接口都是只管发送报文,而不能接受应答。为了接收应答可以通过下面的接口来实现:
sr(...):发送并接收报文。接口等待直到所有发送的报文都收到响应。这个接口是工作在三层。如果没有期待的路由,报文是不 能被发送的。
sr1(...):这个功能与sr接口一样,除了这个接口指捕获第一个返回的响应报文,忽略其他的。
srp(...):功能与sr相似,不过这个接口工作在二层。它允许我们通过一个指定的网卡来发送,即使没有需要的路由,报文仍能被发送。
srp1(...):功能通sr1,只不过工作在二层。
srbt(...):通过蓝牙连接发送。
srloop(...):允许我们发送和接收报文N次。一个报文发送三次,我们将对应收到三个响应。这个接口允许我们指定当报文接收到或者无响应时的行为。
srploop(...):功能通srloop,只不过工作在二层。