p0et
Гость
|
|
« : 08-04-2005 06:17 » |
|
необходимо контролировать передачу приложениями TCP/IP UDP и т.д. пакетов, создание, удаление, передачу данных по сокетам... надо написать простенький фаервол.... просьба не посылать нас на MSDN SDK b WIN32.HLP
|
|
|
Записан
|
|
|
|
npak
|
|
« Ответ #1 : 08-04-2005 08:35 » |
|
Рекомендация общего характера: отправиться на www.codeproject.com и набрать в строке поиска слово firewall. Будет порядка десятка ссылок на статьи с открытыми реализациями файрволов. В качестве базы для простейшего фильтра пакетов предлагаю воспользоваться IP Fitering API. Прости, но за этим придётся отправить тебя к MSDN. Честно скажу, документация хреновая. Как-то раз я попробовал написать фильтр, основываясь только на документации, но ничего не вышло. Пришлось полазить по сети, поискать примеры. По-моему, в конечном итоге это даже заработало, но дело было давно, писал по ночам и от того почти ничего не помню . Поищу в архивах, но не гарантирую, что найду. На codeproject один из файерволов построен на IP Filter API, посмотри там. Если не разберёшся, обращайся. Попробую помочь.
|
|
|
Записан
|
|
|
|
Andrew_k7
Гость
|
|
« Ответ #2 : 02-05-2006 20:36 » |
|
А у меня вот такой вопрос. Изрыл весь codeproject и не нашел там фаервола. который бы мог фильтровть пакеты НЕ по заголовку, а по контенту. Т.е. не пропускал те пакеты, в которых находится заранее мною определённая, так сказать "строка из черного списка". Подскажите как реализовать такую весч?
|
|
|
Записан
|
|
|
|
|
Andrew_k7
Гость
|
|
« Ответ #4 : 11-05-2006 18:59 » |
|
Скачал пример... скачал новый ddk (3790.1830) Пытаюсь откомпилить пример... всё хорошо, вот только не знаю что за ошибка такая - Error 4 fatal error LNK1117: syntax error in option 'debug:notmapped,MINIMAL' FwHookDrv
|
|
« Последнее редактирование: 19-12-2007 21:47 от Алексей1153++ »
|
Записан
|
|
|
|
zubr
Гость
|
|
« Ответ #5 : 12-05-2006 03:58 » |
|
Можно обойтись и без драйвера, перехватывая функции recv, send
|
|
|
Записан
|
|
|
|
Andrew_k7
Гость
|
|
« Ответ #6 : 12-05-2006 21:33 » |
|
С Error-ом разобрался. Там в настройках проекта в командной строке ненужные команды стояли, одна из которых и вызывала эту ошибку. To npak: То что надо писать драйвер - это даже не обсуждается. Вопрос только в том КАК, ведь там немного другой принцип программирования. Кстати столкнулся с одной досадной штукой. Оказывается ( ) нельзя пользоваться, предположим, функциями поиска строки в подстроке, которые в обычном приложении можно юзать просто подключив string.h. Мне придется, я так понял, писать эту ф-ию вручную. Возник еще такой вопрос. Как выходит, я получаю IP пакет, в котором после заголовков, которых я насчитал на 32*6 бит идут данные, которые могут собой представлять UDP или TCP пакет, в котором мне и нужно искать совпадения с "черным" списком. Так вот... 1. как определить - какой пакет находится внутри ip пакета (ведь там разные размеры заголовков, и соответственно разный кусок данных надо выдирать) 2. непонятно пока мне в каком виде данные хранятся в пакете. У меня есть unsigned char *Packet - весь IP пакет, и что я получу, вырезав из него, допустим все данные после первых 192 бит(заголовок тобишь)? Можно ли просто написать ф-ию поиска строки char tmp[]="bad_word" в этом куске? 3. необходим быстрый и что важнее простой алгоритм поиска подстроки в строке.
|
|
|
Записан
|
|
|
|
nikedeforest
|
|
« Ответ #7 : 14-05-2006 09:19 » |
|
Чем могу. int find_str(char *str, int l_str, char *substr, int l_sub) { int uk=0; int str_begin=-1; for(int i=0;i< l_str;i++) { if(str[i]==substr[uk]) { if(uk==0) str_begin=i; uk++; } else { uk=0; str_begin=-1; } if(uk==l_sub) return str_begin; }
return -1; }
как определить - какой пакет находится внутри ip пакета (ведь там разные размеры заголовков, и соответственно разный кусок данных надо выдирать)
структуру пакета надо смотреть, скорее всего есть какая-то метка.
|
|
|
Записан
|
ещё один вопрос ...
|
|
|
Andrew_k7
Гость
|
|
« Ответ #8 : 14-05-2006 09:30 » |
|
Ты будешь смеяться.. но вот это чудо написал сразу после того как оставить пост ) int SubstringInString(unsigned char *SubStr, int SubStrLen, unsigned char * Str, int StrLen) { int i; int j; int hit; for (i=0; i < StrLen - SubStrLen; i++) { hit=0; for (j=0; j <= SubStrLen; j++) if (SubStr[j] == Str[i+j]) hit++; if (hit == SubStrLen) return 1; } return 0; }
|
|
|
Записан
|
|
|
|
Andrew_k7
Гость
|
|
« Ответ #9 : 14-05-2006 09:34 » |
|
В принципе то оно работает.. вот только проблема есть... Дело в том что ищу по всему пакету за заголовком, а там мало чего полезного, точнее того что можно напрямую отфильтровать. Единственно что получилось, это если уазываешь, допустим "yandex", то собственно на яндех зайти не получиться, т.к. в ip пакете текст get-запроса передается как есть. А что если я хочу фильтровать пакеты с http траффиком? Что-то через CommView я не вижу текста html-страничек.. такое "ощущение" что они шафруются.. или как? Может кто подскажет, а то с этим столкнулся впервые...
|
|
|
Записан
|
|
|
|
Andrew_k7
Гость
|
|
« Ответ #10 : 14-05-2006 10:11 » |
|
Кстати, может у кого есть пример программы, которая умеет устанавливать-стартовать драйвер и передавать ему данные, в моем случае - массив строк или структуру, которая может содержать строки.
Всё должно выглядеть просто - есть приложение(точнее его пока нет:)), есть драйвер(а вот он есть). Приложение запускается, пользователь вводит несколько строк в черный список, приложение их отправляет драйверу.. а уж он то и начинает фильтровать пакеты в которых эти слова встречаются.
Скачал пример с codeproject, но уж слишком он громоздкий, да и на C++. Я почти уверен что на С# требуемые мне ф-ии можно реализовать проще. Хотя и против С++ ничего не имею. Самое главное - чем проще.
|
|
|
Записан
|
|
|
|
Andrew_k7
Гость
|
|
« Ответ #11 : 14-05-2006 21:02 » |
|
Пример такой уже сам нашел.. причем именно там где он и должен был быть - в книге Солдатова "Программирование драйверов Windows", любезно предоставленную для скачивания www.natahaus.ruКороче остался один ма-а-а-аленький вопрос. Мне надо передать из приложения драйверу структуру вида typedef struct BlackList { UCHAR * blWord; :-/ // Строка из черного списка UINT blWordSize; // Размер строки }BlackListUnit, *PBlackListUnit;
struct BlackListChain { BlackListUnit blUnit;
struct BlackListChain *next; };
Тут у меня сомнения - можно ли так делать? Хочу сказать, что если писать не UCHAR *, а USHORT (т.е. передать не ссылку на строку, а число), то все ОК. А вот со строчкой боюсь не получится. Подскажите, как вообще передаются строки в драйвер?
|
|
|
Записан
|
|
|
|
DarktError
Гость
|
|
« Ответ #12 : 21-02-2009 12:28 » |
|
Помогите разобраться с данными в пакете. При перехвате пакетов получаю две структуры PacketHeader и сам Packet. Далее в PacketHeader проверяю тип пакета - если TCP, то получаю заголовок TCP пакета из Packet. Подскажите где лежат сами данные в пакете и их рамер?
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #13 : 21-02-2009 12:36 » |
|
Вот так вот описывается заголовок TCP /*** Определение структуры TCP пакета. ***/ /*** Формальное определение находится в файле netinet/tcp.h. ***/ /**************************************************************/ typedef unsigned char ui8; typedef unsigned short int ui16; typedef unsigned int ui32; typedef unsigned int uint; struct TCP_header { ui16 src_port; /* номер порта отправителя */ ui16 dst_port; /* номер порта получателя */ ui32 seq_num; /* порядковый номер */ ui32 ack_num; /* номер подтверждения */ uint data_off:4; /* смещение данных */ uint res:6; /* (зарезервировано) */ . uint urg_flag:1; /* срочное, внеполосное сообщение */ uint ack_flag:1; /* поле подтверждения корректно */ uint psh_flag:1; /* немедленно выдать сообщение процессу */ uint rst_flag:1; /* разорвать соединение вследствие ошибок */ uint syn_flag:1; /* открыть виртуальное соединение (канал) */ uint fin_flag:1; /* закрыть соединение */ ui16 window; /* число байтов, получаемых адресатом */ ui16 checksum; /* контрольная сумма сообщения */ ui16 urg_pos; /* последний байт срочного сообщения */ /* опции TCP */ ui8 options[]; ui8 padding[]; /* (необходимо для выравнивания массива data[]) */ uchar data[]; /* данные */ };
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
DarktError
Гость
|
|
« Ответ #14 : 21-02-2009 12:58 » |
|
Спасибо за структуру - у меня была неправильная, теперь ругается на инициализацию массивов: ui8 options[]; ui8 padding[]; uchar data[]; error C2229: struct '_TCPHeader' has an illegal zero-sized array Как исправить?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #15 : 21-02-2009 13:01 » |
|
DarktError, а замени их на указатели
ui8* options; ui8* padding; uchar* data;
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #16 : 21-02-2009 13:10 » |
|
DarktError, Это как бы принципиальная схема, которая была приведена в книге, чтоб понять работу. Вообше убери три последних поля. Да и кстати, а зачем тебе вообше самому вводить данную структуру, когда она уже описана? Для винды насколько я помню все должно спокойно подключаться, если ты задействуеш хедер winsock2.h. Для *nix систем линк в коментах дан.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
DarktError
Гость
|
|
« Ответ #17 : 21-02-2009 13:33 » |
|
Если убрать три последних поля, как тогда получить данные из пакета? Не знал что структура уже описана, спасибо.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #18 : 21-02-2009 13:50 » |
|
Ну у тебя есть смешение, где данные находятся, просто наведи указатель на этот участок и читай данные.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
DarktError
Гость
|
|
« Ответ #19 : 21-02-2009 14:59 » |
|
А не знаете, где можно найти пример получения данных из TCP пакета? Кажется что уже все перепробовал - и все равно никаких результатов Еще не понятно смещение указывает на начало данных, или может указывать на начало опций(если они есть, и как вообще можно узнать есть опции или нет, если убрать поле options из структуры?), и где взять размер этих самых данных - не могу понять сколько нужно читать (размер пакета у меня есть, и могу получить размер заголовка, но без этих опций)? Извините за кучу вопросов. Заранее спасибо.
|
|
« Последнее редактирование: 21-02-2009 17:06 от DarktError »
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #20 : 21-02-2009 17:11 » |
|
Судя по вопросам, ты явно не работаеш с сырыми пакетами на уровне ядра. На уровне пользователя тебе не нужно знать, как выглядит TCP пакет. Тебе будут приходить чистые данные без всех заголовков всех уровней OSI.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
DarktError
Гость
|
|
« Ответ #21 : 21-02-2009 18:14 » |
|
Я перехватываю пакеты в драйвере - заменяю уже имеющийся в xp фильтр пакетов \\Device\\IPFILTERDRIVER на свой. пакеты приходят в мою функцию PF_FORWARD_ACTION myFilterFunction(IN unsigned char *PacketHeader,IN unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long RecvLinkNextHop, IN unsigned long SendLinkNextHop) и здесь я работаю с сырыми пакетами, данном случаю отбрасываю все пакеты кроме TCP. Просто не могу разобраться с полем Options в TCP пакете - не пойму, если опции указаны, то смещение указывает на начало опций или сразу на поле данных, и как посчитать размер данных, если поле Options имеет переменную длину и в заголовок не входит.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #22 : 21-02-2009 18:30 » |
|
Вот выписка из книги Заголовок может иметь переменный размер, поэтому поле data_off указывает на начало данных. Для экономии места это поле, подобно полю header_len IP пакета, определяет не число байтов, предшествующих данным, а число 32 битовых слов. Некоторые поля используются только для открытия соединения, управления передачей и закрытия соединения. Часть полей в процессе передачи данных не заполняется. В TCP заголовках используются те же номера портов, что и в UDP. Поля seq_num и ack_num позволяют выполнять трассировку потока. Когда посылается сообщение, IP подсистема присваивает ему порядковый номер (seq_num). Получа тель уведомляет отправителя о доставке сообщения, посылая ему подтверждение с номером (ack_num), на единицу большим, чем порядковый номер принятого со общения. Это позволяет в подтверждениях также передавать данные. Взаимодействие посредством TCP При открытии потокового соединения программа и сервер обмениваются со общениями по схеме, описанной в табл. 3.7. Таблица 3.7. Трехфазовое квитирование Клиент посылает Сервер посылает Описание SYN=1 (syn_flag) Запрос на виртуальное подключение (канал) АСК=0 (ack_flag) Задание порядкового номера SYN=1 (syn_flag) Разрешает виртуальное подключение АСК=1 (ack_flag) SYN=0 (syn_flag) ACK=1 (ack_flag) Устанавливает виртуальное соединение Это называется трехфазовым квитированием. В процессе обмена сообщениями клиент и сервер устанавливают размеры приемных буферов (окон). Разрыв соединения — тоже не такой простой процесс, как может показаться, ведь в пути могут находиться важные данные. Когда клиент закрывает соедине ние, обмен сообщениями происходит по схеме, представленной в табл. 3.8. Таблица 3.8. Разрыв TCP соединения Клиент Сервер Описание Передает данные FIN=1 (syn_flag) Клиент запрашивает разрыв соединения Принимает данные АСК=1 Происходит очистка каналов сервера Передает дополнитель ные данные Принимает дополни тельные данные АСК=1 Разрыв принят. Сервер разрывает соединение и FIN=1 ждет подтверждения от клиента Клиент закрывает свой конец соединения АСК=1 Когда TCP соединение разорвано, сокет нельзя повторно использовать для организации других соединений. Если требуется подключиться к другому серверу, необходимо создать новый сокет. Остальные протоколы не имеют подобного ог раничения.
Т.е. Чтоб получить доступ к данным, нужно поле data_off умножить на 4. Это и будет смешение от начала TCP заголовка.
|
|
« Последнее редактирование: 21-02-2009 18:39 от Finch »
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
DarktError
Гость
|
|
« Ответ #23 : 26-02-2009 13:19 » |
|
Снова проблема: использую эту структуру typedef struct _TCPHeader { USHORT sourcePort; // номер порта отправителя USHORT destinationPort; // номер порта получателя UINT sequenceNumber; // порядковый номер UINT acknowledgeNumber; // номер подтверждения UINT dataoffset:4; // смещение данных UINT res:4; // (зарезервировано) UINT cwr_flag:1; //Поле «Окно перегрузки уменьшено» — флаг установлен отправителем, чтоб указать, что получен пакет с установленным флагом ECE UINT ece_flag:1; //Поле «Эхо ECN» — указывает, что данный хост способен на ECN (явное уведомление перегрузки) и для указания отправителю о перегрузках в сети(added to header by RFC 3168). UINT urg_flag:1; // срочное, внеполосное сообщение UINT ack_flag:1; // поле подтверждения корректно UINT psh_flag:1; // немедленно выдать сообщение процессу UINT rst_flag:1; // разорвать соединение вследствие ошибок UINT syn_flag:1; // открыть виртуальное соединение (канал) UINT fin_flag:1; // закрыть соединение USHORT window; // число байтов, получаемых адресатом USHORT checksum; // контрольная сумма сообщения USHORT urgentPointer; // последний байт срочного сообщения }TCPHeader; далее в перехваченом пакете if (((IPPacket *)PacketHeader)->ipProtocol == PROT_TCP) { DbgPrint("Packet Header %x \n",((TCPHeader *)Packet)->dataoffset); } При этом ((TCPHeader *)Packet)->dataoffset возвращает 0, а ((TCPHeader *)Packet)->res (резервные 4 бита) - возвращает как раз смещение к данным. Что не так, в дкументации вроде сначала смещение, потом резерв, а у меня почему наоборот Еще sourcePort и destinationPort вовращают странные значения портов, типа 20480,56070,55814 - захожу на странички через ИЕ, 80 порта так и не увидел, не пойму в чем дело, вроде бы все должно работать. Нужна помощь, заранее спасибо.
|
|
« Последнее редактирование: 26-02-2009 15:47 от DarktError »
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #24 : 26-02-2009 20:27 » |
|
Дай дамп памяти твоего пакета. И еше одно маленьекое дополнение кстати, в сети принято прямая запись чисел, которая отличается от записи чисел в системах на основе Intel процессора.
|
|
« Последнее редактирование: 26-02-2009 20:31 от Finch »
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
DarktError
Гость
|
|
« Ответ #25 : 27-02-2009 09:23 » |
|
Для портов помогла функция RtlUshortByteSwap - я так понял она меняет байты местами, а вот как с остальным быть не знаю - дальше же по битам разбираю, да и для 32-битных переменных такой функции нет (есть еще RtlUlongByteSwap - для 64битных).
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #26 : 27-02-2009 13:37 » |
|
Используй стандартные функции uint16_t htons (uint16_t hostshort) Function This function converts the uint16_t integer hostshort from host byte order to network byte order.
uint16_t ntohs (uint16_t netshort) Function This function converts the uint16_t integer netshort from network byte order to host byte order.
uint32_t htonl (uint32_t hostlong) Function This function converts the uint32_t integer hostlong from host byte order to network byte order.
This is used for IPv4 Internet addresses.
uint32_t ntohl (uint32_t netlong) Function This function converts the uint32_t integer netlong from network byte order to host byte order.
This is used for IPv4 Internet addresses.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
DarktError
Гость
|
|
« Ответ #27 : 27-02-2009 14:34 » |
|
На сколько я понял эти функции не являются ядерными и в драйвере работать не будут . Поправьте если ошибаюсь, просто уже не знаю что делать с этим порядком байт
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #28 : 27-02-2009 15:10 » |
|
Ты же вроде как программированием на уровне ядра занимаешся. Неужели сам не можеш написать такую функцию? Например пример в лоб #include <stdio.h> typedef unsigned int uint;
#define SWAP(a,b) {a ^=b; b ^=a; a ^= b;}
uint SwapUint(uint value) { struct SW { uint a:8; uint b:8; uint c:8; uint d:8; } *sw; sw = (SW *)&value; SWAP(sw->a, sw->d); SWAP(sw->b, sw->c); return value; }
int main() { uint value = 0x50607080; printf("Begin value 0x%X, ", value); value = SwapUint(value); printf("End value 0x%X\n", value); return 0; }
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
DarktError
Гость
|
|
« Ответ #29 : 27-02-2009 15:38 » |
|
Просто только начал - еще не сильно разбираюсь. А данные TCP пакета тоже представлены в обратном порядке байт? Если да, то как их преобразовывать?
|
|
|
Записан
|
|
|
|
|