python通过scapy编写arp扫描器
多网卡的情况下发送二层包需要配置网卡
三层包不需要配置接口
发包方法:
sr()
发送三层数据包,等待接收一个或者多个数据包的响应
sr1()
发送三层数据包,只会接收一个数据包的响应
srp()
发送二层数据包,然后一直等待回应
srp1()
发送二层发送数据包,只返回第一个答案
send()
只发送三层数据包,系统自动处理路由和两层信息
sendp()
只发送二层数据包
带p字母的都是发送二层数据包,必须要写以太网头部Ether(),而且如果是多接口一定要指定接口
不带p字母都是发送三层数据包,不需要填Ether头部,不需要指定接口
hwdst表示硬件MAC
verbose=False 表示关闭scapy自身的回显
通过Scapy看ARP结构:
hwdst表示硬件MAC
verbose=False 表示关闭scapy自身的回显
srp返回包结构分析:
Demo:
#!/usr/bin/python3 from scapy.all import *
localmac = '00:0c:29:b6:6b:7d'
localip = '192.168.64.128'
destip = '192.168.64.129'
intername ='eth0'
result_raw = srp(Ether(src=localmac,dst='FF:FF:FF:FF:FF:FF')/ARP(op=1,hwsrc=localmac,hwdst='00:00:00:00:00:00',psrc=localip,pdst=destip),iface = intername,timeout=1,verbose=False)
print("srp返回的类型",type(result_raw));
print("srp返回的信息:",result_raw);
print("=================================");
print("读取tuple中的第一个元素:",result_raw[0]);
print("类型:",type(result_raw[0]));
print("通过res方法将这个scapy内置的类转换成一个由tuple组成的list");
print("=================res======================")
print(result_raw[0].res);
print("=================end======================");
#res返回的是一个list 可是这个list中只有一个tuple阿 [0] [0]指的是什么数据阿 print("通过getlayer(ARP).fields函数将结果转换为字典");
print(result_raw[0].res[0][1].getlayer(ARP).fields)
输出结果:
srp返回的类型 <class 'tuple'>
srp返回的信息: (<Results: TCP:0 UDP:0 ICMP:0 Other:1>, <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)
=================================
读取tuple中的第一个元素: <Results: TCP:0 UDP:0 ICMP:0 Other:1>
类型: <class 'scapy.plist.SndRcvList'>
通过res方法将这个scapy内置的类转换成一个由tuple组成的list
=================res======================
[(<Ether dst=FF:FF:FF:FF:FF:FF src=00:0c:29:b6:6b:7d type=0x806 |<ARP op=who-has hwsrc=00:0c:29:b6:6b:7d psrc=192.168.64.128 hwdst=00:00:00:00:00:00 pdst=192.168.64.129 |>>
, <Ether dst=00:0c:29:b6:6b:7d src=00:0c:29:05:66:e5 type=0x806 |<ARP hwtype=0x1 ptype=0x800 hwlen=6 plen=4 op=is-at hwsrc=00:0c:29:05:66:e5 psrc=192.168.64.129 hwdst=00:0c:29:b6:6b:7d pdst=192.168.64.128 |<Padding load='\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' |>>>)]
=================end======================
通过getlayer(ARP).fields函数将结果转换为字典
{'hwtype': 1, 'ptype': 2048, 'hwlen': 6, 'plen': 4, 'op': 2, 'hwsrc': '00:0c:29:05:66:e5', 'psrc': '192.168.64.129', 'hwdst': '00:0c:29:b6:6b:7d', 'pdst': '192.168.64.128'}
根据赛题构造一个ARP包:
scapy:
arpPkt = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst='192.168.64.129',hwdst="ff:ff:ff:ff:ff:ff")
参数解释:
Ether()以太网包
dst=广播地址
ARP()ARP包
pdst=目标IP地址
hwdst=广播地址
演示scapy中ARP包结构:
发送ARP包:
res = srp1(arpPkt,timeout=1,verbose=False)
参数解释:
srp1 : Send and receive packets at layer 2 and return only the first answer
翻译来就是 在第2层发送和接收数据包,只返回第一个答案
timeout:设置超时时间
verbose:设置scapy的回显,False表示关闭 默认是开启的
查看srp1返回包的类型,这个比较关键
type(res);
<class 'scapy.layers.l2.Ether'>
可以发现这里返回包结构的数据类型是:scapy.layers.l2.Ether,之前使用srp接收数据包的类型是scapy.plist.SndRcvList
返回包的结构:
>>> res.show()
###[ Ethernet ]###
dst= 00:0c:29:b6:6b:7d
src= 00:0c:29:05:66:e5
type= 0x806
###[ ARP ]###
hwtype= 0x1
ptype= 0x800
hwlen= 6
plen= 4
op= is-at
hwsrc= 00:0c:29:05:66:e5
psrc= 192.168.64.129
hwdst= 00:0c:29:b6:6b:7d
pdst= 192.168.64.130
###[ Padding ]###
load= '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' >>>
参数解释:
这里有一点需要注意,这个包是目标机器接收我们发送的arp包后返回来的包,怎么说呢,就是我们目标机器发给我们的一个包
所以这里的参数 pdst是我们自身的ip,hwdst是我们自身的mac地址,不能看包结构名是dst就觉得是目标的
而psrc是目标ip的ip地址,hwsrc是目标机器的mac地址 这点比较重要 太多数据很容易萌萌
验证结果是正确的:
有了上面发送单个IP的基础来看下赛题:
#encoding=utf-8
from scapy.all import *
import sys def worker():
ip_list=[]
for ipFix in range(1,Flag1):
ip = Flag2 + str(ipFix)
arpPkt = Flag6(dst=Flag3)/ARP(pdst=ip, hwdst="ff:ff:ff:ff:ff:ff")
res = Flag5(arpPkt, timeout=1, verbose=False)
if res:
#print "IP: " + res.psrc + " MAC: " + res.hwsrc
ip_list.append(res.psrc)
return Flag4
if __name__=="__main__":
fp = open('/root/ip.txt','w')
ip_list = worker()
for ip in ip_list:
fp.write(ip+'\n')
print('over scan')
fp.close() #Flag1 = 255
#Flag2 = "192.168.48."
#Flag3 = "FF:FF:FF:FF:FF:FF" 广播地址
#Flag4 = ip_list 返回这个list
#Flag5 = srp1发包函数
#Flag6 = Ether 二层发包需要添加以太网头部
逻辑分析:
1.可写方式的打开一个文件/root/ip.txt
2.worker函数分析:
1.创建一个空的list
2.用for in range 1-255 循环
3.然后字符串拼接成192.168.1.x的ip
4.使用srp1构造arp数据包
5.发送arp数据包返回结果存在res中
6.如果res中成功接收到值,添加到list中
7.循环完1-255 返回存活主机的list
3.将worker返回的list写入1打开的文件 OK.
为了巩固自己对这个库的认识和py代码能力的掌握,我写了一个小玩具~
多线程arp扫描:
#!/usr/bin/python3
from scapy.all import *
import sys
import time
import threading
import optparse
#增加多线程 为了线程同步 加了3个全局变量
liveHost_list = [] #存活主机
live_count = 0; #存活主机数量
liveHostPrint_list = [] #打印的时候用
def printBanner():
banner = '''
_ ____ ____ ____
/ \ | _ \| _ \/ ___| ___ __ _ _ __ _ __ ___ _ __
/ _ \ | |_) | |_) \___ \ / __/ _` | '_ \| '_ \ / _ \ '__|
/ ___ \| _ <| __/ ___) | (_| (_| | | | | | | | __/ |
/_/ \_\_| \_\_| |____/ \___\__,_|_| |_|_| |_|\___|_|
v1.0 by r4bbit
'''
print(banner); def get_current_time():
year = time.strftime('%Y-%m-%d',time.localtime());
minute = time.strftime('%H-%M-%S',time.localtime());
return year+minute #返回时间 def arp_scan(ip):
global liveHostPrint_list
global live_count ;
global liveHost_list
start_time = time.time();
#构造arp数据包
time.sleep(0.001)
arpPkt = Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip,hwdst="ff:ff:ff:ff:ff:ff"); #发送arp数据包
resPkt = srp1(arpPkt,timeout=1,verbose=False);
#如果resPkt中返回的有包
if resPkt:
# print("[+] " + resPkt.psrc+" is Live"+" MAC:"+resPkt.hwsrc); #这里需要注意 因为是接受的包 所以需要打印出的是发送包的源ip和源mac
liveHost_list.append(resPkt.psrc); #存储到傻吊list中
print_tmp = "IP:"+resPkt.psrc+" MAC:"+resPkt.hwsrc
liveHostPrint_list.append(print_tmp);
live_count +=1; #else:
# print("[-] "+ip+" Not Alive"); def main():
printBanner();
global liveHost_list;
global live_count;
global liveHostPrint_list;
parser = optparse.OptionParser("usage -i <192.168.1> 主要是我菜不会用netaddr库");
parser.add_option('-i',dest='target_ips',type='string',help='ip no');
(options,arg) = parser.parse_args()
if(options.target_ips == None):
print(parser.usage);
exit(0);
else:
target_ips = options.target_ips
start_time = time.time();
for ip in range(1,255):
ip_str = target_ips+"."+str(ip);
scan_thread = threading.Thread(target=arp_scan,args=(ip_str,));
scan_thread.start();
end_time = time.time(); #创建文件夹
#如果文件夹不存在
#扫描完成打印结果 然后存储文件 for ip in liveHostPrint_list:
print(ip);
print("Scan Done. Live Host Num:%d Use Time:%f s " % (live_count,end_time-start_time));
if not os.path.exists(target_ips):
os.mkdir(target_ips)
log_name = get_current_time();
fp = open("./"+target_ips+"/"+log_name+".arp","w");
print("Scan Log in "+target_ips);
for i in liveHost_list:
fp.write(i+"\n"); fp.close(); if __name__ == '__main__':
main()
python通过scapy编写arp扫描器的更多相关文章
- python 使用scapy编写DNS Fuzzer
1. 描写叙述 使用scapy库,编写一个DNS Fuzzer工具,并測试.在这之前.先说明一下DNS协议请求包是封装在IP包中的UDP包(有些情况也可使用TCP)中.且UDP的端口为53. 进入sc ...
- Python网络编程——编写一个简单的回显客户端/服务器应用
今天将python中socket模块的基本API学习完后,照着书上的实例编写一个套接字服务器和客户端.采用python3.5版本,在注释中会标明python2和python3的不同之处. 1.代码 ( ...
- python实现FTP弱口令扫描器与简单端口扫描器
python实现FTP弱口令扫描器与简单端口扫描器 目录 FTP弱口令扫描器 简单端口扫描器 参考: https://blog.csdn.net/rebelqsp/article/details/22 ...
- 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试
相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(二) -- 在集群上运行与监控 用python + hadoop streami ...
- 用python + hadoop streaming 编写分布式程序(二) -- 在集群上运行与监控
写在前面 相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍,样例程序与本地调试 用python + hado ...
- 用python + hadoop streaming 编写分布式程序(三) -- 自定义功能
又是期末又是实训TA的事耽搁了好久……先把写好的放上博客吧 相关随笔: Hadoop-1.0.4集群搭建笔记 用python + hadoop streaming 编写分布式程序(一) -- 原理介绍 ...
- Linux 下Python调用C++编写的动态库
在工程中用到使用Python调用C++编写的动态库,结果报如下错误: OSError: ./extract_str.so: undefined symbol: _ZNSt8ios_base4InitD ...
- python 通过scapy获取网卡列表
python通过scapy 获取网卡列表如下: #coding:utf-8 from scapy.all import * #显示网卡信息 show_interfaces() 运行结果如下:
- python练习:编写一个程序,要求用户输入10个整数,然后输出其中最大的奇数,如果用户没有输入奇数,则输出一个消息进行说明。
python练习:编写一个程序,要求用户输入10个整数,然后输出其中最大的奇数,如果用户没有输入奇数,则输出一个消息进行说明. 重难点:通过input函数输入的行消息为字符串格式,必须转换为整型,否则 ...
随机推荐
- python os.path 模块常用方法
代码: import os apath = os.path.abspath(__file__) # 绝对路径 dirname = os.path.dirname(apath) basename = o ...
- H2O theme for Jekyll
正如我在微博上所说的,使用Jekyll半年以来一直没有令我满意的主题模板,所以开始计划自己写一套好看又好用的主题模板.设计之初就明确了极简主义,风格采用扁平化了,通过卡片式设计来进行区块分明的布局,参 ...
- 获取网站title的脚本
脚本在此 公司的商城需要添加一个脚本,这个脚本就是观察首页页面是否正常,虽然已经配置了zabbix监控网站是否200,但是有一些特殊的情况,比如网页可以打开但是页面是"file not fo ...
- 浅谈在ES5环境下实现const
最近看到一个面试题--用ES5实现const.作为JS初学者的笔者知道在ES6中有const命令,可以用来声明常量,一旦声明,常量的值就不可改变.例如: 1234567891011 const Pi ...
- USB小白学习之路(5) HID鼠标程序
HID鼠标程序 1. 特别注意 需要特别注意,各个例程中的设备描述符,配置描述符等各种描述符都是已经配置好了的,我们需要做的只是在例程中将代码修改为自己需要的部分即可,一般情况下是不可以串搭配的. 2 ...
- jmap的使用以及内存溢出分析
一.jmap的使用以及内存溢出分析 前面通过jstat可以对jvm堆的内存进行统计分析,而jmap可以获取到更加详细的内容,如:内存使用情况的汇总.对内存溢出的定位与分析 1.查看内存使用情况 jma ...
- SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- 从零认识 DOM (一): 对象及继承关系
先上图为敬! 说明: 图中包括了大部分 DOM 接口及对象, 其中: 青色背景为接口, 蓝色背景为类, 灰色背景表示为 ECMAScript 中的对象 忽略了一部分对象, 包括: HTML/SVG 的 ...
- h5单页面布局
前段时间做了一个PC端单页面应用 GitHub因为项目开始的比较仓促,加上本人前端经验特别少,虽然项目大体完成了,但是页面布局确成立它的硬伤...为了填补心里落差,专门做了一个h5的单页面布局,代码很 ...
- scroll-view组件bindscroll实例应用:自定义滚动条
我们知道scroll-view组件作为滑动控件非常好用,而有时候我们想放置一个跟随滚动位置来跟进的滚动条,但又不想用滚动条api该怎么办呢?(当然是自己写一个呗还能怎么办[自黑冷漠脸])嗯,没错.自己 ...