发新话题
打印

[原创]DDOS终极加速列车算法

[原创]DDOS终极加速列车算法

文章作者:ZV(zvrop_at_163_dot_com)
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

注意:文章首发Zerg Hole网络技术论坛后,由原创作者友情提交到邪恶八进制讨论组。

很久没来了,因为毕业了...事情太多了...

本文产生与前两天群里讨论现在什么DDOS软件最快,然后看到某个软件打出了相当嚣张的简介,为此,我花了两天时间,研究了一下DDOS算法究竟有没有的提升的空间.以此挑战一下最快的DDOS软件的速度.效果还是不错的.
本文原是分两天写的两个部分,现整理一下发到xfocus上来.

先来段代码:
Code Language : C
  1. USHORT checksum(USHORT *buffer, int size)
  2. {
  3. unsigned long cksum=0;
  4. while(size >1){
  5.    printf(\"%04X\r\n\",*buffer);
  6.   cksum+=*buffer++;
  7.   size -=sizeof(USHORT);
  8. }
  9.   if(size ){
  10.    cksum += *(UCHAR*)buffer;
  11.   }
  12.   cksum = (cksum >> 16) + (cksum & 0xffff);
  13.   cksum += (cksum >>16);
  14.   return (USHORT)(~cksum);
  15. }
Parsed in 0.003 seconds
这个是大多数正常的效验和算法,主要是把数据(buffer)当成一个个16位的数值,挨个相加,最后求反码后返回.这个算法速度非常快,以现代的编译器能力来看,没有可能用汇编来加速.不过就算法本身来说不怎么好,毕竟是只加法.还是有值得研究的地方.

因为原先进来计算的数据中包含的效验和是0,所以计算过后把值(反码)放入0的位置.这样,数据包到达目的地的时候,只要再进行一次同样的效验和计算,就能得出结果是0xffff,因为将0改成了整个效验和的和的反码,再次计算的时候,等于将上次计算的结果再加它的反码,所以结果是0xffff(举个例子:比如0x7878+0x8787 = 0xffff).然后对0xffff又求反码后返回,所以是0.只要目的端计算出的是0,说明途中没有出错.

嗯....其实上面说的都是废话,为了让大家对效验和有个直观的了解,下面说重点:

我们都知道,每个tcp包,是由IP包+tcp包组成的.这样里面就有两个效验和,一个是IP包的,一个是TCP包的,对于TCP包的加速算法,将在下面部分给出,前面部分的加速算法只针对IP包.

参与TCP包计算效验和的包括两个部分,一个是伪首部(本文中是暂称tsd首部),一个是TCP首部.分别是这样的:
Code Language : C
  1. typedef struct tsd_hdr //定义TCP伪首部
  2. {
  3. unsigned long saddr; //源地址
  4. unsigned long daddr; //目的地址
  5. char mbz;
  6. char ptcl; //协议类型
  7. unsigned short tcpl; //TCP长度
  8. }PSDHEADER;
  9.  
  10. typedef struct tcp_hdr //定义TCP首部
  11. {
  12. USHORT th_sport; //16位源端口
  13. USHORT th_dport; //16位目的端口
  14. unsigned int th_seq; //32位序列号
  15. unsigned int th_ack; //32位确认号
  16. unsigned char th_lenres; //4位首部长度/6位保留字
  17. unsigned char th_flag; //6位标志位
  18. USHORT th_win; //16位窗口大小
  19. USHORT th_sum; //16位校验和
  20. USHORT th_urp; //16位紧急数据偏移量
  21. }TCPHEADER;
  22.  
  23. 参与IP包计算效验和也有两个部分,一个是IP首部,一个是TCP首部.分别是这样的:
  24.  
  25. typedef struct ip_hdr //定义IP首部
  26. {
  27. unsigned char h_verlen; //4位首部长度,4位IP版本号
  28. unsigned char tos; //8位服务类型TOS
  29. unsigned short total_len; //16位总长度(字节)
  30. unsigned short ident; //16位标识
  31. unsigned short frag_and_flags; //3位标志位
  32. unsigned char ttl; //8位生存时间 TTL
  33. unsigned char proto; //8位协议 (TCP, UDP 或其他)
  34. unsigned short checksum; //16位IP首部校验和
  35. unsigned int sourceIP; //32位源IP地址
  36. unsigned int destIP; //32位目的IP地址
  37. }IPHEADER;
  38.  
  39. typedef struct tcp_hdr //定义TCP首部
  40. {
  41. USHORT th_sport; //16位源端口
  42. USHORT th_dport; //16位目的端口
  43. unsigned int th_seq; //32位序列号
  44. unsigned int th_ack; //32位确认号
  45. unsigned char th_lenres; //4位首部长度/6位保留字
  46. unsigned char th_flag; //6位标志位
  47. USHORT th_win; //16位窗口大小
  48. USHORT th_sum; //16位校验和
  49. USHORT th_urp; //16位紧急数据偏移量
  50. }TCPHEADER;
Parsed in 0.016 seconds
可见两个效验和计算的时候,TCP首部都有参与.根据算法原理,这个是可以被中和的.现在好玩的来了.

因为TCP效验和是先于IP效验和开始计算的(因为IP效验和需要包括TCP首部,而TCP首部这个时候需要先计算完成),TCP首部计算过后,它的效验和已经放入自己的效验和字段.如果再次计算tcp的效验和,因为已经加入了tcp效验和的反码也参与计算.所以最终计算结果为0.

那么计算IP+TCP的效验和的时候,将整个已经计算过效验和的TCP首部加入进来,岂不是白做工?

不,不是,因为TCP计算效验和的时候还参与了TCP伪首部.所以TCP首部中的效验和不是只有它一个部分,还有另外一个部分,TCP伪首部(TSD首部).

那么有没有办法中和这个伪首部呢?如果能综合这个伪首部,使得它也失去计算效果......

答案是肯定的,方法是通过IP首部.

仔细看上面的TCP伪首部和IP首部.仔细分析他们的区别.

因为效验和终归来讲是对数值进行加法计算.如果我们能用IP首部中的某些字段,巧妙的代替了TSD首部中的某些字段,将他们计算的结果综合,那么整个计算过程就相当简单了.

分析的结果大为让人吃惊,TCP伪首部和IP首部中竟然都有目的IP,源IP字段......意思也就是说,这两个字段如果改变的话,对于IP效验和的计算结果丝毫没有任何影响....我想到了可怕的DDOS程序,你呢?

经过一番筛选和精简,得出了一个可怕结论.下面先来个结构,这是我自己分析出的:
Code Language : C
  1. #pragma pack(1)
  2.  
  3. typedef struct _PackStk{
  4. unsigned char h_verlen; //4位首部长度,4位IP版本号
  5. unsigned char tos; //8位服务类型TOS
  6. unsigned short ident; //16位标识
  7. unsigned char ttl; //8位生存时间 TTL
  8. unsigned char frag_and_flags; //3位标志位
  9. unsigned short checksum; //16位IP首部校验和
  10. }PackStk;
Parsed in 0.003 seconds
唯一注意的地方是,这个结构的顺序不能变,且内存对其应该为1.

然后我们只要设置这个报文的字段,计算之效验和后,所有不改变PackStk中字段的IP报文(其他字段可任意改变,包括IP),均不用重新计算IP效验和.大大的节省了时间.不,应该说根本不用花时间.

IP效验和加速到此结束,加速成果:100%

前面说到tcp包中的IP包的效验和可以省略的办法,本次再来说说还剩下的一个效验和也就是tcp效验和的加速方法.由于IP效验和被完全取消,所以这个速度理论上可以提升一倍,而接下来的tcp效验和经过加速之后可以提升90甚至更多,所以最终的效果是将DDOS程序的算法提升了5-6倍.是不是很夸张?是的,我蟁i饷春湍闼?你才会吧这个文章看完.呵呵...

好了,到了这里我也不想隐瞒什么了,我确实在写ddos程序.不过需要澄清一点,我只是为了研究,为了实现加速算法,不会发布的这个程序或者是公开代码,因为这个做法实在太危险了.

下面开始正文.

首先说说我的想法,DDOS程序中对于效验和要反复计算的原因,在于其伪造的IP需要不停的更变,于是每次IP更变之后,都要对整个数据包(IP+TCP)进行效验和,否则发不出去.

在前次的文章中(见我的实验一),我用综合Tsd首部和IP首部的办法,成功的分离出一个packstk首部,于是只要计算这个首部,即可完成IP效验和的计算,并且从此不再需要改变(相信很多人写ddos的时候都会发现这点,更改了ip首部中的ip地址之后,重新计算ip首部,效验和不变).

(对于前次文章,还有个补遗,就是packstk首部中的len字段,不是ip首部+tcp首部的长度,而是单独的ip首部中len的长度,减去Tsd首部中len的长度)

那么剩下的这个tcp首部的效验和计算方法是:计算Tsd首部和tcp首部的和.

关键的来了,大家知道ttl的,当一个数据包经过一个路由的时候,就会将数据包中的ttl值减去1,那么这个时候路由一定需要重新计算效验和,不然数据包到了下个路由就会被丢弃.

路由器真的重新计算这个效验和了吗?

答案是否定的,路由器使用了一个弥补算法,对效验和进行简单的更新之后,就发了出去,这种简单的算法和完全计算效验和计算之后的值是一样的.我们姑且称之为"路由效验和算法".

有文档可查,在rfc1141上.看这里看这里:http://www.faqs.org/rfcs/rfc1141.html

公式是:
复制内容到剪贴板
代码:
~C' = ~(C + (-m) + m') = ~C + (m - m') = ~C + m + ~m'
代码:
Code Language : C
  1. UpdateTTL(iph,n)
  2.     struct ip_hdr *ipptr;
  3.     unsigned char n;
  4.     {
  5.       unsigned long sum;
  6.       unsigned short old;
  7.  
  8.       old = ntohs(*(unsigned short *)&ipptr->ttl);
  9.       ipptr->ttl -= n;
  10.       sum = old + (~ntohs(*(unsigned short *)&ipptr->ttl) & 0xffff);
  11.       sum += ntohs(ipptr->Checksum);
  12.       sum = (sum & 0xffff) + (sum>>16);
  13.       ipptr->Checksum = htons(sum + (sum>>16));
  14.     }
Parsed in 0.005 seconds
不过非常遗憾的是,这个算法经过我的测试,效率只提高了30%-50%,离我预期的90%有相当一段距离.于是我对这段算法进行了更改.

整体上对效验和进行更新的实现不变,新算法采用这样的公式:
复制内容到剪贴板
代码:
C = ~(~C + ∑[所有更改的位i]Gray_Code[i])
抱歉这里不好打求和符号,大概意思就是,效验和新值 = 原始效验和求反,加上所有改变位的格雷码异或位的和,再求反.

这个算法是速度比重新计算效验和快了90%,而且可以改变多个byte的值(原先算法只针对ttl这个byte).因为格雷码可以查表得到,这仅仅是一个内存复制的过程,如果你每次只更改1个IP段(IP有4个段不用我说吧),那么每次只要加上一个格雷码异或位即可.然而实际应用中需要加两个,因为端口也需要改变.

好了,什么是Gray_Code,这个我不想解释了,去看wiki吧.然而我这里用到的Gray_Code是我自己生成的一个表.下面这样的:
复制内容到剪贴板
代码:
unsigned char gray_code[256][2] = {
{0x00,0x80},{0x01,0x01},{0x03,0x02},{0x02,0x01},{0x06,0x04},{0x07,0x01},{0x05,0x02},{0x04,0x01},
{0x0C,0x08},{0x0D,0x01},{0x0F,0x02},{0x0E,0x01},{0x0A,0x04},{0x0B,0x01},{0x09,0x02},{0x08,0x01},

{0x18,0x10},{0x19,0x01},{0x1B,0x02},{0x1A,0x01},{0x1E,0x04},{0x1F,0x01},{0x1D,0x02},{0x1C,0x01},
{0x14,0x08},{0x15,0x01},{0x17,0x02},{0x16,0x01},{0x12,0x04},{0x13,0x01},{0x11,0x02},{0x10,0x01},

{0x30,0x20},{0x31,0x01},{0x33,0x02},{0x32,0x01},{0x36,0x04},{0x37,0x01},{0x35,0x02},{0x34,0x01},
{0x3C,0x08},{0x3D,0x01},{0x3F,0x02},{0x3E,0x01},{0x3A,0x04},{0x3B,0x01},{0x39,0x02},{0x38,0x01},

{0x28,0x10},{0x29,0x01},{0x2B,0x02},{0x2A,0x01},{0x2E,0x04},{0x2F,0x01},{0x2D,0x02},{0x2C,0x01},
{0x24,0x08},{0x25,0x01},{0x27,0x02},{0x26,0x01},{0x22,0x04},{0x23,0x01},{0x21,0x02},{0x20,0x01},

{0x60,0x40},{0x61,0x01},{0x63,0x02},{0x62,0x01},{0x66,0x04},{0x67,0x01},{0x65,0x02},{0x64,0x01},
{0x6C,0x08},{0x6D,0x01},{0x6F,0x02},{0x6E,0x01},{0x6A,0x04},{0x6B,0x01},{0x69,0x02},{0x68,0x01},

{0x78,0x10},{0x79,0x01},{0x7B,0x02},{0x7A,0x01},{0x7E,0x04},{0x7F,0x01},{0x7D,0x02},{0x7C,0x01},
{0x74,0x08},{0x75,0x01},{0x77,0x02},{0x76,0x01},{0x72,0x04},{0x73,0x01},{0x71,0x02},{0x70,0x01},

{0x50,0x20},{0x51,0x01},{0x53,0x02},{0x52,0x01},{0x56,0x04},{0x57,0x01},{0x55,0x02},{0x54,0x01},
{0x5C,0x08},{0x5D,0x01},{0x5F,0x02},{0x5E,0x01},{0x5A,0x04},{0x5B,0x01},{0x59,0x02},{0x58,0x01},

{0x48,0x10},{0x49,0x01},{0x4B,0x02},{0x4A,0x01},{0x4E,0x04},{0x4F,0x01},{0x4D,0x02},{0x4C,0x01},
{0x44,0x08},{0x45,0x01},{0x47,0x02},{0x46,0x01},{0x42,0x04},{0x43,0x01},{0x41,0x02},{0x40,0x01},

{0xC0,0x80},{0xC1,0x01},{0xC3,0x02},{0xC2,0x01},{0xC6,0x04},{0xC7,0x01},{0xC5,0x02},{0xC4,0x01},
{0xCC,0x08},{0xCD,0x01},{0xCF,0x02},{0xCE,0x01},{0xCA,0x04},{0xCB,0x01},{0xC9,0x02},{0xC8,0x01},

{0xD8,0x10},{0xD9,0x01},{0xDB,0x02},{0xDA,0x01},{0xDE,0x04},{0xDF,0x01},{0xDD,0x02},{0xDC,0x01},
{0xD4,0x08},{0xD5,0x01},{0xD7,0x02},{0xD6,0x01},{0xD2,0x04},{0xD3,0x01},{0xD1,0x02},{0xD0,0x01},

{0xF0,0x20},{0xF1,0x01},{0xF3,0x02},{0xF2,0x01},{0xF6,0x04},{0xF7,0x01},{0xF5,0x02},{0xF4,0x01},
{0xFC,0x08},{0xFD,0x01},{0xFF,0x02},{0xFE,0x01},{0xFA,0x04},{0xFB,0x01},{0xF9,0x02},{0xF8,0x01},

{0xE8,0x10},{0xE9,0x01},{0xEB,0x02},{0xEA,0x01},{0xEE,0x04},{0xEF,0x01},{0xED,0x02},{0xEC,0x01},
{0xE4,0x08},{0xE5,0x01},{0xE7,0x02},{0xE6,0x01},{0xE2,0x04},{0xE3,0x01},{0xE1,0x02},{0xE0,0x01},

{0xA0,0x40},{0xA1,0x01},{0xA3,0x02},{0xA2,0x01},{0xA6,0x04},{0xA7,0x01},{0xA5,0x02},{0xA4,0x01},
{0xAC,0x08},{0xAD,0x01},{0xAF,0x02},{0xAE,0x01},{0xAA,0x04},{0xAB,0x01},{0xA9,0x02},{0xA8,0x01},

{0xB8,0x10},{0xB9,0x01},{0xBB,0x02},{0xBA,0x01},{0xBE,0x04},{0xBF,0x01},{0xBD,0x02},{0xBC,0x01},
{0xB4,0x08},{0xB5,0x01},{0xB7,0x02},{0xB6,0x01},{0xB2,0x04},{0xB3,0x01},{0xB1,0x02},{0xB0,0x01},

{0x90,0x20},{0x91,0x01},{0x93,0x02},{0x92,0x01},{0x96,0x04},{0x97,0x01},{0x95,0x02},{0x94,0x01},
{0x9C,0x08},{0x9D,0x01},{0x9F,0x02},{0x9E,0x01},{0x9A,0x04},{0x9B,0x01},{0x99,0x02},{0x98,0x01},

{0x88,0x10},{0x89,0x01},{0x8B,0x02},{0x8A,0x01},{0x8E,0x04},{0x8F,0x01},{0x8D,0x02},{0x8C,0x01},
{0x84,0x08},{0x85,0x01},{0x87,0x02},{0x86,0x01},{0x82,0x04},{0x83,0x01},{0x81,0x02},{0x80,0x01}
};
比较乱,没办法,这里有255个组,每组的第一位是这个组的值,第二位是异或位.

记住,格雷码的好处是,每个相邻变化,在二进制中仅仅有一位改变.我用格雷码的最初原因是因为只更新IP的一个byte情况下较为简单,而选择格雷码表就简单很多,仅仅需要加一次.如果用递增方式更新IP,会产生多个bit位的改变(比如5[0101]->6[0110],这里同时改变了两个bit)对于加法不利.后来因为需要多个位的改变(同时更新IP和端口),使得判断bit位变得很复杂.所以权衡了一下,还是选择了递增方式更新IP的做法(虽然此法要比最快的单格雷码变化要慢上一倍,不过更加适用于实际).

异或位表还是采用的格雷码表,便于定位是哪个位需要更新.因为效验和计算的时候,是按16位为单位计算的,所以可以分析出:
例如
IP:1.2.3.4
端口:0x0506
那么计算时候是这样的
复制内容到剪贴板
代码:
0x0201
+
0x0403
+
0x0506
+
.....
那么02所在的位,04所在的位,端口05所在的位如果更新了,加上的格雷码异或位需要左移八个位置.

好了,下面这个是算法:
Code Language : C
  1. sip = 0; sport = 0;
  2. psip = (unsigned char*) & sip;
  3. psport = (unsigned char*) & sport;
  4. stt2 = (unsigned char*) & tt2;
  5.  
  6. ft_cc[5] = psport[1];
  7. ft_cc[4] = psport[0];
  8.  
  9. ft_cc[3] = psip[3];//01
  10. ft_cc[2] = psip[2];//02
  11. ft_cc[1] = psip[1];//03
  12. ft_cc[0] = psip[0];//04
  13.  
  14. {
  15.  
  16.   sip ++;
  17.   sport ++; //更新ip和端口
  18.   tmp_sum = 0;
  19.  
  20.   //判断是否和上次的IP值不一样,大于则加,小于则减
  21.   //if(gray_code[psip[0]][0] != gray_code[ft_cc[0]][0]){
  22.   if(psip[0] != ft_cc[0]){
  23.    if(gray_code[psip[0]][0] > gray_code[ft_cc[0]][0]){
  24.    tmp_sum += ((unsigned short)gray_code[psip[0]][1] << 8 | 0x00);
  25.    }else{
  26.    tmp_sum -= ((unsigned short)gray_code[psip[0]][1] << 8 | 0x00);
  27.    }
  28.    ft_cc[0] = psip[0];
  29.  
  30.    //if(gray_code[psip[1]][0] != gray_code[ft_cc[1]][0]){
  31.    if(psip[1] != ft_cc[1]){
  32.    if(gray_code[psip[1]][0] > gray_code[ft_cc[1]][0]){
  33.     tmp_sum += (unsigned short)gray_code[psip[1]][1];
  34.    }else{
  35.     tmp_sum -= (unsigned short)gray_code[psip[1]][1];
  36.    }
  37.    ft_cc[1] = psip[1];
  38.  
  39.    //if(gray_code[psip[2]][0] != gray_code[ft_cc[2]][0]){
  40.    if(psip[2] != ft_cc[2]){
  41.     if(gray_code[psip[2]][0] > gray_code[ft_cc[2]][0]){
  42.     tmp_sum += ((unsigned short)gray_code[psip[2]][1] << 8 | 0x00);
  43.     }else{
  44.     tmp_sum -= ((unsigned short)gray_code[psip[2]][1] << 8 | 0x00);
  45.     }
  46.     ft_cc[2] = psip[2];
  47.  
  48.     //if(gray_code[psip[3]][0] != gray_code[ft_cc[3]][0]){
  49.     if(psip[3] != ft_cc[3]){
  50.     if(gray_code[psip[3]][0] > gray_code[ft_cc[3]][0]){
  51.      tmp_sum += (unsigned short)gray_code[psip[3]][1];
  52.     }else{
  53.      tmp_sum -= (unsigned short)gray_code[psip[3]][1];
  54.     }
  55.     ft_cc[3] = psip[3];
  56.     }
  57.    }
  58.    }
  59.   }
  60.  
  61.   //判断是否和上次的端口值不一样,大于则加,小于则减
  62.   //if(gray_code[psport[0]][0] != gray_code[ft_cc[4]][0]){
  63.   if(psport[0] != ft_cc[4]){
  64.    if(gray_code[psport[0]][0] > gray_code[ft_cc[4]][0]){
  65.    tmp_sum += ((unsigned short)gray_code[psport[0]][1] << 8 | 0x00);
  66.    }else{
  67.    tmp_sum -= ((unsigned short)gray_code[psport[0]][1] << 8 | 0x00);
  68.    }
  69.    ft_cc[4] = psport[0];
  70.  
  71.    //if(gray_code[psport[1]][0] != gray_code[ft_cc[5]][0]){
  72.    if(psport[1] != ft_cc[5]){
  73.    if(gray_code[psport[1]][0] > gray_code[ft_cc[5]][0]){
  74.     tmp_sum += (unsigned short)gray_code[psport[1]][1];
  75.    }else{
  76.     tmp_sum -= (unsigned short)gray_code[psport[1]][1];
  77.    }
  78.    ft_cc[5] = psport[1];
  79.    }
  80.   }
  81.  
  82.   tpt2 = (unsigned short)~tt2 + tmp_sum;
  83.   tpt2 = (tpt2 >> 16) + (tpt2 & 0xffff);
  84.   tt2 = (unsigned short)(~tpt2);
  85. }
Parsed in 0.025 seconds
这个算法可以更新IP和port,并更新的效验和使其有效,下面这个部分的
复制内容到剪贴板
代码:
tpt2 = (unsigned short)~tt2 + tmp_sum;
  tpt2 = (tpt2 >> 16) + (tpt2 & 0xffff);
  tt2 = (unsigned short)(~tpt2);
tmp_sum就是格雷码异或位的和值.然后经过高位相加,最后存入效验和.这样更新出来的效验和与重新计算过后的是一样的.

到这里.基本上该说的都说完了,应该来说不是那么详细.

测试中1000万个效验和,只改变1byte(ip单位变化)的计算时间是230ms,同时改变3个byte(ip多位变化+端口)以上的计算时间只要600ms,而用正常方法计算得2800ms.

效验和计算是达到12倍的速度.经过发包测试(这个时候主要的瓶颈就在于sendto函数了),采用缓存池并发线程(一个线程专门负责计算效验和,另外开3-n个线程用于发包),在我机器上可以满负荷运行,效率是目前最快的算法的程序的3-6倍,如果网络环境允许,可以达到10倍以上.

不要向我要求代码,有编程能力和数学能力的,看完我这篇垃圾的文章,应该就可以写出这样的算法.最后感谢这两天编写过程中给于我支持和一直帮我测试的朋友,有花须酌酒,LK007.谢谢.好像没什么好说的了,我不善于写文章,也不知道大家看的懂不懂,细节也没说清楚,因为被DDOS的开发者拿去了,这个危害也就大了.另外请大家有什么问题可以给我来信(zvrop_at_163_dot_com)
流氓会武术,谁都挡不住. http://hi.baidu.com/zvrop

TOP

你这个算法一点用都没有,你的机器能有多少带宽,

一般个人用户1M, 服务器好点也才100M,

甚至于网卡也是问题,以64K的SYN 包为例,

我的垃圾集成网卡最高线性速度才是几十K,(线性速度,指发送64K的最小包,每秒的速度)

只有很好的网卡才能达到100M的线性速度,还是理论上的,


//==============

而且DDOS的时候,你能所有用户全满速攻击???

那肉鸡会飞一样向下掉,写的小,稳定就行了,

算法对攻击的影响是微乎其微的,楼主还是省点力吧

TOP

(其实楼主的标题以及开题也很嚣张的说。)
我也考虑过能否在PC机上实现实际加速效果的问题。
不过看完文章后,觉得受益很大,稍微发一点感慨。
“见微知著”吧,可以说,没想到一个DDOS软件的算法也能涉及到这么“复杂”的东西。
为什么我现在还是一个小菜?[我不指在安全方面]
也许是因为我的眼光本来就只放在了桌面级应用上,甘愿只做一个小菜。
[husheng34兄,这也是我看了你的回复后的感觉。只是一个想法,绝无恶意,请不要误会。]
http://hi.baidu.com/anuiz anuiz#163.com

TOP

看来husheng34兄没明白我写这篇文章的意义.带宽可以提高,算法却不是哪里都能找到.

换句话即是说说:

如果机器一样情况下,带宽越高,我的算法所产生的效果越大.
带宽一样的情况下,机器越差,我的算法产生的效果越大.
流氓会武术,谁都挡不住. http://hi.baidu.com/zvrop

TOP

我就不能理解为什么一定要在发包的时候计算checksum呢?
checksum算法是synflood最消耗cpu的部分
不会预先算好checksum再发吗?
这样再烂的算法也能达到15wpps

TOP

补充一下,15wpps是100M下64byte包的极限,当然受到很多东西的限制。比方说husheng34提到的网卡限制,在这方面最明显的例子就是8139和82559。同时猜测路由器限制可以忽略不计,因为crc的硬件实现非常快,而且路由器和pc总线不是同一等级。
另外楼主没有必要再写啥ddos软件了,因为tfn2k已经是难以逾越的颠峰之作。

TOP