Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Помогите.... Как получить контроль над TCP/IP стеком  (Прочитано 32316 раз)
0 Пользователей и 1 Гость смотрят эту тему.
p0et
Гость
« : 08-04-2005 06:17 » 

необходимо контролировать передачу приложениями TCP/IP UDP и т.д. пакетов, создание, удаление, передачу данных по сокетам...
надо написать простенький фаервол.... просьба не посылать нас на MSDN SDK b WIN32.HLP Ага
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 08-04-2005 08:35 » 

Рекомендация общего характера: отправиться на www.codeproject.com и набрать в строке поиска слово firewall.  Будет порядка десятка ссылок на статьи с открытыми реализациями файрволов.

В качестве базы для простейшего фильтра пакетов предлагаю воспользоваться IP Fitering API.  Прости, но за этим придётся отправить тебя к MSDN.  Честно скажу, документация хреновая.  Как-то раз я попробовал написать фильтр, основываясь только на документации, но ничего не вышло.  Пришлось полазить по сети, поискать примеры.  По-моему, в конечном итоге это даже заработало, но дело было давно, писал по ночам и от того почти ничего не помню Улыбаюсь.  Поищу в архивах, но не гарантирую, что найду.

На codeproject один из файерволов построен на IP Filter API, посмотри там.  Если не разберёшся, обращайся.  Попробую помочь.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Andrew_k7
Гость
« Ответ #2 : 02-05-2006 20:36 » 

А у меня вот такой вопрос. Изрыл весь codeproject и не нашел там фаервола. который бы мог фильтровть пакеты НЕ по заголовку, а по контенту. Т.е. не пропускал те пакеты, в которых находится заранее мною определённая, так сказать "строка из черного списка". Подскажите как реализовать такую весч?
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 03-05-2006 08:10 » 

По хорошему надо сделать Filter Driver на транспортный драйвер, но это та ещё бодяга

На codeproject (http://www.codeproject.com/internet/FwHookDrv.asp) есть пример файервола на основе недокументированной фичи ядра Windows 2000 и Windows XP. Автор утверждает, что это просто.  Исходники автор выложил.

Ещё статья с сайта автора http://www.txakynetwork.com/articles/filterhook.htm
« Последнее редактирование: 03-05-2006 08:14 от npak » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
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
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #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
Спокойный
Администратор

il
Offline 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
Как исправить?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Online Online
Сообщений: 13


« Ответ #15 : 21-02-2009 13:01 » 

DarktError, а замени их на указатели

ui8* options;
ui8* padding; 
uchar* data; 
Записан

Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #16 : 21-02-2009 13:10 » 

DarktError, Это как бы принципиальная схема, которая была приведена в книге, чтоб понять работу. Вообше убери три последних поля. Да и кстати, а зачем тебе вообше самому вводить данную структуру, когда она уже описана? Для винды насколько я помню все должно спокойно подключаться, если ты задействуеш хедер  winsock2.h. Для *nix систем линк в коментах дан.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
DarktError
Гость
« Ответ #17 : 21-02-2009 13:33 » 

Если убрать три последних поля, как тогда получить данные из пакета? Не знал что структура уже описана, спасибо.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #18 : 21-02-2009 13:50 » 

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

Не будите спашяго дракона.
             Джаффар (Коша)
DarktError
Гость
« Ответ #19 : 21-02-2009 14:59 » 

А не знаете, где можно найти пример получения данных из TCP пакета? Кажется что уже все перепробовал - и все равно никаких результатов Жаль

Еще не понятно смещение указывает на начало данных, или может указывать на начало опций(если они есть, и как вообще можно узнать есть опции или нет, если убрать поле options из структуры?), и где взять размер этих самых данных - не могу понять сколько нужно читать (размер пакета у меня есть, и могу получить размер заголовка, но без этих опций)?
Извините за кучу вопросов. Заранее спасибо.
« Последнее редактирование: 21-02-2009 17:06 от DarktError » Записан
Finch
Спокойный
Администратор

il
Offline 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
Спокойный
Администратор

il
Offline 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
Спокойный
Администратор

il
Offline 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
Спокойный
Администратор

il
Offline 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
Спокойный
Администратор

il
Offline 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 пакета тоже представлены в обратном порядке байт? Если да, то как их преобразовывать?
Записан
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines