「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 脚本中使用此技术,可以按顺序执行此任务,来扫描多个系统或整个网络范围。


分享到:


相關文章: