Search code examples
c#packetpacket-snifferspacket-capturepacketdotnet

Sniffing TCP packets of an android device on local network


I am writing a packet sniffer using C# and PcapDotNet, I've successfully implemented the feature and I was able to capture all the TCP packets from my laptop, the problem is if I target my android device I get no packets at all, I am a beginner at networking, so I think I am probably missing something.

This is my code for the packet handler, I am using an ObjectListView with a model object that contains all the information I want to list, also I have the network adapter in Promiscuous mode with a Berkeley filter to get only TCP packets with port numbers 443 and 80 that contains data (No SYN, FIN, ACK-only packets) from a specific Mac address

Code:

        private void PacketHandler(PcapDotNet.Packets.Packet packet)
        {
            if (packet == null) { return; }
            if (packet.Ethernet == null) { return; }
            if (packet.Ethernet.IpV4 == null) { return; }
            if (packet.Ethernet.IpV4.Tcp == null) { return; }
            if (packet.Ethernet.IpV4.Tcp.Http == null) { return; }

            var acpacket = new AcceptedPacket(); //Model Object
            acpacket.Packet = packet;
            try
            {
                HttpDatagram http = packet.Ethernet.IpV4.Tcp.Http;
                if (packet.Ethernet.Source.ToString() == targetmac)
                {
                    if (http.IsRequest && http.IsValid)
                    {
                        if (materialListView1.InvokeRequired)
                        {
                            materialListView1.BeginInvoke(new Action(() => { 
                            materialListView1.AddObject(acpacket); }));
                        }
                        else
                        {
                            materialListView1.AddObject(acpacket);
                        }
                        ListofAcceptedPackets.Add(acpacket);
                    }
                }
            }
            catch (Exception ex)
            {
                MetroMessageBox.Show(this, ex.Message, "Error", 
                MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
            }
        }

And this how I opened the adapter :

    using (communicator =
  selectedDevice.Open(65536,PacketDeviceOpenAttributes.Promiscuous,
   1000))
    {
        if (communicator.DataLink.Kind != 
        DataLinkKind.Ethernet)
        {
            if (MetroMessageBox.Show(this, "Only Ethernet is supported in this operation!","Error", MessageBoxButtons.OK,MessageBoxIcon.Error) == DialogResult.OK)
                    {
                    return;
                    }
        }

        using (BerkeleyPacketFilter filter = communicator.CreateFilter($"tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) and ether src {targetmac.ToLower()} or tcp port 443 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) and ether src {targetmac.ToLower()}"))
        {
        communicator.SetFilter(filter);
        }

        flag = true;


        Packet packet;
        do
        {
            PacketCommunicatorReceiveResult result = 
            communicator.ReceivePacket(out packet);
            switch (result)
            {
                case 
                PacketCommunicatorReceiveResult.Timeout:
                continue;

                case 
                PacketCommunicatorReceiveResult.Ok:
                {
                    PacketHandler(packet);
                }
                    break;

                default:
                    break;
            }
        } while (flag);

}     

I also tried without any filter and couldn't reach the android device packets. so is it possible to capture TCP packets from other devices on the network besides my own device? or maybe there's something wrong with my implementation?

Edit: after trying a bit more I was able to successfully get the TCP packets from the android device but only while implementing ARP Cache Poisoning at the same time because the device thinks that I am the gateway. so my question stands, can this be done without ARP Cache Poisoning because I think it's a bit aggressive for a packet sniffer.


Solution

  • I was finally able to make it work by applying ARP cache poisoning while the code below is able to redirect packets for any device to their destination, this way you get to capture packets for any device on the network specifically without losing internet access for this device.

    Code:

       private void StartSniffer()
            {
    
                RawCapture rawCapture;
                do
                {
                    if ((rawCapture = capturedevice.GetNextPacket()) != null)
                    {
                        EthernetPacket Packet = PacketDotNet.Packet.ParsePacket(rawCapture.LinkLayerType, rawCapture.Data) as EthernetPacket;
                        if (Packet == null) { return; }
    
                        AcceptedPacket acPacket = new AcceptedPacket();
                        acPacket.Packet = Packet;
    
                        if (Packet.SourceHwAddress.Equals(TargetMAC))
                        {
                            Packet.SourceHwAddress = capturedevice.MacAddress;
                            Packet.DestinationHwAddress = GatewayMAC;
                            capturedevice.SendPacket(Packet);
    
                            if (acPacket.TCPPacket != null &&
                                ((acPacket.Type.Equals("HTTPS") && acPacket.TCPPacket.PayloadData != null) ||
                                 (acPacket.Type.Equals("HTTP") && acPacket.TCPPacket.PayloadData != null)))
                            {
    
                                materialListView1.BeginInvoke(new Action(() =>
                                {
                                    materialListView1.AddObject(acPacket);
    
                                    if (materialListView1.Items.Count > 15 && !ResizeDone)
                                    {
                                        olvColumn8.MaximumWidth = 65;
                                        olvColumn8.MinimumWidth = 65;
                                        olvColumn8.Width = 65;
                                        ResizeDone = true;
                                    }
    
                                    ListofAcceptedPackets.Add(acPacket);
    
                                }));
    
                            }
                        }
    
                        else if (Packet.SourceHwAddress.Equals(GatewayMAC))
                        {
                            IPv4Packet IPV4 = Packet.Extract(typeof(IPv4Packet)) as IPv4Packet;
    
                            if (IPV4.DestinationAddress.Equals(Target))
                            {
                                Packet.SourceHwAddress = capturedevice.MacAddress;
                                Packet.DestinationHwAddress = TargetMAC;
                                capturedevice.SendPacket(Packet);
                            }
    
                            if (Properties.Settings.Default.PacketDirection == "Inbound")
                            {
                                if (acPacket.TCPPacket != null &&
                                    ((acPacket.Type.Equals("HTTPS") && acPacket.TCPPacket.PayloadData != null) ||
                                     (acPacket.Type.Equals("HTTP") && acPacket.TCPPacket.PayloadData != null)))
                                {
                                    materialListView1.BeginInvoke(new Action(() =>
                                    {
                                        materialListView1.AddObject(acPacket);
    
                                        if (materialListView1.Items.Count > 15 && !ResizeDone)
                                        {
                                            olvColumn8.MaximumWidth = 65;
                                            olvColumn8.MinimumWidth = 65;
                                            olvColumn8.Width = 65;
                                            ResizeDone = true;
                                        }
    
                                        ListofAcceptedPackets.Add(acPacket);
    
    
                                    }));
                                }
                            }
                        }
                    }
    
                } while (snifferStarted);
    

    And this is the capture device setup:

     try
        {
            snifferStarted = true;
            if (capturedevice != null)
            {
                capturedevice.Open(DeviceMode.Promiscuous, 1000);
    
                    capturedevice.Filter = $"(ip and ether src {targetmac.ToLower()}) or (ip and ether src {gatewayMAC.ToLower()} and dst net {Target})";
    
                new Thread(() => { StartSniffer(); }).Start();
            }
            else
            {
                MetroMessageBox.Show(this, "No Capture Device is selected!", "Error", MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }
        catch (Exception exception)
        {
            MetroMessageBox.Show(this, exception.Message, "Error", MessageBoxButtons.OK,
                MessageBoxIcon.Error);
        }
    

    Note: this has been done using Packet.Net NOT PcapDotNet.