Пытаюсь изменить драйвер passthru чтоб он менял порты в исходящих и входящих пакетах т.е для исходящих пакетов на 443 порт заменял порт назначения на 80 а для входящих с 80 порта менял порт источника на 443. Для замены использую следующий код в функции MPSendPackets: Код (Text): addrpckt=(UCHAR*)Packet->Private.Head->MappedSystemVa; if((addrpckt[0x17]==6)&& (addrpckt[0x25]==0xBB)&& (addrpckt[0x24]==0x01)&& (addrpckt[0xc]==0x8)&& (addrpckt[0xd]==0)) { addrpckt[0x25]=0x50; addrpckt[0x24]=0; rez=chsumm(&addrpckt[0xe]);//расчет КС и перезапись новой КС поверх старой } проблема в том что сам пакет иногда (но не всегда) располагается в виртуальной памяти не последовательно, а разбит как бы на несколько частей т.е. Packet->Private.Head это указатель на MDL и в этом MDL заполнено поле Next которое указывает на следующий MDL в списке,а он указывает на следующий. В каждом из MDL поле MappedSystemVa указывает на разные адреса далеко находящиеся друг от друга. То есть в первом MDL в списке может быть часть пакета с ethernet заголовком во втором IP заголовок в третьем TCP заголовок и данные. Вопрос в том можно ли это все как нибудь последовательно разместить в памяти чтоб можно было работать с пакетом (изменять байты) как с последовательным блоком виртуальной памяти. Или какой-нибудь более привычный для драйверов способ - я в ядре новичок.
Если пакет состоит из 2-х буферов по 100 байт находящихся на разных физических страницах, то эти страницы смапить в виртуальные адреса так, чтобы данные шли последовательно не получится. И ещё, если я не ошибаюсь, то NDIS_PACKET передаётся read-only, чтобы менять данные в общем случае понадобится копировать и создавать свой пакет. Данные из пакета можно читать вот так: Код (Text): UINT len; PNDIS_BUFFER current_ndis_buffer; void* out_buffer; NdisQueryPacket((PNDIS_PACKET)packet, NULL, NULL, ¤t_ndis_buffer, &len); out_buffer = ExAllocatePoolWithTag(NonPagedPool, len, 'test'); while (NULL != current_ndis_buffer) { void* va; NdisQueryBuffer(current_ndis_buffer, &va, &len); memcpy(out_buffer, va, len); out_buffer = (char*)out_buffer + len; NdisGetNextBuffer(current_ndis_buffer, ¤t_ndis_buffer); }
+1, в NDIS IM изменить IP:port у произвольного пакета не выйдет. Там либо надо свой пакет создавать и каким-то образом втыкать его в очередь (что ппц как геморно), либо перехватывать функцию отсылки на минипорте и партачить пакет там
Насчет если буфер один последовательный (такое иногда бывает) то тот код который я привел работает без вопросов. Захожу на модем ADSL на порт 443 без загруженного мной драйвера 192.168.1.1:443 - результат "Попытка соединения не удалась" при установке драйвера захожу на тот же адрес 192.168.1.1:443 без проблем. Так и в памяти если смотреть в Syser'е то видно что соответствующие байты изменяются.
Может быть можно как-то перепаковать эти данные в другой пакет который будет в памяти расположен более удобно для манипуляций.
Да не сложно это сделать, ну т.е. относительно не сложно))) код вычитки данных из NDIS_PACKET я привёл, чтобы создать свой нужно Код (Text): NdisAllocatePacket(&status, &ndis_packet, packet_pool_handle); NdisAllocateBuffer(&status, &ndis_buffer, buffer_pool_handle, packet, packet_len); NDIS_SET_PACKET_STATUS(ndis_packet, NDIS_STATUS_RESOURCES); NdisChainBufferAtFront(ndis_packet, ndis_buffer); NDIS_SET_PACKET_HEADER_SIZE(ndis_packet, 0); NdisXXXIndicateXXX(ndis_handle, &ndis_packet, 1); NdisUnchainBufferAtFront(ndis_packet, &chained_buffer); NdisFreeBuffer(ndis_buffer); NdisFreePacket(ndis_packet); *За подробностями в msdn* Для подмены пакета достаточно просто вместо того который пришёл, отдать тот который создал.
Просто поставщик пакета не работает с данными пакета после того как отдал, что в общем случае не всегда верно.
А почему не получиться, другое дело что это сложно но сам механизм виртуальной адресации позволяет настроить виртуальные адреса так что физические адреса будут разбросаны один относительно другого а виртуальные адреса для этих физических будут располагаться последовательно. Или это в нашем конкретном случае зависит от размера страницы.
И ещё, советую ооочень, ну т.е. ОООЧЕНЬ внимательно прочитать раздел msdn посвящённый разработке ndis. Тут слишком много ньюансов и сложная архитектура. Да это целиком займёт несколько дней, но без этого будет ещё сложней что-то писать.
ооочень ну ооочень внимательно прочитать раздел MSDN получиться только после того как я ооооочень ну оооооочень внимательно прочитаю бальшой англо-русский словарь. А пока так бегло как в школе на уроке английского научили.
т.е. также как в passthru если нет возможности послать тот же пакет дальше Код (Text): \\Packet stacks: Check if we can use the same packet for sending down. pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining); А в каких случаях бывает иначе и как он может с ними работать если он их уже передал в другой драйвер?
Без английского ловить просто нечего И вот как раз про всякие разные случаи обработки пакета в msdn и написано. Например, при наличии флага NDIS_STATUS_RESOURCES владение пакетом возвращается сразу же после возврата из функции, иначе надо специально вызывать NdisReturnPacket
Т.е. если для каждого пакета я буду вызывать следующие функции, то для некоторых пакетов или приложений будут возникать проблемы или даже BSOD. Я так понимаю нельзя вызывать NdisFreePacket(ndis_packet); если есть флаг NDIS_STATUS_RESOURCES или этот код можно применить ко всем пакетам для так сказать "переупаковки". Код (Text): NdisAllocatePacket(&status, &ndis_packet, packet_pool_handle); NdisAllocateBuffer(&status, &ndis_buffer, buffer_pool_handle, packet, packet_len); NDIS_SET_PACKET_STATUS(ndis_packet, NDIS_STATUS_RESOURCES); NdisChainBufferAtFront(ndis_packet, ndis_buffer); NDIS_SET_PACKET_HEADER_SIZE(ndis_packet, 0); NdisXXXIndicateXXX(ndis_handle, &ndis_packet, 1); NdisUnchainBufferAtFront(ndis_packet, &chained_buffer); NdisFreeBuffer(ndis_buffer); NdisFreePacket(ndis_packet);