「Kali Linux網絡掃描祕籍系列」使用 Scapy 跨網段發現IP

「Kali Linux網絡掃描秘籍系列」使用 Scapy 跨網段發現IP

本秘籍簡介:

Scapy 是一種工具,允許用戶製作並向網絡中注入自定義數據包。 此工具可以用於構建 ICMP 協議請求,並將它們注入網絡來分析響應。 這個特定的秘籍演示瞭如何使用 Scapy 在遠程主機上執行第3層發現。

準備

使用 Scapy 執行第三層發現不需要實驗環境,因為 Internet 上的許多系統都將回復ICMP 回顯請求。 但是,強烈建議你只在您自己的實驗環境中執行任何類型的網絡掃描,除非你完全熟悉您受到任何管理機構施加的法律法規。 如果你希望在實驗環境中執行此技術,你需要至少有一個響應 ICMP 請求的系統。

操作步驟

為了使用 Scapy 發送 ICMP 回顯請求,我們需要開始堆疊層級來發送請求。 堆疊數據包時的一個好的經驗法則是,通過 OSI 按照的各層進行處理。 你可以通過使用斜槓分隔每個層級來堆疊多個層級。 為了生成 ICMP 回顯請求,IP 層需要與 ICMP請求堆疊。 為了開始,請使用 scapy 命令打開 Scapy 交互式控制檯,然後將 IP 對象賦給變量:

root@kali:~# scapy

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

WARNING: No route found for IPv6 destination :: (no default route?)

WARNING: IPython not available. Using standard Python shell instead.

AutoCompletion, History are disabled.

aSPY//YASa

apyyyyCY//////////YCa |

sY//////YSpcs scpCY//Pp | Welcome to Scapy

ayp ayyyyyyySCP//Pp syY//C | Version 2.4.0

AYAsAYYYYYYYY///Ps cY//S |

pCCCCY//p cSSps y//Y | [url=https://github.com/secdev/scapy]https://github.com/secdev/scapy[/url]

SPPPP///a pP///AC//Y |

A//A cyP////C | Have fun!

p///Ac sC///a |

P////YCpc A//A | We are in France, we say Skappee.

scccccp///pSP///p p//Y | OK? Merci.

sY/////////y caa S//P | -- Sebastien Chabal

cayCyayP//Ya pY/Ya |

sY/PsY////YCc aC//Yp

sc sccaCY//PCypaapyCP//YSs

spCPY//////YPSps

ccaacs

>>> ip=IP()

>>> ip.display()

###[ IP ]###

version= 4

ihl= None

tos= 0x0

len= None

id= 1

flags=

frag= 0

ttl= 64

proto= hopopt

chksum= None

class="lazy" src="//p2.ttnews.xyz/loading.gif" data-original= 127.0.0.1

dst= 127.0.0.1

\options\

將新值賦給目標地址屬性後,可以通過再次調用 display() 函數來驗證更改。 請注意,當目標 IP 地址值更改為任何其他值時,源地址也會從回送地址自動更新為與默認接口關聯的 IP 地址。 現在 IP 對象的屬性已經適當修改了,我們將需要在我們的封包棧中創建第二層。 要添加到棧的下一個層是 ICMP 層,我們將其賦給單獨的變量:

>>> ping=ICMP()

>>> ping.display()

###[ ICMP ]###

type= echo-request

code= 0

chksum= None

id= 0x0

seq= 0x0

在所提供的示例中,ICMP 對象使用 ping 變量名稱初始化。 然後可以調用 display() 函數來顯示 ICMP 屬性的默認配置。 為了執行 ICMP 回顯請求,默認配置就足夠了。 現在兩個層都已正確配置,它們可以堆疊來準備發送。 在Scapy 中,可以通過使用斜槓分隔每個層級來堆疊層級。 看看下面的命令集:

>>> ip.dst="172.16.155.1"

>>> ping_request=(ip/ping)

>>> ping_request.display()

###[ IP ]###

version= 4

ihl= None

tos= 0x0

len= None

id= 1

flags=

frag= 0

ttl= 64

proto= icmp

chksum= None

class="lazy" data-original= 172.16.155.150

dst= 172.16.155.1

\options\

###[ ICMP ]###

type= echo-request

code= 0

chksum= None

id= 0x0

seq= 0x0

一旦堆疊層級被賦給一個變量, display() 函數可以顯示整個棧。 以這種方式堆疊層的過程通常被稱為數據報封裝。 現在已經堆疊了層級,並已經準備好發送請求。 這可以使用 Scapy 中的 sr1() 函數來完成:

>>> ping_reply=sr1(ping_request)

Begin emission:

...........................*Finished sending 1 packets.

Received 28 packets, got 1 answers, remaining 0 packets

>>> ping_reply.display()

###[ IP ]###

version= 4

ihl= 5

tos= 0x0

len= 28

id= 47924

flags=

frag= 0

ttl= 64

proto= icmp

chksum= 0x30f4

class="lazy" data-original= 172.16.155.1

dst= 172.16.155.150

\options\

###[ ICMP ]###

type= echo-reply

code= 0

chksum= 0xffff

id= 0x0

seq= 0x0

###[ Padding ]###

load= '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'

在提供的示例中, sr1() 函數賦給了 ping_reply 變量。 這將執行該函數,然後將結果傳遞給此變量。 在接收到響應後,在 ping_reply 變量上調用 display() 函數來查看響應的內容。 請注意,此數據包是從我們發送初始請求的主機發送的,目標地址是 Kali 系統的 IP 地址。 另外,注意響應的 ICMP 類型是回應應答。 基於此示例,使用 Scapy 發送和接收 ICMP 的過程看起來很有用,但如果你嘗試對非響應的目標地址使用相同的步驟,你會很快注意到問題:

>>> ip.dst="172.16.155.100"

>>> ping_request=(ip/ping)

>>> ping_reply=sr1(ping_request)

Begin emission:

..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................WARNING: Mac address to reach destination not found. Using broadcast.

Finished sending 1 packets.

......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................^C

Received 4340 packets, got 0 answers, remaining 1 packets

示例輸出被截斷,但此輸出應該無限繼續,直到你使用 Ctrl + C 強制關閉。 不向函數提供超時值, sr1() 函數會繼續監聽,直到接收到響應。 如果主機不是活動的,或者如果 IP 地址沒有與任何主機關聯,則不會發送響應,並且該功能也不會退出。 為了在腳本中有效使用此函數,應定義超時值:

>>> ping_reply=sr1(ping_request,timeout=1)

Begin emission:

....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................WARNING: Mac address to reach destination not found. Using broadcast.

Finished sending 1 packets.

................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Received 2340 packets, got 0 answers, remaining 1 packets

>>>

通過提供超時值作為傳遞給 sr1() 函數的第二個參數,如果在指定的秒數內沒有收到響應,進程將退出。 在所提供的示例中, sr1() 函數用於將 ICMP 請求發送到無響應地址,因為未收到響應,會在 1 秒後退出。 到目前為止提供的示例中,我們將函數賦值給變量,來創建持久化和可操作的對象。 但是,這些函數不必複製給變量,也可以通過直接調用函數生成。

>>> answer=sr1(IP(dst="172.16.155.1")/ICMP(),timeout=1)

Begin emission:

..................................................................Finished sending 1 packets.

*

Received 67 packets, got 1 answers, remaining 0 packets

>>> answer.display()

###[ IP ]###

version= 4

ihl= 5

tos= 0x0

len= 28

id= 2141

flags=

frag= 0

ttl= 64

proto= icmp

chksum= 0xe3cb

class="lazy" data-original= 172.16.155.1

dst= 172.16.155.150

\options\

###[ ICMP ]###

type= echo-reply

code= 0

chksum= 0xffff

id= 0x0

seq= 0x0

###[ Padding ]###

load= '\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'

在這裡提供的示例中,之前使用四個單獨的命令完成的所有工作,實際上可以通過直接調用函數的單個命令來完成。 請注意,如果在超時值指定的時間範圍內,ICMP 請求沒有收到 IP 地址的回覆,調用對象會產生異常。 由於未收到響應,因此此示例中賦值為響應的應答變量不會初始化:

>>> answer=sr1(IP(dst="172.16.155.100")/ICMP(),timeout=1)

Begin emission:

....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................WARNING: Mac address to reach destination not found. Using broadcast.

...Finished sending 1 packets.

.....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Received 2348 packets, got 0 answers, remaining 1 packets

>>> answer.dislay()

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'NoneType' object has no attribute 'dislay'

有關這些不同響應的知識,可以用於生成在多個 IP 地址上按順序執行 ICMP 請求的腳本。 腳本會循環遍歷目標 IP 地址中最後一個八位字節的所有可能值,併為每個值發送一個 ICMP 請求。 當從每個 sr1() 函數返回時,將評估響應來確定是否接收到應答的響應:

#!/usr/bin/python3

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.all import *

if len(sys.argv)!=2:

print("Usage - ./ping.py [/24 network address]")

print("Exameple - ./pinger.py 172.16.155.1")

print("Exameple will perform an ICMP scan of the 172.16.155.0/24 range")

sys.exit()

address=str(sys.argv[1])

prefix=address.split(".")[0]+'.'+address.split(".")[1]+'.'+address.split(".")[2]+'.'

for addr in range(1,255):

answer=sr1(IP(dst=prefix+str(addr))/ICMP(),timeout=1,verbose=0)

if answer==None:

pass

else:

print(prefix+str(addr))

腳本的第一行標識了 Python 解釋器所在的位置,以便腳本可以在不傳遞到解釋器的情況下執行。 然後腳本導入所有 Scapy 函數,並定義 Scapy 日誌記錄級別,以消除腳本中不必要的輸出。 還導入了子過程庫,以便於從系統調用中提取信息。 第二個代碼塊是條件測試,用於評估是否向腳本提供了所需的參數。 如果在執行時未提供所需的參數,則腳本將輸出使用情況的說明。 該說明包括工具的用法,示例和所執行任務的解釋。

在這個代碼塊之後,有一個單獨的代碼行將所提供的參數賦值給 interface 變量。 下一個代碼塊使用 check_output() 子進程函數執行 ifconfig 系統調用,該調用也使用 grep 和 cut 從作為參數提供的本地接口提取 IP 地址。 然後將此輸出賦給 ip 變量。 然後使用 split 函數從 IP 地址字符串中提取 / 24 網絡前綴。 例如,如果 ip 變量包含 192.168.11.4 字符串,則值為 192.168.11 。 它將賦給 prefix 變量。

最後一個代碼塊是一個用於執行實際掃描的 for 循環。 for 循環遍歷介於 0 和254 之間的所有值,並且對於每次迭代,該值隨後附加到網絡前綴後面。 在早先提供的示例的中,將針對 192.168.11.0 和 192.168.11.254 之間的每個 IP 地址發送 ICMP 回顯請求。 然後對於每個回覆的活動主機,將相應的 IP 地址打印到屏幕上,以表明主機在 LAN 上活動。 一旦腳本被寫入本地目錄,你可以在終端中使用句號和斜槓,然後是可執行腳本的名稱來執行它。 看看以下用於執行腳本的命令:

root@kali:~# ./ping.py

Usage - ./ping.py [/24 network address]

Exameple - ./pinger.py 172.16.155.1

Exameple will perform an ICMP scan of the 172.16.155.0/24 range

root@kali:~# ./ping.py 172.16.155.0

172.16.155.1

172.16.155.2

如果在沒有提供任何參數的情況下執行腳本,則會將使用方法輸出到屏幕。 使用方法輸出表明,此腳本需要用於定義要掃描的 / 24 網絡的單個參數。 提供的示例使用 172.16.155.0 網絡地址來執行腳本。 該腳本然後輸出在 / 24 網絡範圍上的活動 IP 地址的列表。 此輸出也可以使用尖括號重定向到輸出文本文件,後跟輸出文件名。 一個例子如下:

root@kali:~# ./ping.py 172.16.155.0 > output.txt

root@kali:~# ls output.txt

output.txt

root@kali:~# cat output.txt

172.16.155.1

172.16.155.2

然後可以使用 ls 命令來驗證輸出文件是否已寫入文件系統,或者可以使用 cat 命令查看其內容。 也可以修改此腳本,來接受 IP 地址列表作為輸入。 為此,必須更改 for 循環來循環遍歷從指定的文本文件讀取的行。 一個例子如下:

#!/usr/bin/python3

import logging

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.all import *

if len(sys.argv)!=2:

print("Usage - ./ping.py [filename]")

print("Exameple - ./pinger.py iplist.txt")

print("Exameple will perform an ICMP scan of the IP addresses in iplist.txt")

sys.exit()

filename=str(sys.argv[1])

file1=open(filename,"r")

for addr in file1:

answer=sr1(IP(dst=addr.strip())/ICMP(),timeout=1,verbose=0)

if answer==None:

pass

else:

print(str(addr.strip()))

與之前的腳本唯一的主要區別是,它接受一個輸入文件名作為參數,然後循環遍歷此文件中列出的每個 IP 地址進行掃描。 與其他腳本類似,生成的輸出包括響應ICMP 回顯請求的系統的相關 IP 地址的簡單列表,其中包含 ICMP 回顯響應:

root@kali:~# ./ping2.py

Usage - ./ping.py [filename]

Exameple - ./pinger.py iplist.txt

Exameple will perform an ICMP scan of the IP addresses in iplist.txt

root@kali:~# ./ping2.py iplist.txt

172.16.155.1

172.16.155.2

此腳本的輸出可以以相同的方式重定向到輸出文件。 使用作為參數提供的輸入文件來執行腳本,然後使用尖括號重定向輸出,後跟輸出文本文件的名稱。 一個例子如下:

root@kali:~# ./ping2.py iplist.txt > output.txt

root@kali:~# ls output.txt

output.txt

root@kali:~# cat output.txt

172.16.155.1

172.16.155.2

工作原理

此處使用 Scapy 通過構造包括 IP 層和附加的 ICMP 請求的請求來執行 ICMP 第三層發現。 IP 層能夠將封包路由到本地網絡之外,並且 ICMP 請求用於從遠程系統請求響應。 在 Python 腳本中使用此技術,可以按順序執行此任務,來掃描多個系統或整個網絡範圍。


分享到:


相關文章: