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,只不過工作在二層。