Охота на КАИНа payhash[Wolf D.A.] Спецвыпуск: Хакер, номер #060, стр. 060-064-5 Mambo number two Рассмотрим еще одну интересную деталь в стеке TCP (RFC 793). Стек tcp, уже знакомый нам по модели OSI, находится выше стека IP. Посмотрим на схему 2. На языке С это можно представить в виде такой структуры: struct br0_tcphdr { WORD th_sport; //Порт источник WORD th_dport; //Порт получения DWORD th_seq; //(КАИН) DWORD th_ack; //(КАИН) BYTE th_lenres; //(КАИН) BYTE th_flags //Тип TCP-фрагмента (КАИН) #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_ECE 0x40 #define TH_CWR 0x80 #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG|TH_ECE|TH_CWR) u_short th_win; //Размер TCP-фрейма u_short th_sum; // Контрольная сумма TCP-пакета u_short th_urp; }; В данном случае в полях DWORD th_seq; DWORD th_ack; могут содержаться любые данные (см. рисунок). В сумме эти поля дают 8 байт, а это уже, извините, 8x8 = 64 бит, что не так уж и мало для дифференциальных инструкций. Играя смещениями битов, можно получить множество команд или две инструкции для 32-разрядного процессора. Если сформировать SYN-пакет и отправить его на любой другой хост, на хосте-получателе можно будет наблюдать следующую картину дампа SYN-пакета, в котором подделаны значения Seq и Ack. Также мы видим, что ядро нисколько не обратило внимание на эту "мелочь". В принципе, если в поле BYTE th_flag будет содержаться значение, отличное от принятого в стандарте (имеются в виду значения TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG, TH_ECE, TH_CWR, TH_FLAGS (интересно, а неофициальных сколько? =)), пакет все равно будет доставлен на хост-получатель, а ядро само решит, что делать с ним ;). Если просуммировать разряды полей BYTE th_lenres, BYTE th_flags и u_short th win, получим еще оду 32-х разрядную инструкцию. В таком случае наш TCP-пакет может содержать три 32-х разрядные инструкции. С переходом на 64-разрядные архитектуры мы получим одну 64-разрядную инструкцию. Однако на этом наше публичное вскрытие не закончится. Мы присмотримся к структуре TCP еще пристальнее и увидим интересную вещь: WORD th_sport; //Порт источник WORD th_dport; //Порт получения Все, что будет содержаться в этих полях, есть число не больше 65535. Соответственно, в этих полях может содержаться любое число не больше 65535. Объединив разряды этих двух полей, получим еще одно место под 32-разрядную инструкцию. Подделав поля th_sport и th_dport (порт источник, порт назначения) как показано на рисунке, отправим SYN-запрос, а на машине, куда будем отправлять пакет, запустим утилиту tcpbump и увидим вот такую картину: Как видим, система приняла такой пакет (и не подавилась даже ;)) и ответила флагом [R]eset, так как порт не прослушивается. Но все же система обработала такой пакет. Итак, у нас имеется место под четыре 32- и две 64-битные свободные инструкции. Получились интересные четные числа (4x32 и 2x64), а при переходе на 128-разрядные платформы получим одну 128-разрядную инструкцию. В недалеком будущем нас ждет переход на стандарт IPv6, поэтому никто от этого ничего не теряет, все запланировано на несколько лет вперед ;). |