轉載請注明:@小五義:http://www.cnblogs/xiaowuyi
一、包
包(Packet)是TCP/IP協議通信傳輸中的數據單位,一般也稱“數據包”。其主要由“目的IP地址”、“源IP地址”、“凈載數據”等部分構成,包括包頭和包體,包頭是固定長度,包體的長度不定,各字段長度固定,雙方的請求數據包和應答數據包的包頭結構是一致的,不同的是包體的定義。 數據包的結構與我們平常寫信非常類似,目的IP地址是說明這個數據包是要發給誰的,相當於收信人地址;源IP地址是說明這個數據包是發自哪里的,相當於發信人地址;而凈載數據相當於信件的內容。包沿着不同的路徑在一個或多個網絡中傳輸,並且在目的地重新組合。
二、常見的幾個關鍵字
ICMP:Internet Control Message Protocol(Internet控制報文協議)的縮寫。它是TCP/IP協議族的一個子協議,用於在IP主機、路由器之間傳遞控制消息。控制消息是指網絡通不通、主機是否可達、路由是否可用等網絡本身的消息。這些控制消息雖然並不傳輸用戶數據,但是對於用戶數據的傳遞起着重要的作用。
DST:目的地址
SRC:源地址
TTL:(Time To Live ) 生存時間,指定數據包被路由器丟棄之前允許通過的網段數量。TTL是IP協議包中的一個值,它告訴網絡,數據包在網絡中的時間是否太長而應被丟棄。有很多原因使包在一定時間內不能被傳遞到目的地。解決方法就是在一段時間后丟棄這個包,然后給發送者一個報文,由發送者決定是否要重發。TTL的初值通常是系統缺省值,是包頭中的8位的域。TTL的最初設想是確定一個時間范圍,超過此時間就把包丟棄。由於每個路由器都至少要把TTL域減一,TTL通常表示包在被丟棄前最多能經過的路由器個數。當記數到0時,路由器決定丟棄該包,並發送一個ICMP報文給最初的發送者。
三、scapy中常用的幾個命令
1、ls():作用也是list show,可以顯示所有支持的數據包對象。ls()可以不帶參數,也可以帶參數,參數可是任何一個具體的包。下面列出了一部分結果:
>>> from scapy.all import * WARNING: No route found for IPv6 destination :: (no default route?) >>> ls() ARP : ARP ASN1_Packet : None BOOTP : BOOTP CookedLinux : cooked linux DHCP : DHCP options DHCP6 : DHCPv6 Generic Message) DHCP6OptAuth : DHCP6 Option - Authentication DHCP6OptBCMCSDomains : DHCP6 Option - BCMCS Domain Name List DHCP6OptBCMCSServers : DHCP6 Option - BCMCS Addresses List DHCP6OptClientFQDN : DHCP6 Option - Client FQDN DHCP6OptClientId : DHCP6 Client Identifier Option DHCP6OptDNSDomains : DHCP6 Option - Domain Search List option DHCP6OptDNSServers : DHCP6 Option - DNS Recursive Name Server DHCP6OptElapsedTime : DHCP6 Elapsed Time Option DHCP6OptGeoConf :
列出TCP的所有對象:
>>> from scapy.all import *
WARNING: No route found for IPv6 destination :: (no default route?)
>>> ls(TCP)
sport : ShortEnumField = (20)
dport : ShortEnumField = (80)
seq : IntField = (0)
ack : IntField = (0)
dataofs : BitField = (None)
reserved : BitField = (0)
flags : FlagsField = (2)
window : ShortField = (8192)
chksum : XShortField = (None)
urgptr : ShortField = (0)
options : TCPOptionsField = ({})
列出任意包的情況如:
>>> a=IP(ttl=5)
>>> a.src
'127.0.0.1'
>>> a
<IP ttl=5 |>
>>> a.dst
'127.0.0.1'
>>> a.dst="192.168.0.1"
>>> a
<IP ttl=5 dst=192.168.0.1 |>
>>> ls(a)
version : BitField = 4 (4)
ihl : BitField = None (None)
tos : XByteField = 0 (0)
len : ShortField = None (None)
id : ShortField = 1 (1)
flags : FlagsField = 0 (0)
frag : BitField = 0 (0)
ttl : ByteField = 5 (64)
proto : ByteEnumField = 0 (0)
chksum : XShortField = None (None)
src : Emph = '27.214.7.85' (None)
dst : Emph = '192.168.0.1' ('127.0.0.1')
options : PacketListField = [] ([])
>>>
2、lsc()列出所有函數。如:
>>> lsc() arpcachepoison : Poison target's cache with (your MAC,victim's IP) couple arping : Send ARP who-has requests to determine which hosts are up bind_layers : Bind 2 layers on some specific fields' values 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 : defrag(plist) -> plist defragmented as much as possible 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" etherleak : Exploit Etherleak flaw fragment : Fragment a big IP datagram fuzz : Transform a layer into a fuzzy layer by replacing some default values by random objects getmacbyip : Return MAC address corresponding to a given IP address hexdiff : Show differences between 2 binary strings hexdump : -- hexedit : -- is_promisc : Try to guess if target is in Promisc mode. The target is provided by its ip. linehexdump : -- ls : List available layers, or infos on a given layer promiscping : Send ARP who-has requests to determine which hosts are in promiscuous mode rdpcap : Read a pcap file and return a packet list send : Send packets at layer 3 sendp : Send packets at layer 2 sendpfast : Send packets at layer 2 using tcpreplay for performance sniff : Sniff packets split_layers : Split 2 layers previously bound sr : Send and receive packets at layer 3 sr1 : Send packets at layer 3 and return only the first answer srbt : send and receive using a bluetooth socket srbt1 : send and receive 1 packet using a bluetooth socket srflood : Flood and receive packets at layer 3 srloop : Send a packet at layer 3 in loop and print the answer each time srp : Send and receive packets at layer 2 srp1 : Send and receive packets at layer 2 and return only the first answer srpflood : Flood and receive packets at layer 2 srploop : Send a packet at layer 2 in loop and print the answer each time traceroute : Instant TCP traceroute tshark : Sniff packets and print them calling pkt.show(), a bit like text wireshark wireshark : Run wireshark on a list of packets wrpcap : Write a list of packets to a pcap file
3、hide_defaults()方法,用來刪除一些用戶提供的那些和default value相同的項目
>>> a=IP()/TCP() >>> b=IP(str(a)) >>> b <IP version=4L ihl=5L tos=0x0 len=40 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x7ccd src=127.0.0.1 dst=127.0.0.1 options=[] |<TCP sport=ftp_data dport=http seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x917c urgptr=0 |>> >>> b.hide_defaults() >>> b <IP ihl=5L len=40 frag=0 proto=tcp chksum=0x7ccd src=127.0.0.1 |<TCP dataofs=5L chksum=0x917c |>>
4、display():display()方法可以簡單查看當前packet的各個參數的取值情況,例子見下。
5、sprintf:輸出某一層某個參數的取值,如果不存在就輸出??,具體的format是:%[[mt][r],][layer[:nb].]field%,參數的具體信息請參看《Security Power Tools》146頁或者http://wikicode.net。例:
>>> a=IP()/TCP()
>>> b=IP(str(a))
>>> b
<IP version=4L ihl=5L tos=0x0 len=40 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x7ccd src=127.0.0.1 dst=127.0.0.1 options=[] |<TCP sport=ftp_data dport=http seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x917c urgptr=0 |>>
>>> b.hide_defaults()
>>> b
<IP ihl=5L len=40 frag=0 proto=tcp chksum=0x7ccd src=127.0.0.1 |<TCP dataofs=5L chksum=0x917c |>>
>>> a.sprintf("%IP.gabuzomeu%")
'??'
四、創建包
scapy的包創建是按照網絡接口層,互聯網層,傳輸層,應用層四層參考模型來完成,各個層都有各自的創建函數,比如IP(),TCP(),UDP()等等,不同層之間通過“/”來連接。例如 ,接前面a的例子:
例1
>>> a=IP(ttl=5) >>> a.src '127.0.0.1' >>> a <IP ttl=5 |> >>> a.dst '127.0.0.1' >>> a.dst="192.168.0.1" >>> a <IP ttl=5 dst=192.168.0.1 |> >>> packet1=a >>> packet1 <IP ttl=5 dst=192.168.0.1 |> 例2
>>> packet2=IP(dst="192.168.0.1")/TCP(dport=80) 例3
>>> packet3=IP(dst="www.baidu.com")/ICMP() >>> packet3 <IP frag=0 proto=icmp dst=Net('www.baidu.com') |<ICMP |>> >>> ls(packet3) version : BitField = 4 (4) ihl : BitField = None (None) tos : XByteField = 0 (0) len : ShortField = None (None) id : ShortField = 1 (1) flags : FlagsField = 0 (0) frag : BitField = 0 (0) ttl : ByteField = 64 (64) proto : ByteEnumField = 1 (0) chksum : XShortField = None (None) src : Emph = '27.214.7.85' (None) dst : Emph = Net('www.baidu.com') ('127.0.0.1') options : PacketListField = [] ([]) -- type : ByteEnumField = 8 (8) code : MultiEnumField = 0 (0) chksum : XShortField = None (None) id : ConditionalField = 0 (0) seq : ConditionalField = 0 (0) ts_ori : ConditionalField = 4842323 (4842323) ts_rx : ConditionalField = 4842323 (4842323) ts_tx : ConditionalField = 4842323 (4842323) gw : ConditionalField = '0.0.0.0' ('0.0.0.0') ptr : ConditionalField = 0 (0) reserved : ConditionalField = 0 (0) addr_mask : ConditionalField = '0.0.0.0' ('0.0.0.0') unused : ConditionalField = 0 (0) 例4
>>> target="www.baidu.com/30" >>> ip=IP(dst=target) >>> ip <IP dst=Net('www.baidu.com/30') |> >>> ls(ip) version : BitField = 4 (4) ihl : BitField = None (None) tos : XByteField = 0 (0) len : ShortField = None (None) id : ShortField = 1 (1) flags : FlagsField = 0 (0) frag : BitField = 0 (0) ttl : ByteField = 64 (64) proto : ByteEnumField = 0 (0) chksum : XShortField = None (None) src : Emph = '27.214.7.85' (None) dst : Emph = Net('www.baidu.com/30') ('127.0.0.1') options : PacketListField = [] ([])
>>> IP().display()
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = ip
chksum = None
src = 127.0.0.1
dst = 127.0.0.1
\options \
>>> TCP().display()
###[ TCP ]###
sport = ftp_data
dport = http
seq = 0
ack = 0
dataofs = None
reserved = 0
flags = S
window = 8192
chksum = None
urgptr = 0
options = {}
這里的display()方法可以簡單查看當前packet的各個參數的取值情況.
五、包的結構
在Scapy中,scapy為各個層都寫了類,使用時,只需要將其實例化,調用類的方法或者改變類的參數取值。如IP()沒有傳給它參數,那么它的參數就是默認的,如果傳了就覆蓋了默認值:
>>> a=IP() >>> a.display() ###[ IP ]### version = 4 ihl = None tos = 0x0 len = None id = 1 flags = frag = 0 ttl = 64 proto = ip chksum = None src = 127.0.0.1 dst = 127.0.0.1 \options \ >>> a=IP(dst="192.168.0.1") >>> a.display() ###[ IP ]### version = 4 ihl = None tos = 0x0 len = None id = 1 flags = frag = 0 ttl = 64 proto = ip chksum = None src = 27.214.7.** //(本機IP) dst = 192.168.0.1 \options \
注意比較這兩次display()的不同,第一次是默認值,第二次傳入了“192.168.0.1”。
"/"用來連接各層,如IP()/TCP()。如:
>>> IP() <IP |> >>> IP()/TCP() <IP frag=0 proto=tcp |<TCP |>> >>> Ether()/IP()/TCP() <Ether type=0x800 |<IP frag=0 proto=tcp |<TCP |>>> >>> IP()/TCP()/"GET / HTTP/1.0\r\n\r\n" <IP frag=0 proto=tcp |<TCP |<Raw load='GET / HTTP/1.0\r\n\r\n' |>>> >>> Ether()/IP()/IP()/UDP() <Ether type=0x800 |<IP frag=0 proto=ipencap |<IP frag=0 proto=udp |<UDP |>>>> >>> IP(proto=55,ttl=10)/TCP() <IP frag=0 ttl=10 proto=55 |<TCP |>> 具體的參數傳遞過程,在scapy文檔中提供了圖表,如下:

