专栏首页一名白帽的成长史【Python】利用Scapy进行三层主机探测

【Python】利用Scapy进行三层主机探测

Hello,各位小伙伴周一好~

今天依然是喜闻乐见的python模块...

今天就来看看scapy怎么实现三层探测吧~

Here we go~

Part.1

三层探测原理

ICMP报文

三层扫描我们需要用到ICMP的两类报文:

echo request、echo reply。

其实就是我们使用的ping命令,请求机向目标主机发送echo request报文,如果收到了echo reply应答就认为对方在线。

优点:相比ARP,可进行跨网段扫描

缺点:可能被防火墙过滤,结果可能不准确

Fping命令

既然说到ICMP,那再额外补充一下,除了ping以外,还有个fping命令。

在linux中,使用ping命令访问目标主机,会不停的发送echo request报文:

即使目标主机不可以访问,也会不断发送echo request请求:

这里其实还有一个命令fping,使用fping访问主机,如果主机应答了,就马上停止发包:

如果主机不应答,也只会发送4次请求包就自动停止:

fping -g 还可以扫描一整个网段:

把错误信息去掉:

Part.2

脚本编写

需求说明

通过python编写一个三层主机探测脚本,使用ping命令进行扫描。

脚本需要从外部传入参数:

  • 通过-f参数,可以读取本地文件中的IP地址进行扫描。
  • 通过-i参数,输入一个IP地址,探测该IP所在网段的存活主机。

今天的脚本依然是使用scapy模块,忘记的小伙伴先去补补课哦:

【Python】使用scapy模块编写ARP欺骗脚本

模块引入

首先引入我们需要的模块,如下:

具体调用模块的什么功能,我们在后面用到的时候说明。

3、sweep()函数

首先我们来定义一个sweep()函数,来向指定IP地址发送echo request请求。

接收的参数ip表示我们需要探测的主机地址。

使用scapy定义一个icmp echo request报文:

  • IP报头目的地址设置为接收的ip地址
  • IP报头源地址不设置,默认为Kali的地址
  • ICMP报头不设置参数,默认type为echo-request
  • 此处根据三层发包,不需要设置二层帧头,系统会自动添加默认二层头部

使用sr1进行三层发包,仅接收1个应答报文,超时时间为1s,且不显示详细信息。

将收包结果赋值给result,通过if判断result是否有值,进而判断是否收到了响应。

如果收到响应,就判断主机存活,打印“IP online”

time.sleep(0.1)用于进行短暂停顿,避免多线程导致输出乱序。

最后再添加try/except异常处理功能,说明如下:

  • 程序运行过程中难免出现错误,当Python检测到错误时,解释器就无法继续执行下去,于是抛出相应的信息,这些统称为异常信息。
  • 使用try/except语句: 程序执行时,如果try子句中没有异常发生,那么except子句在try语句执行之后被忽略; 如果try子句中有异常发生,那么该部分的其他语句将被忽略,直接跳到except部分,执行其后面的子句。

主函数main()

接下来我们来定义主函数main(),如下:

(1)首先通过optparse模块,通过选项向脚本传递所需的参数:

  • 添加-f 选项,让脚本扫描指定文件内的IP地址。
  • 添加-i 选项,让脚本扫描指定的IP地址所在的整个网段。

该部分代码如下:

说明如下:

  • 第一行为帮助信息,%prog表示当前脚本文件的名字。
  • 第二行将类实例化成对象,配置usage=usage,使用-h就会显示help信息。
  • 第三行,利用add_option()方法添加选项。 -f和--file分别表示长短选项名,长选项可以省略。 type指定了参数类型,默认为string,dest指定将参数赋值给哪个变量,help为帮助信息。
  • 第四行同理,利用add_option()方法添加选项-i和--ip。
  • 第五行,利用parse_args()方法来获取定义的选项和参数,可以视作一种固定用法。 parseargs()方法返回两个值,其中options对象保存了所传递进来的参数值。
  • 第六、七行,通过options.filename和options.address的方式调用参数值。

