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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: работа с TDI  (Прочитано 23347 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Dmitry_177
Участник

ru
Offline Offline

« : 09-06-2007 23:41 » 

Подскажите пожалуйста где можно почитать про TDI и желательно с кодом.. Поискал по форуму на эту тему, Гром обещал накидать инфы по TDI еще давно, но так и нету.. Не понял

Скачал коды tdi_fw, и попробовал разобраться в них.. Я как понял там создается девайс для приема IRP и еще создаются девайсы и аттачатся (IoAttachDevice) к "\\Device\\Tcp", "\\Device\\Udp", "\\Device\\RawIp". Так вот при приеме IRP_MJ_CREATE что нужно вообще сделать? А то в коде tdifw я почему-то не совсем пойму что там делается.. Здесь была моя ладья...
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #1 : 10-06-2007 07:00 » 

IRP_MJ_CREATE - функция, которая входит в набор обязательных функций, при подъеме системы на создании контекста запускается именно она. Ее стоит использовать для инициализации всех внутренних структур драйвера.

Я не понимаю вопросов типа - не пойму что и как вообще делать. Ставь вопросы конкретнее, чем могу - помогу.

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

А птичку нашу прошу не обижать!!!
Dmitry_177
Участник

ru
Offline Offline

« Ответ #2 : 10-06-2007 12:07 » 

Цитата
IRP_MJ_CREATE - функция, которая входит в набор обязательных функций, при подъеме системы на создании контекста запускается именно она. Ее стоит использовать для инициализации всех внутренних структур драйвера.
Я это знаю.. Я имел ввиду нужно ли какнибудь TDI инициализировать или еще там что-то делать? Или в моем случае можно просто возвращать STATUS_SUCCESS?

Цитата
Я не понимаю вопросов типа - не пойму что и как вообще делать. Ставь вопросы конкретнее, чем могу - помогу.
Я имел ввиду то что мне не ясно что там в tdi_fw делается в обработке IRP_MJ_CREATE, может и мне чего тоже нужно там инициализировать или еще чего..

Цитата
По поводу кодов, я очень давно не работаю для виндовс, поэтому и не выкладывал нового материала. Но у меня есть некоторый опыт и старые код...
Я думаю это будет не только мне интересно, а многим на этом форуме..

Цитата
Давай подробности, что и зачем ты делаешь - попробуем вместе разобраться и вспомнить.
Мне нужно создать TDI Filter. в общем задача такова, перехватывать принятые/отправляемые пакеты, "потрошить" их и сохранять все в файл..
Записан
lexer666
Гость
« Ответ #3 : 11-06-2007 08:02 » 

Цитата
Мне нужно создать TDI Filter. в общем задача такова, перехватывать принятые/отправляемые пакеты, "потрошить" их и сохранять все в файл..
Почему TDI? C NDIS какие-то проблемы?
Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #4 : 11-06-2007 16:23 » 

С NDIS я тоже поразбирался, но он мне ИМХО не подходит.. т.к. мне еще нужно узнавать какое приложение отправляет/принимает текущий пакет. И еще NDIS вроде не работает на виртуальных девайсах, вроде PPP. Да и вообще опять же ИМХО с TDI будет больше универсальности и надежности.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #5 : 11-06-2007 19:12 » 

TDI проще тут ты прав...
Завтра выложу код. Если я правильно помню, то диск у меня на работе. Если не найду, то тогда позже....
Записан

А птичку нашу прошу не обижать!!!
Dmitry_177
Участник

ru
Offline Offline

« Ответ #6 : 12-06-2007 12:05 » 

Буду с нетерпением ждать =)
Записан
lexer666
Гость
« Ответ #7 : 13-06-2007 21:46 » 

tdi так tdi Улыбаюсь

вот исходники по теме:

Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #8 : 14-06-2007 09:47 » 

lexer666, Спасибо! Улыбаюсь

Хотелось бы еще взглянуть на код Грома..
Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #9 : 14-06-2007 17:17 » 

Скажите пожалуйста, как сами данные из пакетов перехватывать? Какой вообще должен быть алгоритм? Что-то я как-то непойму никак..Жаль
Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #10 : 15-06-2007 19:39 » 

У меня что-то не получается.. Приведу весь свой код TDI фильтра. Это мой первый драйвер, если что пожалуйста не пинайте ногами..
Код:
#include <ntddk.h>
#include <tdikrnl.h>

PDEVICE_OBJECT
g_TcpDeviceObject = NULL, // \Device\Tcp
g_TcpOldDeviceObject = NULL,
g_DeviceObject = NULL; // control device


NTSTATUS
DeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);

if (IrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL)
{
switch (IrpStack->MinorFunction)
{
case TDI_SEND:
if (Irp->MdlAddress)
{
UCHAR mdlBuffer[IrpStack->Parameters.SendLength];

mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority);

if (mdlBuffer)
{
DbgPrint ("TDI_Driver[DROP]: Send: 0x%x\n", mdlBuffer);
}
}

break;

//case TDI_RECEIVE:


// break;
}
}


// IoSkipCurrentIrpStackLocation(Irp);
// return IoCallDriver(g_TcpOldDeviceObject, Irp);


Irp->IoStatus.Status = STATUS_SUCCESS;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
}


VOID
UnloadRoutine(IN PDRIVER_OBJECT pDriverObject)
{
#if DBG
DbgPrint ("TDI_Driver: UnloadRoutine called\n");
#endif
}


NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
int i;
UNICODE_STRING usDeviceName;
UNICODE_STRING usDeviceLinkName;
UNICODE_STRING usTcpDeviceName;

RtlInitUnicodeString (&usDeviceName, L"\\Device\\tdifilter");

RtlInitUnicodeString (&usDeviceLinkName, L"\\??\\tdifilter");


status = IoCreateDevice (DriverObject,
0, // sizeof(DEVICE_EXTENSION)
&usDeviceName,
0, // FILE_DEVICE_UNCNOWN
0,
TRUE,
&g_DeviceObject);

if (!NT_SUCCESS(status))
{
#if DBG
DbgPrint ("DriverEntry: g_DeviceObject IoCreateDevice error\n");
#endif

return status;
}


status = IoCreateSymbolicLink (&usDeviceLinkName, &usDeviceName);

if (!NT_SUCCESS(status))
{
#if DBG
DbgPrint ("DriverEntry: IoCreateSymbolicLink error\n");
#endif

IoDeleteDevice (g_DeviceObject);

return status;
}


RtlInitUnicodeString (&usTcpDeviceName, L"\\Device\\Tcp");

status = IoCreateDevice (DriverObject,
0,
NULL,
FILE_DEVICE_UNKNOWN,
0,
TRUE, // FALSE
&g_TcpDeviceObject);

if (!NT_SUCCESS(status))
{
#if DBG
DbgPrint ("DriverEntry: g_TcpDeviceObject IoCreateDevice error\n");
#endif

IoDeleteDevice (g_DeviceObject);

return status;
}


g_TcpDeviceObject->Flags |= DO_DIRECT_IO; // DO_BUFFERED_IO


status = IoAttachDevice (g_TcpDeviceObject,
&usTcpDeviceName,
&g_TcpOldDeviceObject);

if (!NT_SUCCESS(status))
{
#if DBG
DbgPrint ("DriverEntry: g_TcpOldDeviceObject IoAttachDevice error\n");
#endif

IoDeleteDevice (g_TcpDeviceObject);
IoDeleteDevice (g_DeviceObject);

return status;
}


for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = DeviceDispatch;

DriverObject->DriverUnload = UnloadRoutine;


return status;
}

У меня возник ряд вопросов:
1. Правильная ли сама реализация?
2. Почему-то компилятор ругается на: UCHAR mdlBuffer[IrpStack->Parameters.SendLength]; по идее в IrpStack->Parameters.SendLength содержится длина..
3. Как правильно передавать IPR далее по стеку?
     так:
Код:
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(g_TcpOldDeviceObject, Irp);
     или так:   
Код:
Irp->IoStatus.Status = STATUS_SUCCESS;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #11 : 16-06-2007 21:45 » 

По поводу второго вопроса, наверно нужно создавать динамический массив, попробовал сделать так:
Код:
CHAR *mdlBuffer;

mdlBuffer = (CHAR *)malloc (IrpStack->Parameters.SendLength);

mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority);

...

free(mdlBuffer);

компилятор ругается:

1: 'malloc' undefined; assuming extern returning int
2: 'SendLength' : is not a member of '_unnamed'
3: 'free' undefined; assuming extern returning int

Как тогда реализовывать динамический массив? Не понял
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #12 : 17-06-2007 04:32 » 

Dmitry_177, вместо malloc и free надо использовать new и delete -
Код:
CHAR* mdlBuffer=new CHAR [...];

...

delete [] mdlBuffer;

а насчёт SendLength ничего не смогу подсказать... разбирайся с этими классами и их методами...
« Последнее редактирование: 17-06-2007 04:43 от Алексей1153++ » Записан

Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #13 : 17-06-2007 12:17 » 

malloc - функция из юзер мода - ищи и пользуйся кернелевскими.
Записан

А птичку нашу прошу не обижать!!!
Dmitry_177
Участник

ru
Offline Offline

« Ответ #14 : 17-06-2007 12:31 » 

Сделал я, создался у меня драйвер.. Создал программку для его запуска. И.. Полего его загрузки сразуже синий экран выскочил, я даже не успел прочитать что там у меня на экране, как сразу же перезагрузился компьютер.. С тех пор у меня драйвер почему-то больше не запускается.. Ошибка на функции CreateService..
Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #15 : 17-06-2007 12:32 » 

Гром, пока Вы здесь.. что там с кодом?
Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #16 : 17-06-2007 16:14 » 

ругается на
Код:
char* mdlBuffer = new char[IrpStack->Parameters.SendLength];

'new' undeclared identifier
'initializing' : 'char *' differs in levels of indirection from 'int'
syntax error : missing ';' before 'type'
syntax error : missing ';' before '['
' ' : ignored on left of 'char' when no variable is declared
Записан
aks68
Модератор

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

« Ответ #17 : 17-06-2007 20:08 » 

Добрый день.

То Dmitry_177:
Настоятельно рекомендую ознакомится с архитектурой и принципами программирования памяти в ядре Windows.

Исчерпывающее описание архитектуры приводится у Русиновича(#) ch.7 - Memory Management.

По работе с памятью в режиме ядра можно прочитать в:
А. Солдатов(*) гл 7.3 (погано написанно, зато по русски)
Б. Бэйкер(**) - (примерно тоже, что и в Солдатове, но ,как не странно, более понятно, несмотря на то, что по англцки)
В. Они(***) Ch. 3 Memory Management- (великолепное описание теории и практики работы с памятью, много но поделу)

(#) M.Russinovich, D.Solomon. Microsoft Windows Internals. (3-4 editions)
(*) В.П. Солдатов, Программирование драйверов Windows.
(**) A. Baker, J. Lozano. The Windows Device Drivers Book.
(***) W. Oney. Programming WDM.

Все эти книги есть в сети. Русинович и, по-моему, Они еть на русском.

С уважением,
Акс.
« Последнее редактирование: 18-06-2007 05:33 от aks68 » Записан
StandAlone
Гость
« Ответ #18 : 17-06-2007 22:24 » 

CHAR   *mdlBuffer;
mdlBuffer = (CHAR *)malloc (IrpStack->Parameters.SendLength);
mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority);
free(mdlBuffer);

Dmitry_177, похоже, Вас обманул код tdifw -) Там malloc и free, для удобства автора, сделаны макросами для ExAllocatePool\ExFreePool, в memstat.h.
Вообще говоря, IMHO, tdifw полезен как удобный готовый источник, но стиль там довольно жуткий. Венгерская нотация, C-style форматирование...жуть -))
Намного приятней исходники PassThruEx, http://www.wd-3.com, Там аж три варианта.
По поводу TDI в целом... большого смысла в нем нет, Vista в любом случае имеет капитально переписанный стек и TDI там, AFAIK, нету как класса. Решить же задачу с per-application распределением трафика можно банальной фильтрацией IRP поверх объектов устройств, созданных TCP\IP драйвером - device\\tcp, device\\udp, etc.Лелею надежду, что принципы I\O в Висте не изменились, и стеки объектов устройств остались -) Но тут обязательно нужно глубоко вдаться в тонкости обработки IRP - completion, cancellation, queueing..imho, Лучше всего - наглядней и подробнее - это сделано у Walter Oney, Chapter 5, "I/O". Есть в переводе, но на самом деле техническую литературу на английском достаточно просто читать даже с моим pre-intermediate level -).
Из прочего Вам уже посоветовали .. добавлю еще "Программирование драйверов и систем безопасности". На русском, есть в сети.
Сухая и краткая выжимка из DDK, но довольно неплоха (хотя до Они далеко - зато по-русски -))
« Последнее редактирование: 17-06-2007 22:34 от StandAlone » Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #19 : 18-06-2007 09:54 » 

Сделал так:
Код:
#include <ntddk.h>
#include <tdikrnl.h>

PDEVICE_OBJECT
g_TcpDeviceObject = NULL, // \Device\Tcp
g_TcpOldDeviceObject = NULL,
//g_udpfltobj = NULL, // \Device\Udp
//g_udpoldobj = NULL,
//g_ipfltobj = NULL, // \Device\RawIp
//g_ipoldobj = NULL,
g_DeviceObject = NULL; // control device

KSPIN_LOCK g_SpinLock;


NTSTATUS
DeviceDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
UCHAR *mdlBuffer;
UCHAR usBuffer;
KIRQL irql;

KeAcquireSpinLock(&g_SpinLock, &irql);

if (DeviceObject == g_TcpDeviceObject) // || DeviceObject == g_udpfltobj || DeviceObject == g_ipfltobj)
{
if (IrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL)
{
switch (IrpStack->MinorFunction)
{
case TDI_SEND:
if (Irp->MdlAddress)
{
mdlBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, LowPagePriority);

if (mdlBuffer)
{
DbgPrint ("tdifilter: Send[DROP]: %x\n", mdlBuffer);
}
}

KeReleaseSpinLock(&g_SpinLock, irql);

Irp->IoStatus.Status = STATUS_SUCCESS;
//Irp->IoStatus.Information = 0;

if (Irp->PendingReturned)
IoMarkIrpPending(Irp);

IoCompleteRequest(Irp, IO_NO_INCREMENT);

//return IoCallDriver (g_TcpOldDeviceObject, Irp);

break;

//case TDI_RECEIVE:


// break;
}
}
}

KeReleaseSpinLock (&g_SpinLock, irql);

Irp->IoStatus.Status = STATUS_SUCCESS;

//Irp->IoStatus.Information = 0;

IoCompleteRequest(Irp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
}


VOID
UnloadRoutine(IN PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING usDeviceLinkName;

#if DBG
DbgPrint ("tdifilter: UnloadRoutine called\n");
#endif

IoDeleteDevice (g_TcpOldDeviceObject);
IoDeleteDevice (g_TcpDeviceObject);
RtlInitUnicodeString (&usDeviceLinkName, L"\\??\\tdifilter");
IoDeleteSymbolicLink(&usDeviceLinkName);
IoDeleteDevice (g_DeviceObject);

#if DBG
DbgPrint ("tdifilter: UnloadRoutine successfully comleted\n");
#endif
}


NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_SUCCESS;
int i;
UNICODE_STRING usDeviceName;
UNICODE_STRING usDeviceLinkName;
UNICODE_STRING usTcpDeviceName;

#if DBG
DbgPrint ("tdifilter: In DriverEntry\n");
DbgPrint ("tdifilter: RegistryPath = %ws\n", RegistryPath->Buffer);
#endif


DriverObject->DriverUnload = UnloadRoutine;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = DeviceDispatch;


RtlInitUnicodeString (&usDeviceName, L"\\Device\\tdifilter");

status = IoCreateDevice (DriverObject,
0, //sizeof(DEVICE_EXTENSION),
&usDeviceName,
FILE_DEVICE_UNKNOWN,
0,
TRUE,
&g_DeviceObject);

if (!NT_SUCCESS(status))
{
#if DBG
DbgPrint ("tdifilter: g_DeviceObject IoCreateDevice error\n");
#endif

return status;
}


RtlInitUnicodeString (&usDeviceLinkName, L"\\??\\tdifilter");

status = IoCreateSymbolicLink (&usDeviceLinkName, &usDeviceName);

if (!NT_SUCCESS(status))
{
#if DBG
DbgPrint ("tdifilter: IoCreateSymbolicLink error\n");
#endif

IoDeleteDevice (g_DeviceObject);

return status;
}


RtlInitUnicodeString (&usTcpDeviceName, L"\\Device\\Tcp");

status = IoCreateDevice (DriverObject,
0,
NULL,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&g_TcpDeviceObject);

if (!NT_SUCCESS(status))
{
#if DBG
DbgPrint ("tdifilter: g_TcpDeviceObject IoCreateDevice error\n");
#endif

IoDeleteSymbolicLink(&usDeviceLinkName);
IoDeleteDevice (g_DeviceObject);

return status;
}


g_TcpDeviceObject->Flags |= DO_DIRECT_IO; //DO_BUFFERED_IO;


status = IoAttachDevice (g_TcpDeviceObject,
&usTcpDeviceName,
&g_TcpOldDeviceObject);

if (!NT_SUCCESS(status))
{
#if DBG
DbgPrint ("tdifilter: g_TcpOldDeviceObject IoAttachDevice error\n");
#endif

IoDeleteDevice (g_TcpDeviceObject);
IoDeleteSymbolicLink(&usDeviceLinkName);
IoDeleteDevice (g_DeviceObject);

return status;
}


KeInitializeSpinLock(&g_SpinLock);


#if DBG
DbgPrint ("tdifilter: DriverEntry successfully comleted\n");
#endif


return status;
}

Драйвер запускается, все нормальтно.. Но стоит только зайти на какойнибудь сайт или еще что-то, ну в общем чтобы TCPIP трафик пошел, как вылетает сразу синий экран..=( Подскажите пожалуйста что не так?
Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #20 : 18-06-2007 19:32 » 

Почитал я про физическую и вирткальную память.. Чисто теоретически я представляю себе как прочитать данные, а вот практически, что-то до меня не дойдет как это сделать программно..Жаль
Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #21 : 19-06-2007 09:13 » 

У меня получилось =))))))))

TDI_SEND перехватывается..=) Но вот TDI_RECEIVE почему-то нет..=( Может входящий трафик надо еще как-то???

Если я захожу на какойнибудь сайт, по идее там должны быть http-пакеты и html страничка.. Но этого почему-то нету..=(
Записан
Dmitry_177
Участник

ru
Offline Offline

« Ответ #22 : 19-06-2007 12:53 » 

Вообще прежде чем у меня заработало, я переделал драйвер.. У меня не создается девайс и не аттачится потом.. А перехватывается функция MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] драйвера Tcp. Может это из-за этого ловится только исходящий трафик, а входящий нет? Хотя по идее не должно быть такого..
Записан
StandAlone
Гость
« Ответ #23 : 23-06-2007 13:44 » 

Dmitry_177, найди TDIMon и внимательно глянь на все TDI_SET_EVENT_XXX. При ресейве пакеты идут в коллбек-обработчик, зарегистрированный ранее.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines