Modifying IPv6 packets

Home Forums Discussions Support Modifying IPv6 packets

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #5071
    zer0
    Participant

      Hi all,

      I have a question about winpkfilter (version 3.0).
      My “ultimate” goal is to patch the ethertype of incoming packets. I have a network equipment (that I can’t modify) which generates bad IPv6 packets. All the packet is correct except the ethertype, which is 0x0800 (IP) instead of 0x86dd (IPv6).

      I made some tests and I can’t understand why some cases are working and some other don’t. I used the PassThru.cpp sample as a starting point. You can find the whole code at the end of the message.

      I have 5 test cases:

      1/ Modify ethertype from 0x0800 to anything else in case of ICMPv4. The packet should be dropped by the stack. Indeed, if I launch the program, I cannot ping the machine anymore. [OK]

      2/ Modify incoming ICMPv4 payload without breaking the chksum. The answer has not the same payload and ping display it. [OK]

      3/ Modify ethertype of v6 packet to a wrong one. The packet should be dropped by the stack, but it is not. [FAILED]

      4/ Modify content of a v6 packet. The packet should be dropped by the stack, but it is not. [FAILED]

      5/ Don’t give v6 packets to stack. When I launch a ping6 to this machine, it still works. [FAILED]

      So, it acts as if v6 packets are only received in my program but without the ability to modify them (perhaps like in FILTER mode).

      Did I do something wrong, or there an explaination for this behaviour ?

      Thanks a lot.
      Olivier


      /*************************************************************************/
      /* Copyright (c) 2000-2004 NT Kernel Resources. */
      /* All Rights Reserved. */
      /* http://www.ntkernel.com */
      /* ndisrd@ntkernel.com */
      /* */
      /*************************************************************************/
      // Modified version of PassThru.cpp sample code
      //

      #include "stdafx.h"
      #define ETH_P_IPV6 0x86dd /* ipv6 ethertype */


      TCP_AdapterList AdList;
      DWORD iIndex;
      CNdisApi api;
      ETH_REQUEST Request;
      INTERMEDIATE_BUFFER PacketBuffer;
      HANDLE hEvent;


      USHORT ntohs( USHORT netshort )
      {
      PUCHAR pBuffer;
      USHORT nResult;

      nResult = 0;
      pBuffer = (PUCHAR )&netshort;

      nResult = ( (pBuffer[ 0 ] << 8) & 0xFF00 )
      | ( pBuffer[ 1 ] & 0x00FF );

      return( nResult );
      }

      #define htons(x) ntohs(x)

      void ReleaseInterface()
      {
      // This function releases packets in the adapter queue and stops listening the interface
      ADAPTER_MODE Mode;

      Mode.dwFlags = 0;
      Mode.hAdapterHandle = (HANDLE)AdList.m_nAdapterHandle[iIndex];

      // Set NULL event to release previously set event object
      api.SetPacketEvent(AdList.m_nAdapterHandle[iIndex], NULL);

      // Close Event
      if (hEvent)
      CloseHandle ( hEvent );

      // Set default adapter mode
      api.SetAdapterMode(&Mode);

      // Empty adapter packets queue
      api.FlushAdapterPacketQueue (AdList.m_nAdapterHandle[iIndex]);
      }

      int main(int argc, char* argv[])
      {
      ether_header* pEthHeader = NULL;
      UINT i=0, k=0;
      UINT testnum=0;

      if (argc < 3)
      {
      printf ("Command line syntax:ntPassThru.exe index numntindex - network interface index.ntnum - number or packets to filterntYou can use ListAdapters to determine correct index.n");
      return 0;
      }

      iIndex = atoi(argv[1]) - 1;
      testnum = atoi(argv[2]);

      if(!api.IsDriverLoaded())
      {
      printf ("Driver not installed on this system of failed to load.n");
      return 0;
      }

      api.GetTcpipBoundAdaptersInfo ( &AdList );

      if ( iIndex + 1 > AdList.m_nAdapterCount )
      {
      printf("There is no network interface with such index on this system.n");
      return 0;
      }

      ADAPTER_MODE Mode;

      Mode.dwFlags = MSTCP_FLAG_RECV_TUNNEL;
      Mode.hAdapterHandle = (HANDLE)AdList.m_nAdapterHandle[iIndex];

      // Create notification event
      hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

      // Set event for helper driver
      if ((!hEvent)||(!api.SetPacketEvent((HANDLE)AdList.m_nAdapterHandle[iIndex], hEvent)))
      {
      printf ("Failed to create notification event or set it for driver.n");
      return 0;
      }

      atexit (ReleaseInterface);

      // Initialize Request

      ZeroMemory ( &Request, sizeof(ETH_REQUEST) );
      ZeroMemory ( &PacketBuffer, sizeof(INTERMEDIATE_BUFFER) );
      Request.EthPacket.Buffer = &PacketBuffer;
      Request.hAdapterHandle = (HANDLE)AdList.m_nAdapterHandle[iIndex];

      api.SetAdapterMode(&Mode);

      while (1)
      {
      WaitForSingleObject ( hEvent, INFINITE );
      ResetEvent(hEvent);

      while(api.ReadPacket(&Request))
      {
      pEthHeader = (ether_header*)PacketBuffer.m_IBuffer;

      /* Display packet info */
      printf ("%4.4d: proto %4.4x ", i, ntohs(pEthHeader->h_proto));
      printf ("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X -> ",
      pEthHeader->h_source[0],
      pEthHeader->h_source[1],
      pEthHeader->h_source[2],
      pEthHeader->h_source[3],
      pEthHeader->h_source[4],
      pEthHeader->h_source[5]);

      printf ("%.2X:%.2X:%.2X:%.2X:%.2X:%.2Xn",
      pEthHeader->h_dest[0],
      pEthHeader->h_dest[1],
      pEthHeader->h_dest[2],
      pEthHeader->h_dest[3],
      pEthHeader->h_dest[4],
      pEthHeader->h_dest[5]);

      switch(testnum) {


      case 1: /* works */
      /* Modify ethertype of ICMPv4 to a wrong one. The packet should be dropped by the stack */
      if(ntohs(pEthHeader->h_proto) == ETH_P_IP) {
      if (PacketBuffer.m_Length >= 0x17) {
      if (PacketBuffer.m_IBuffer[0x17] == 0x01) { /* type == icmp */
      PacketBuffer.m_IBuffer[12] = 0x12;
      PacketBuffer.m_IBuffer[13] = 0x34;
      printf("packet %d PATCHED (ethertype)n",i);
      }
      }
      }
      break;



      case 2: /* works */
      /* Modify incoming ICMPv4 payload without breaking the chksum. The answer will not have
      * the same payload and ping will display it. */
      if(ntohs(pEthHeader->h_proto) == ETH_P_IP) {
      if (PacketBuffer.m_Length >= 0x61) {
      if (PacketBuffer.m_IBuffer[0x17] == 0x01) { /* type == icmp */
      PacketBuffer.m_IBuffer[0x5f] = 0x34;
      PacketBuffer.m_IBuffer[0x61] = 0x38;
      printf("packet %d PATCHED (icmp)n",i);
      }
      }
      }
      break;



      case 3: /* does not work */
      /* Modify ethertype of v6 packet to a wrong one. The packet should be dropped by the stack */
      if(ntohs(pEthHeader->h_proto) == ETH_P_IPV6) {
      if (PacketBuffer.m_Length >= 13) {
      PacketBuffer.m_IBuffer[12] = 0x12;
      PacketBuffer.m_IBuffer[13] = 0x34;
      printf("packet %d PATCHED (ethertype)n",i);
      }
      }
      break;



      case 4: /* does not work */
      /* Modify content of a v6 packet. The packet should be dropped by the stack */
      if(ntohs(pEthHeader->h_proto) == ETH_P_IPV6) {
      if (PacketBuffer.m_Length >= 20) {
      for (k=16; k<20; k++) {
      PacketBuffer.m_IBuffer[k] = 0xFF;
      }
      printf("packet %d PATCHED (IPv6)n",i);
      }
      }
      break;


      case 5: /* does not work */
      /* Don't give v6 packets to stack */
      if(ntohs(pEthHeader->h_proto) == ETH_P_IPV6) {
      i++;
      printf("packet %d droppedn",i);
      continue;
      }
      break;



      default:
      printf("There's no test %dn", testnum);
      return 1;
      }

      // Indicate packet to MSTCP
      api.SendPacketToMstcp(&Request);
      i++;

      }

      }

      return 0;
      }


      #6177
      Vadim Smirnov
      Keymaster

        Well, first of all WinpkFilter x86 standard build (NDIS hook based) you probably downloaded from this site ignores IPv6 protocol (you still can see incoming IPv6 packets as they are also delivered to IPv4) and works with IPv4 only. Though it can be easily extended to support IPv6, but it require rebuilding driver binary. Such sort of modification is available to licensed users.

        x64 standard build also available from this site is based on NDIS IM driver and by default it works with both IPv6 and IPv4.

        #6178
        zer0
        Participant

          Hi SerpentFly, thanks for your answer.

          For my culture, can you please tell me more between an NDIS hook based build and an NDIS IM based build ? I would be quite interrested in understanding better “where” are these hooks in windows… By the way, do you also provide a kernel API to filter and modify packets directly in ring 0 ?

          But I suppose all of this is quite long to explain and I can find a good documentation on the internet…

          Anyway, thanks for the support.

          #6179
          Vadim Smirnov
          Keymaster

            Some filtering techniques overview can be found here http://www.ntkernel.com/w&p.php?id=14

            You can use drivers IOCTL interface in kernel mode, though it would be far easier to modify the original driver to add the functionality you need.

          Viewing 4 posts - 1 through 4 (of 4 total)
          • You must be logged in to reply to this topic.