Topic

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.