Modifying IPv6 packets

Home Forums Discussions Support Portal Modifying IPv6 packets

This topic contains 3 replies, has 2 voices, and was last updated by  Vadim Smirnov 11 years, 2 months ago.

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
    Moderator

    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
    Moderator

    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.