upside
反病毒 反詐騙 反虐犬
|
分享:
x0
|
[資訊教學] 比较smurf与DrDoS攻击
比较smurf与DrDoS攻击 文章 作者:SystEm32
一.SMURF攻击的概念及效果 1.概念:Smurf攻击的命名,是从smurf这个攻击工具来的。Smurf是一种在局域网中的攻击手段,它的作用原理是基于广播地址与回应请求的,我们都知道,在局域网中,计算机被分配的ip地址的最后一位,是在1-254之间,那么最后那个255是留下来干什么的呢?其实带有这个255的地址,比如:192.168.0.255,就是这个子网的广播地址你可以这样试试看:运行->CMD.exe,输入ping 192.168.0.255(假设你的ip是192.168.0.xxx),你会看到计算机会去ping所有属于这个局域网的ip,你发出了一个echo request,却收到了253个reply响应报文。换句话说,你消耗了一份的资源去发送报文,却要消耗253倍的资源去处理接受到的报文,对比是不是很大呢?:) 从攻击者的角度来看,如何利用局域网的这个特性呢?考虑到广播地址有如此惊人的放大能力(200多倍),攻击者只要对广播地址发送大量的ICMP报文(通常是echo,也就是ping出来的东东),其引发的报文震荡是十份剧烈的,很快整个局域网中就会充斥着大量的echo与reply。但是,这样做,吃亏的是可怜的攻击者,因为所有的reply报文都是冲着发送echo报文的ip去的,如果直接这样干的话,攻击者就成了受害者...没人会这么傻,所以smurf诞生了..攻击者用互联网控制信息协议(ICMP)的应答数据包--一种特殊的ping数据包来填充受害者的路由器,这些数据包的目的IP地址同时是受害者的广播地址,而且通过伪造报文的源IP地址,所有的应答报文都将返回到受害者身上,巨大的流量将使受害者失去反应能力,甚至死机,这就是Smurf攻击。
2.效果:看了以上这些,是不是觉得有点毛骨悚然?其实不必担心,因为Smurf看上去似乎能放大攻击力度很多很多倍,但事实如何?其实,由于现在路由器/网关的设置,带有广播地址的报文不能穿越网关,广播报文到达不了目标所在的远程局域网的,所以现在这种攻击是无效的,这也是很多人对smurf不了解的原因。
3.小结:smurf能放大攻击,但只对本地局域网有效,不需要肉鸡,由于网关的过滤,此攻击现在已失效。
二.D.R.D.O.S攻击的概念及效果 1.概念.R.D.O.S是Distributed Reflection Denial of Service Attack的缩写,直译为分布式(Distributed)反射(Reflection)拒绝服务 (Denial of Service)攻击,2002年1月11日凌晨两点,grc.com遭到攻击,大量的ack应答淹没了可怜的grc.com,所幸当时grc.com的网络管理员正好在服务器上,他截取了一小部分攻击数据包,令人吃惊的是,所有攻击他的数据竟然来自于200 多个网络核心基础设施路由器,而这些路由器不可能全部存在安全漏洞。经过这件事,D.R.D.O.S开始被人们所了解,下面,我就来介绍一下D.R.D.O.S的攻击原理和编程实现。 在D.R.D.O.S的名称里有Reflection这个单词,而这,就是这个攻击方式的核心原理所在,从“反射”的字面意思来想一想,grc.com所受到的攻击来自于那么多并未被黑客入侵的核心路由器这种奇怪的现象也就不难解释了,grc.com遭到了“反射”。好比SystEm32小孩躲在Sheepxxy后面拿 鸡蛋丢Jambray,J以为是Sheepxxy丢的,所以拿了一块石头(汗...)砸Sheepxxy(倒霉的Sheepxxy,残念...),发动D.R.D.O.S的攻击者冒充grc.com的IP地址向路由器们发送syn request,也就是TCP三次握手的第一步,路由器们以为grc.com要和自己建立tcp连接,所以返回ack应答,由于源ip 的伪造,所有的ack应答全部都涌向了grc.com,可怜的grc.com就这样被踢下了互联网.一次成功的D.R.D.O.S就产生了。
2.效果:在查关于D.R.D.O.S的资料时,我注意到大部分的资料都提到了分布式反射拒绝服务攻击的一个显著优点:“不需要傀儡机”,也就是不要很多肉鸡便可产生惊人的破坏。但是对于这一点,我只能非常遗憾的说:这是错的,D.R.D.O.S与传统的D.D.O.S(分布式拒绝服务攻击)相比,并没有什么实质的不同,他并不能像有些人说的那样放大攻击,也同样需要很多肉鸡才能实现,攻击的效果也和普通的syn flood(DDOS方式)差不多,并不存在效果的优越性。D.R.D.O.S发送一个syn请求给服务器,服务器便反射一个ack应答给受害者,D.R.D.O.S要想同时有1000个ack应答涌向受害者,它本身就得发送1000个syn请求给1000个服务器,从效果上来说,这和直接发送1000个syn给受害者并无不同。
3.小结.R.D.O.S一向被传得很神奇,因为它"能放大攻击力度",“不需要傀儡机”,但是,事实上D.R.D.O.S不能放大攻击,并且同样要很多肉鸡,那么,D.R.D.O.S有什么优点吗?答案是肯定的,它的优点在于一些对攻击的特征检测和防御将会失效,比如对是否无效ip的判断,是否有固定的TTL值等...还有在路由器上过滤报文也很难,因为攻击你的都是正常的主机.
三.R.D.O.S的编程实现 从本质上说D.R.D.O.S和syn flood区别不大,从编程的角度来看也的却如此,我们常用的SYN ATTACK TOOLS稍做修改就可以变为R.D.O.S工具(为什么不是D.R.D.O.S?我们是学习的,不是破坏的,要分布式的工具何用呢? :P ),下面就简单对R.D.O.S的源码做点说明,完整的代码和工具可以在本期光盘中找到。
1.定义ip头部,tcp头部和tcp伪头部 typedef struct _IP_HEADER //定义IP首部 { unsigned char h_verlen; //4位首部长度,4位IP版本号 unsigned char tos; //8位服务类型TOS unsigned short total_len; //16位总长度(字节) unsigned short ident; //16位标识 unsigned short frag_and_flags; //3位标志位 unsigned char ttl; //8位生存时间 TTL unsigned char proto; //8位协议 (TCP, UDP 或其他) unsigned short checksum; //16位IP首部校验和 unsigned int sourceIP; //32位源IP地址 unsigned int destIP; //32位目的IP地址 }IP_HEADER;
typedef struct _PSD_HEADER //定义TCP伪首部 { unsigned long saddr; //源地址 unsigned long daddr; //目的地址 char mbz; char ptcl; //协议类型 unsigned short tcpl; //TCP长度 }PSD_HEADER;
typedef struct _TCP_HEADER //定义TCP首部 { USHORT th_sport; //16位源端口 USHORT th_dport; //16位目的端口 unsigned int th_seq; //32位序列号 unsigned int th_ack; //32位确认号 unsigned char th_lenres; //4位首部长度/6位保留字 unsigned char th_flag; //6位标志位 USHORT th_win; //16位窗口大小 USHORT th_sum; //16位校验和 USHORT th_urp; //16位紧急数据偏移量 }TCP_HEADER;
我们使用TCP协议通信的时候,系统自动为我们填充好了这些头部,现在为了能够实现伪造源ip,我们必须自己来填充它们,在真正发出的包的结构中,是没有PSD_HEADER(TCP伪首部)的,定义PSD_HEADER仅仅是为了计算出正确的效验和,我们使用CHECKSUM子程序来计算效验和
//CheckSum:计算校验和的子函数 USHORT checksum(USHORT *buffer, int size) { unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size ) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); }
checksum函数的算法是固定的,这里我们使用的是TCP,但它对UDP,ICMP同样适用
建立一个原始套接字 SockRaw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED);
设置IP_HDRINCL,告诉系统由我们自己来填充IP首部 ErrorCode=setsockopt(SockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&flag,sizeof(int));
填充发送缓冲区,利用checksum()函数计算出tcp效验和 memcpy(SendBuf,&psd_header,sizeof(psd_header)); memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header)); tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));
这里要注意,很多人认为发出的包里面包含了psd_header,其实呢... memcpy(SendBuf,&ip_header,sizeof(ip_header)); memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header)); memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);
这几句就是完整的填充好了发送缓冲区,我们可以看到里面并没有psd_header : ] ,再一次证明了psd_header仅仅是为了正确地计算校验和而存在的
最后就是通过一个循环把包发出去了,代码本身很简单,注释得也很详细了,就不多讲了
|