Sending a packet to Adapter, can’t see anywhere

Home Forums Discussions General Sending a packet to Adapter, can’t see anywhere

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #13891
    BrianC
    Participant

      Hi. My question is about how actually the driver sends packets to the adapter, because I seems like have success on the sending but I can not see the actual result anywhere, in my own driver capturing or in the Wireshark everything is just empty… Can you clarify is it actually normal or I do something wrong?

      Here is my C# function to send the packet to the adapter. Maybe I made a mistake or something.

      public unsafe void SendPacket(Span<byte> bytes, int adapterIndex)
      {
      var _driver = NdisApi.Open();
      var availableNetworkAdapters = _driver.GetNetworkAdapters().ToList();

      fixed (byte* dataPinnedPtr = bytes)
      {
      // Allocate memory
      var bufPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(INTERMEDIATE_BUFFER)));

      var intBuff = new INTERMEDIATE_BUFFER
      {
      m_Length = (uint)bytes.Length,
      m_Flags = 0,
      };
      for (var i = 0; i < MAX_ETHER_FRAME; i++)
      {
      intBuff.m_IBuffer[i] = dataPinnedPtr[i];
      }

      Marshal.StructureToPtr(intBuff, bufPtr, false);

      var ethRequest = new ETH_REQUEST
      {
      hAdapterHandle = availableNetworkAdapters[adapterIndex].Handle,
      EthPacket = new NDISRD_ETH_Packet
      {
      Buffer = bufPtr
      }
      };
      var result = _driver.SendPacketToAdapter(ref ethRequest);
      Debug.WriteLine($”Result: {result}”);

      // Free allocated memory
      Marshal.FreeHGlobal(bufPtr);
      }
      _driver.Close();
      }

      #13892
      Vadim Smirnov
      Keymaster

        The ability to capture a sent packet depends on how the drivers are layered. In some cases, it might not be possible. I recommend trying to capture the packet using Wireshark on the destination machine.
        If the adapter handle is configured correctly, you should be able to send any packet on a wired network. However, with WiFi, the situation is more complex since the MAC addresses must be accurate.

        #13912
        cjw94022
        Participant

          I am having a similar issue. I have received using a filter, an incoming TCP SYN packet from an IP address I want to block. I can just drop it, but it will cause the remote sender to resend the packet multiple times before giving up. So I tried sending a RST packet response using the SYN packet as a base, swapping the ethernet address, IP addresses and TCP ports setting the TCP flags to RST and then sending the packet back to the adapter. However, the packet was never received at the destination, confirmed by running wireshark.

          #13914
          cjw94022
          Participant

            FYI, I also update the TCP and IP checksums before sending to the adapter.

            #13916
            Vadim Smirnov
            Keymaster
              /**
              @brief Resets a TCP session by sending a forged RST packet. *
              This function clones the original packet, swaps the necessary fields to create a RST packet,recalculates the checksums, and re-injects both the modified original and the forged RST packets. *
              @param packet The original packet to be processed.@return true if the session is successfully reset, false otherwise. */
              bool reset_tcp_session( intermediate_buffer& packet)
              {
              bool result = true;
              if (const auto ethernet_header = reinterpret_cast<ether_header_ptr>(packet.m_IBuffer); ntohs(
              ethernet_header->h_proto) == ETH_P_IP)
              {
              if (const auto ip_header = reinterpret_cast<iphdr_ptr>(ethernet_header + 1); ip_header->ip_p == IPPROTO_TCP)
              {
              const auto tcp_header = reinterpret_cast<tcphdr_ptr>(ip_header + 1);
              // 1. Clone the original packet and obtain headers
              intermediate_buffer cloned_packet = packet;
              const auto clone_ethernet_header = reinterpret_cast<ether_header_ptr>(cloned_packet.m_IBuffer);
              const auto clone_ip_header = reinterpret_cast<iphdr_ptr>(clone_ethernet_header + 1);
              const auto clone_tcp_header = reinterpret_cast<tcphdr_ptr>(reinterpret_cast<PUCHAR>(clone_ip_header) + sizeof(DWORD) * clone_ip_header->ip_hl);
              // 2. Swap Ethernet addresses for the clone
              std::swap(clone_ethernet_header->h_dest, clone_ethernet_header->h_source);
              // 3. Swap IP addresses for the clone
              std::swap(clone_ip_header->ip_dst, clone_ip_header->ip_src);
              // 4. Swap TCP ports for the clone
              std::swap(clone_tcp_header->th_dport, clone_tcp_header->th_sport);
              // 5. Swap SEQ/ACK for the clone
              std::swap(clone_tcp_header->th_ack, clone_tcp_header->th_seq);
              // 6. Update ACK from the original packet with m_data size for the clone
              if (clone_tcp_header->th_flags & TH_SYN)
              clone_tcp_header->th_ack = htonl(ntohl(clone_tcp_header->th_ack) + 1);
              else
              clone_tcp_header->th_ack = htonl(ntohl(clone_tcp_header->th_ack) +
              ntohs(clone_ip_header->ip_len) - clone_ip_header->ip_hl * 4 - clone_tcp_header->th_off * 4);
              // 7. Set new packet buffer length
              cloned_packet.m_Length = sizeof(ether_header) + clone_ip_header->ip_hl * 4 + sizeof(tcphdr);
              // 7.1. Adjust tcp m_data offset
              clone_tcp_header->th_off = 0x5;
              // 8. Set IP total length
              clone_ip_header->ip_len = htons(static_cast<short>(cloned_packet.m_Length - sizeof(ether_header)));
              // 9. Set TTL
              clone_ip_header->ip_ttl = 128;
              // 10. Set TCP flags
              clone_tcp_header->th_flags = TH_RST | TH_ACK;
              // 11. Recalculate checksums
              CNdisApi::RecalculateTCPChecksum(&cloned_packet);
              CNdisApi::RecalculateIPChecksum(&cloned_packet);
              // 7-11 for original packet only done if it is not a connection establishment phase
              if (tcp_header->th_flags != TH_SYN) {
              packet.m_Length = sizeof(ether_header) + ip_header->ip_hl * 4 + tcp_header->th_off * 4;
              ip_header->ip_len = htons(static_cast<short>(packet.m_Length - sizeof(ether_header)));
              tcp_header->th_flags = TH_RST | TH_ACK;
              CNdisApi::RecalculateTCPChecksum(&packet);
              CNdisApi::RecalculateIPChecksum(&packet);
              }
              // 12. Re-inject the modified original and forged RST packets
              PINTERMEDIATE_BUFFER packets[] = {&packet};
              PINTERMEDIATE_BUFFER cloned_packets[] = {&cloned_packet};
              // Check if the packet is not a SYN packet for sending to the appropriate filter
              if (tcp_header->th_flags != TH_SYN) {
              if (packet.m_dwDeviceFlags == PACKET_FLAG_ON_SEND) {
              result = result && send_packets_to_adapters(packets, 1);
              }
              else {
              result = result && send_packets_to_mstcp(packets, 1);
              }
              }
              // Send cloned packets to the opposite filter based on the flag
              if (packet.m_dwDeviceFlags == PACKET_FLAG_ON_SEND) {
              result = result && send_packets_to_mstcp(cloned_packets, 1);
              }
              else {
              result = result && send_packets_to_adapters(cloned_packets, 1);
              }
              }
              }
              return result;
              }
            Viewing 5 posts - 1 through 5 (of 5 total)
            • You must be logged in to reply to this topic.