/// <summary>
        /// Parses a raw packet (e.g. from
        /// <seealso cref="WinDivertRecv(IntPtr, WinDivertBuffer, ref WinDivertAddress, ref uint)" />)
        /// into the various packet headers and/or payloads that may or may not be present.
        /// </summary>
        /// <param name="packet">
        /// The packet to be parsed.
        /// </param>
        /// <param name="packetDataLength">
        /// The total length of the packet pPacket.
        /// </param>
        /// <returns>
        /// TRUE if all expected (non-NULL) outputs were present, FALSE otherwise. Note that FALSE
        /// may sometimes be a legitimate return value, e.g., when both ppIpHdr and ppIpv6Hdr are non-NULL.
        /// </returns>
        /// <remarks>
        /// Each output parameter may be NULL or non-NULL. For non-NULL parameters, this function
        /// will write the pointer to the corresponding header/payload if it exists, or will write
        /// NULL otherwise. Any non-NULL pointer that is returned Is pointer into the original
        /// pPacket packet, and, there is enough space in pPacket to fit the header. This function
        /// does not do any verification of the header/payload contents beyond checking the header
        /// length and any other minimal information required for parsing.
        /// </remarks>
        public static WinDivertParseResult WinDivertHelperParsePacket(WinDivertBuffer packet, uint packetDataLength)
        {
            IPv4Header* _pip4Header = null;
            IPv6Header* _pip6Header = null;
            IcmpV4Header* _picmp4Header = null;
            IcmpV6Header* _picmp6Header = null;
            TcpHeader* _ptcpHdr = null;
            UdpHeader* _pudpHdr = null;

            byte* _pdataPtr;
            uint _dataLen = 0;

            var retVal = new WinDivertParseResult();

            WinDivertNative.WinDivertHelperParsePacket(packet.BufferPointer, packetDataLength, &_pip4Header, &_pip6Header, &_picmp4Header, &_picmp6Header, &_ptcpHdr, &_pudpHdr, &_pdataPtr, ref _dataLen);

            retVal._pip4Header = _pip4Header;
            retVal._pip6Header = _pip6Header;
            retVal._picmp4Header = _picmp4Header;
            retVal._picmp6Header = _picmp6Header;
            retVal._ptcpHdr = _ptcpHdr;
            retVal._pudpHdr = _pudpHdr;
            retVal._pdataPtr = _pdataPtr;
            retVal._dataLen = _dataLen;

            return retVal;
        }
Пример #2
0
        private static unsafe void RunDiversion(IntPtr handle)
        {
            var packet = new WinDivertBuffer();

            var addr = new WinDivertAddress();

            uint readLen = 0;

            IPv4Header *  ipv4Header   = null;
            IPv6Header *  ipv6Header   = null;
            IcmpV4Header *icmpV4Header = null;
            IcmpV6Header *icmpV6Header = null;
            TcpHeader *   tcpHeader    = null;
            UdpHeader *   udpHeader    = null;

            Span <byte> packetData = null;

            NativeOverlapped recvOverlapped;

            IntPtr recvEvent      = IntPtr.Zero;
            uint   recvAsyncIoLen = 0;

            do
            {
                if (s_running)
                {
                    packetData = null;

                    readLen = 0;

                    recvAsyncIoLen = 0;
                    recvOverlapped = new NativeOverlapped();

                    recvEvent = Kernel32.CreateEvent(IntPtr.Zero, false, false, IntPtr.Zero);

                    if (recvEvent == IntPtr.Zero)
                    {
                        Console.WriteLine("Failed to initialize receive IO event.");
                        continue;
                    }

                    addr.Reset();

                    recvOverlapped.EventHandle = recvEvent;

                    Console.WriteLine("Read");

                    if (!WinDivert.WinDivertRecvEx(handle, packet, 0, ref addr, ref readLen, ref recvOverlapped))
                    {
                        var error = Marshal.GetLastWin32Error();

                        // 997 == ERROR_IO_PENDING
                        if (error != 997)
                        {
                            Console.WriteLine(string.Format("Unknown IO error ID {0} while awaiting overlapped result.", error));
                            Kernel32.CloseHandle(recvEvent);
                            continue;
                        }

                        while (Kernel32.WaitForSingleObject(recvEvent, 1000) == (uint)WaitForSingleObjectResult.WaitTimeout)
                        {
                            ;
                        }

                        if (!Kernel32.GetOverlappedResult(handle, ref recvOverlapped, ref recvAsyncIoLen, false))
                        {
                            Console.WriteLine("Failed to get overlapped result.");
                            Kernel32.CloseHandle(recvEvent);
                            continue;
                        }

                        readLen = recvAsyncIoLen;
                    }

                    Kernel32.CloseHandle(recvEvent);

                    Console.WriteLine("Read packet {0}", readLen);

                    var parseResult = WinDivert.WinDivertHelperParsePacket(packet, readLen);
                    ipv4Header   = parseResult.IPv4Header;
                    ipv6Header   = parseResult.IPv6Header;
                    icmpV4Header = parseResult.IcmpV4Header;
                    icmpV6Header = parseResult.IcmpV6Header;
                    tcpHeader    = parseResult.TcpHeader;
                    udpHeader    = parseResult.UdpHeader;

                    if (addr.Direction == WinDivertDirection.Inbound)
                    {
                        Console.WriteLine("inbound!");
                    }

                    if (ipv4Header != null && tcpHeader != null)
                    {
                        Console.WriteLine($"V4 TCP packet {addr.Direction} from {ipv4Header->SrcAddr}:{tcpHeader->SrcPort.ReverseBytes()} to {ipv4Header->DstAddr}:{tcpHeader->DstPort.ReverseBytes()}");
                    }
                    else if (ipv6Header != null && tcpHeader != null)
                    {
                        Console.WriteLine($"V4 TCP packet {addr.Direction} from {ipv6Header->SrcAddr}:{tcpHeader->SrcPort.ReverseBytes()} to {ipv6Header->DstAddr}:{tcpHeader->DstPort.ReverseBytes()}");
                    }

                    if (packetData != null)
                    {
                        Console.WriteLine("Packet has {0} byte payload.", packetData.Length);
                    }

                    Console.WriteLine($"{nameof(addr.Direction)} - {addr.Direction}");
                    Console.WriteLine($"{nameof(addr.Impostor)} - {addr.Impostor}");
                    Console.WriteLine($"{nameof(addr.Loopback)} - {addr.Loopback}");
                    Console.WriteLine($"{nameof(addr.IfIdx)} - {addr.IfIdx}");
                    Console.WriteLine($"{nameof(addr.SubIfIdx)} - {addr.SubIfIdx}");
                    Console.WriteLine($"{nameof(addr.Timestamp)} - {addr.Timestamp}");
                    Console.WriteLine($"{nameof(addr.PseudoIPChecksum)} - {addr.PseudoIPChecksum}");
                    Console.WriteLine($"{nameof(addr.PseudoTCPChecksum)} - {addr.PseudoTCPChecksum}");
                    Console.WriteLine($"{nameof(addr.PseudoUDPChecksum)} - {addr.PseudoUDPChecksum}");

                    // Console.WriteLine(WinDivert.WinDivertHelperCalcChecksums(packet, ref addr, WinDivertChecksumHelperParam.All));

                    if (!WinDivert.WinDivertSendEx(handle, packet, readLen, 0, ref addr))
                    {
                        Console.WriteLine("Write Err: {0}", Marshal.GetLastWin32Error());
                    }
                }
            }while (s_running);
        }