(2)判断用户是否传参

判断filename和address参数是否同时为空:

如果同时为空则打印报错信息,报错后通过sys.exit()函数直接退出程序。

(3)通过 -f 文件名传参

代码如下:

  • 首先通过if判断filename变量是否为空。
  • 如果不为空则通过os.path.exists()判断文件是否真实存在
  • 文件不存在则报错,并通过sys.exit()直接退出程序。
  • 若文件存在,则通过open函数,以只读方法打开该文件。
  • 通过for-in语句读取每一行的IP地址,并通过多线程传入sweep()函数进行判断。

(4)通过 -i IP地址传参

代码如下:

  • 首先通过if判断address变量是否为空。
  • 如果不为空则先读取IP地址的前缀。
  • 通过for-in语句,在前缀后面拼接上数字1-254,组成IP地址。
  • 最后将IP地址通过多线程传入sweep()函数完成判断。

Part.3

脚本测试

脚本测试

接下来我们对脚本进行测试。

(1)查看帮助信息

输入 -h 查看帮助信息:

(2)不传入任何参数

当不传参时,脚本提示报错并退出:

(3)通过 -i 传入IP地址

成功探测到存活主机:

(4)通过 -f 传入文件

创建ip.txt文件如下:

通过 -f 传入ip.txt,成功探测存活主机:

Part.4

结语

好啦,到此我们的代码就全部完成了。

涉及了大量python基础知识,没看明白的小伙伴,可以针对不明白的函数在百度查询获取解答哦。

当然也可以在公众号给我留言,我看到会直接回复的,最后附上完整代码:

Peace!

本文分享自微信公众号 - 一名白帽的成长史(monster-liuzhi)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 在nuxt.js项目中对axios进行封装

    不管是在服务端还是客户端获取数据都可以使用axios。在实际的开发过程中,每次请求中往往要携带一些自定义的参数或进行一些统一的处理,所以对axios进行封装是必...

    用户3258338
  • C# HTTP系列3 HttpWebRequest.ContentType属性

    获取或设置请求的 Content-type HTTP 标头的值。默认值为null。

    张传宁老师
  • C# HTTP系列2 HttpWebReponse类

    System.Net.HttpWebReponse 类提供 WebResponse 类的特定于HTTP的实现。

    张传宁老师
  • .NET软件开发与常用工具清单

    Visual Studio是目前最流行的Windows平台应用程序的集成开发环境。最新版本为 Visual Studio 2014 版本,基于.NET Fra...

    张传宁老师
  • 二进制安全学习规划指南

    HACK学习
  • C# HTTP系列1 HttpWebRequest类

      .NET Framework 中 System.Net 命名空间下提供了 HttpWebRequest 和 HttpWebResponse 2个类,他们是用...

    张传宁老师
  • 如何下载优酷 m3u8 格式的视频文件?

    平常最熟悉的视频文件格式就是mp4了,比如这个微博视频就是mp4格式https://weibo.com/tv/v/I6NlI3XNO?fid=1034:4416...

    苏生不惑
  • python测试开发django-63.基于函数的视图(@api_view())

    上一篇讲了基于类的视图,在REST framework中,你也可以使用常规的基于函数的视图。它提供了一组简单的装饰器,用来包装你的视图函数, 以确保视图函数会收...

    上海-悠悠
  • C# HTTP系列5 HttpWebResponse.StatusCode属性

    HttpWebResponse.StatusCode 属性获取响应的状态。对应 HttpStatusCode 枚举值之一。

    张传宁老师
  • 手把手带你开发一款 IIS 模块后门

    记得之前看一篇 APT 组织的报告时偶然间看到过 IIS 模块后门然后在网上找了找了资料,想自己开发一款然后开发到一半因为一些事情就停止了很久,这次清理项目文件...

    信安之路

扫码关注云+社区

领取腾讯云代金券