Буфер из нескольких MDL в MPSendPackets

Тема в разделе "WASM.NT.KERNEL", создана пользователем linkmaze, 11 мар 2012.

  1. linkmaze

    linkmaze New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2007
    Сообщения:
    60
    Пытаюсь изменить драйвер passthru чтоб он менял порты в исходящих и входящих пакетах т.е для исходящих пакетов на 443 порт заменял порт назначения на 80 а для входящих с 80 порта менял порт источника на 443. Для замены использую следующий код в функции MPSendPackets:
    Код (Text):
    1. addrpckt=(UCHAR*)Packet->Private.Head->MappedSystemVa;
    2. if((addrpckt[0x17]==6)&&
    3.     (addrpckt[0x25]==0xBB)&&
    4.     (addrpckt[0x24]==0x01)&&
    5.     (addrpckt[0xc]==0x8)&&
    6.     (addrpckt[0xd]==0))
    7. {
    8.     addrpckt[0x25]=0x50;
    9.     addrpckt[0x24]=0;
    10.     rez=chsumm(&addrpckt[0xe]);//расчет КС и перезапись новой КС поверх старой
    11. }
    проблема в том что сам пакет иногда (но не всегда) располагается в виртуальной памяти не последовательно, а разбит как бы на несколько частей т.е. Packet->Private.Head это указатель на MDL и в этом MDL заполнено поле Next которое указывает на следующий MDL в списке,а он указывает на следующий. В каждом из MDL поле MappedSystemVa указывает на разные адреса далеко находящиеся друг от друга. То есть в первом MDL в списке может быть часть пакета с ethernet заголовком во втором IP заголовок в третьем TCP заголовок и данные.
    Вопрос в том можно ли это все как нибудь последовательно разместить в памяти чтоб можно было работать с пакетом (изменять байты) как с последовательным блоком виртуальной памяти. Или какой-нибудь более привычный для драйверов способ - я в ядре новичок.
     
  2. 100gold

    100gold New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2010
    Сообщения:
    165
    Если пакет состоит из 2-х буферов по 100 байт находящихся на разных физических страницах, то эти страницы смапить в виртуальные адреса так, чтобы данные шли последовательно не получится.

    И ещё, если я не ошибаюсь, то NDIS_PACKET передаётся read-only, чтобы менять данные в общем случае понадобится копировать и создавать свой пакет.

    Данные из пакета можно читать вот так:
    Код (Text):
    1.     UINT len;
    2.     PNDIS_BUFFER current_ndis_buffer;
    3.     void* out_buffer;
    4.  
    5.     NdisQueryPacket((PNDIS_PACKET)packet, NULL, NULL, &current_ndis_buffer, &len);
    6.     out_buffer =  ExAllocatePoolWithTag(NonPagedPool, len, 'test');
    7.  
    8.     while (NULL != current_ndis_buffer)
    9.     {
    10.         void* va;
    11.         NdisQueryBuffer(current_ndis_buffer, &va, &len);
    12.         memcpy(out_buffer, va, len);
    13.         out_buffer = (char*)out_buffer + len;
    14.         NdisGetNextBuffer(current_ndis_buffer, &current_ndis_buffer);
    15.     }
     
  3. steelfactor

    steelfactor New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    501
    +1, в NDIS IM изменить IP:port у произвольного пакета не выйдет. Там либо надо свой пакет создавать и каким-то образом втыкать его в очередь (что ппц как геморно), либо перехватывать функцию отсылки на минипорте и партачить пакет там
     
  4. linkmaze

    linkmaze New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2007
    Сообщения:
    60
    Насчет
    если буфер один последовательный (такое иногда бывает) то тот код который я привел работает без вопросов.
    Захожу на модем ADSL на порт 443 без загруженного мной драйвера 192.168.1.1:443 - результат "Попытка соединения не удалась"
    при установке драйвера захожу на тот же адрес 192.168.1.1:443 без проблем.
    Так и в памяти если смотреть в Syser'е то видно что соответствующие байты изменяются.
     
  5. linkmaze

    linkmaze New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2007
    Сообщения:
    60
    Может быть можно как-то перепаковать эти данные в другой пакет который будет в памяти расположен более удобно для манипуляций.
     
  6. 100gold

    100gold New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2010
    Сообщения:
    165
    Да не сложно это сделать, ну т.е. относительно не сложно))) код вычитки данных из NDIS_PACKET я привёл, чтобы создать свой нужно
    Код (Text):
    1. NdisAllocatePacket(&status, &ndis_packet, packet_pool_handle);
    2. NdisAllocateBuffer(&status, &ndis_buffer, buffer_pool_handle, packet, packet_len);
    3. NDIS_SET_PACKET_STATUS(ndis_packet, NDIS_STATUS_RESOURCES);
    4. NdisChainBufferAtFront(ndis_packet, ndis_buffer);
    5. NDIS_SET_PACKET_HEADER_SIZE(ndis_packet, 0);
    6.  
    7. NdisXXXIndicateXXX(ndis_handle, &ndis_packet, 1);
    8.  
    9. NdisUnchainBufferAtFront(ndis_packet, &chained_buffer);
    10. NdisFreeBuffer(ndis_buffer);
    11. NdisFreePacket(ndis_packet);
    *За подробностями в msdn*
    Для подмены пакета достаточно просто вместо того который пришёл, отдать тот который создал.
     
  7. 100gold

    100gold New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2010
    Сообщения:
    165
    Просто поставщик пакета не работает с данными пакета после того как отдал, что в общем случае не всегда верно.
     
  8. linkmaze

    linkmaze New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2007
    Сообщения:
    60
    А почему не получиться, другое дело что это сложно но сам механизм виртуальной адресации позволяет настроить виртуальные адреса так что физические адреса будут разбросаны один относительно другого а виртуальные адреса для этих физических будут располагаться последовательно. Или это в нашем конкретном случае зависит от размера страницы.
     
  9. 100gold

    100gold New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2010
    Сообщения:
    165
    И ещё, советую ооочень, ну т.е. ОООЧЕНЬ внимательно прочитать раздел msdn посвящённый разработке ndis. Тут слишком много ньюансов и сложная архитектура. Да это целиком займёт несколько дней, но без этого будет ещё сложней что-то писать.
     
  10. linkmaze

    linkmaze New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2007
    Сообщения:
    60
    ооочень ну ооочень внимательно прочитать раздел MSDN получиться только после того как я ооооочень ну оооооочень внимательно прочитаю бальшой англо-русский словарь. А пока так бегло как в школе на уроке английского научили.
     
  11. linkmaze

    linkmaze New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2007
    Сообщения:
    60
    т.е. также как в passthru если нет возможности послать тот же пакет дальше
    Код (Text):
    1. \\Packet stacks: Check if we can use the same packet for sending down.
    2.      pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);
    А в каких случаях бывает иначе и как он может с ними работать если он их уже передал в другой драйвер?
     
  12. 100gold

    100gold New Member

    Публикаций:
    0
    Регистрация:
    26 фев 2010
    Сообщения:
    165
    Без английского ловить просто нечего

    И вот как раз про всякие разные случаи обработки пакета в msdn и написано. Например, при наличии флага NDIS_STATUS_RESOURCES владение пакетом возвращается сразу же после возврата из функции, иначе надо специально вызывать NdisReturnPacket
     
  13. steelfactor

    steelfactor New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2007
    Сообщения:
    501
    100gold
    :) спасибо
    давно я этот вопрос ковырял, помню что получалось у меня плохо ))
     
  14. linkmaze

    linkmaze New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2007
    Сообщения:
    60
    Т.е. если для каждого пакета я буду вызывать следующие функции, то для некоторых пакетов или приложений будут возникать проблемы или даже BSOD. Я так понимаю нельзя вызывать NdisFreePacket(ndis_packet); если есть флаг NDIS_STATUS_RESOURCES или этот код можно применить ко всем пакетам для так сказать "переупаковки".
    Код (Text):
    1. NdisAllocatePacket(&status, &ndis_packet, packet_pool_handle);
    2. NdisAllocateBuffer(&status, &ndis_buffer, buffer_pool_handle, packet, packet_len);
    3. NDIS_SET_PACKET_STATUS(ndis_packet, NDIS_STATUS_RESOURCES);
    4. NdisChainBufferAtFront(ndis_packet, ndis_buffer);
    5. NDIS_SET_PACKET_HEADER_SIZE(ndis_packet, 0);
    6.  
    7. NdisXXXIndicateXXX(ndis_handle, &ndis_packet, 1);
    8.  
    9. NdisUnchainBufferAtFront(ndis_packet, &chained_buffer);
    10. NdisFreeBuffer(ndis_buffer);
    11. NdisFreePacket(ndis_packet);
     
  15. linkmaze

    linkmaze New Member

    Публикаций:
    0
    Регистрация:
    23 авг 2007
    Сообщения:
    60
    100gold
    спасибо за код.