Sending SNMP Packets

Mar 14, 2014 at 8:30 PM
I am trying to be able to send out different SNMP packets(Get Bulk, Get Next, walk) while spoofing the sender information at the interface level. SnmpSharpNet offers and awesome SNMP library which would be perfect except it cannot spoof the packets sender info at the interface level.

I tried quickly integrating the two to basically take an encoded snmpsharpnet packet as bytes and then using the bytes as a datagram although this didn't work. So this leads me to ask, is there any examples of sending and receiving SNMP packets with pcap.net? I would like to be able to send out the snmp get requests as a different sender and receive the info back for viewing. Would it be possible to integrate the two or how could I build send and recieve the SNMP packets if I used Pcap.net only?

Here is an example of me trying to use snmpsharpnet with pcap.net. I basically am just using pcap.net as kind of a wrapper to wrap an already encoded packet as a datagram and recieve the reply from snmpsharpnet aswell. It doesnt seem to work though. Could anyone offer assistance?

Code is in next post:
Mar 14, 2014 at 8:30 PM
Edited Mar 14, 2014 at 8:30 PM
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
using PcapDotNet.Packets;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Core;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport;
using SnmpSharpNet;

namespace SnmpPacketSend
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {

            IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;


            int deviceIndex = 0;
            do
            {
                listBox2.Items.Add("Select your interface" + allDevices.Count + "):");
                string deviceIndexString = listBox2.SelectedIndex.ToString();
                if (!int.TryParse(deviceIndexString, out deviceIndex) ||
                    deviceIndex < 1 || deviceIndex > allDevices.Count)
                {
                    deviceIndex = 0;
                }
            } while (deviceIndex == 0);

            // Take the selected adapter
            PacketDevice selectedDevice = allDevices[deviceIndex - 1];

            // Open the output device
            using (PacketCommunicator communicator = selectedDevice.Open(100, // name of the device
                                                                         PacketDeviceOpenAttributes.Promiscuous,
                                                                         // promiscuous mode
                                                                         1000)) // read timeout
            {

                // SNMP community name
                OctetString community = new OctetString("public");

                // Define agent parameters class
                AgentParameters param = new AgentParameters(community);
                // Set SNMP version to 2 (GET-BULK only works with SNMP ver 2 and 3)
                param.Version = SnmpVersion.Ver2;
                // Construct the agent address object
                // IpAddress class is easy to use here because
                //  it will try to resolve constructor parameter if it doesn't
                //  parse to an IP address
                IpAddress agent = new IpAddress("127.0.0.1");

                // Construct target
                UdpTarget target = new UdpTarget((IPAddress) agent, 161, 2000, 1);

                // Define Oid that is the root of the MIB
                //  tree you wish to retrieve
                Oid rootOid = new Oid("1.3.6.1.2.1.2.2.1.2"); // ifDescr

                // This Oid represents last Oid returned by
                //  the SNMP agent
                Oid lastOid = (Oid) rootOid.Clone();

                // Pdu class used for all requests
                Pdu pdu = new Pdu(PduType.GetBulk);

                // In this example, set NonRepeaters value to 0
                pdu.NonRepeaters = 0;
                // MaxRepetitions tells the agent how many Oid/Value pairs to return
                // in the response.
                pdu.MaxRepetitions = 5;

                // Loop through results
                while (lastOid != null)
                {
                    // When Pdu class is first constructed, RequestId is set to 0
                    // and during encoding id will be set to the random value
                    // for subsequent requests, id will be set to a value that
                    // needs to be incremented to have unique request ids for each
                    // packet
                    if (pdu.RequestId != 0)
                    {
                        pdu.RequestId += 1;
                    }
                    // Clear Oids from the Pdu class.
                    pdu.VbList.Clear();
                    // Initialize request PDU with the last retrieved Oid
                    pdu.VbList.Add(lastOid);
                    // Make SNMP request
                    SnmpV2Packet packetv2 = new SnmpV2Packet();
                    packetv2.Community.Set(community);
                    packetv2.Pdu.Set(pdu);
                    byte[] snmppacket = packetv2.encode();
                    Packet packet =
                        PacketBuilder.Build(DateTime.Now,
                                            new EthernetLayer
                                                {
                                                    Source = new MacAddress("11:22:33:44:55:66"),
                                                    Destination = new MacAddress("11:22:33:44:55:67"),
                                                },
                                            new IpV4Layer
                                                {
                                                    Source = new IpV4Address("1.2.3.4"),
                                                    CurrentDestination = new IpV4Address("11.22.33.44"),
                                                    Ttl = 64,
                                                    Identification = 100,
                                                },                                              
                                            new UdpLayer
                                                {
                                                   
                                                    DestinationPort = 161,
                                                    Checksum = null, // Will be filled automatically.
                                                    CalculateChecksumValue = true,
                                                },
                                            new PayloadLayer
                                                {
                                                    Data = new Datagram(snmppacket)
                                                });
                    communicator.SendPacket(packet);

                    // You should catch exceptions in the Request if using in real application.

                    // If result is null then agent didn't reply or we couldn't parse the reply.
                    if (packetv2 != null)
                    {
                        // ErrorStatus other then 0 is an error returned by 
                        // the Agent - see SnmpConstants for error definitions
                        if (packetv2.Pdu.ErrorStatus != 0)
                        {
                            // agent reported an error with the request
                            Console.WriteLine("Error in SNMP reply. Error {0} index {1}",
                                              packetv2.Pdu.ErrorStatus,
                                              packetv2.Pdu.ErrorIndex);
                            lastOid = null;
                            break;
                        }
                        else
                        {
                            // Walk through returned variable bindings
                            foreach (Vb v in packetv2.Pdu.VbList)
                            {
                                // Check that retrieved Oid is "child" of the root OID
                                if (rootOid.IsRootOf(v.Oid))
                                {
                                    listBox1.Items.Add("{0} ({1}): {2}" + v.Oid.ToString() +
                                                       SnmpConstants.GetTypeName(v.Value.Type) + v.Value.ToString());
                                    if (v.Value.Type == SnmpConstants.SMI_ENDOFMIBVIEW)
                                        lastOid = null;
                                    else
                                        lastOid = v.Oid;
                                }
                                else
                                {
                                    // we have reached the end of the requested
                                    // MIB tree. Set lastOid to null and exit loop
                                    lastOid = null;
                                }
                            }
                        }
                    }
                    else
                    {
                       this.Text = ("No response received from SNMP agent.");
                    }
                }
                target.Close();
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;

            if (allDevices.Count == 0)
            {
                listBox2.Items.Add("No interfaces found! Make sure WinPcap is installed.");
                return;
            }

            // Print the list
            for (int i = 0; i != allDevices.Count; ++i)
            {
                LivePacketDevice device = allDevices[i];
                listBox2.Items.Add((i + 1) + ". " + device.Name);
                if (device.Description != null)
                    listBox2.Items.Add(" (" + device.Description + ")");
                else
                    listBox2.Items.Add(" (No description available)");
            }
        }

    }
}
Coordinator
Mar 15, 2014 at 8:26 AM
Hi Autogamer,

Could you provide a .pcap file with a packet you would like to create and a .pcap file with a packet you've created using Pcap.Net so it's easier to see what's wrong?

Thanks,

Boaz.
Mar 20, 2014 at 11:01 PM
Edited Mar 20, 2014 at 11:02 PM
Hi Brickner, sorry for the late reply. I hadn't checked the capture, because I didn't think it even sent. It actually did and I am receiving a reply back. So this leads me to ask, is there a way I can capture only the response from my snmp request so I can do what I need to do with it? So I would like to send my packet like I normally would with pcap.net and then handle the , reply. Does pcap have built in functionality to do this, or do I need to filter it out myself?
Mar 21, 2014 at 8:20 PM
Hi Brickner. I was able to create a solid approach at sending the SNMP packets and receiving them, although I am unsure about how I can decode the received packet. Can this be done directly with pcap.net?


Here is how I am receiving the packets:

private void recievePacket(PacketCommunicator communicator)
{
communicator.SetFilter("udp and src " + destAddress + " and dst " + sourceAddress + " and src port " + destPort);
Packet packet;
while (true)
{
    if (communicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok)
    {
        //Write our packet to text file
        using (StreamWriter writer = new StreamWriter("snmpinfo.txt", true))
        {
           //write decoded packet to text file.
        }
    }
    else if (communicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Timeout)
    {
        //Timeout- Execute code
    }

}
Mar 24, 2014 at 3:26 AM
Hi Brickner, sorry for all of the messages. You can ignore all up until now. To clarify I mean't could I dissect it like wireshark can. See the issue I am having is that I am creating an encoded packet with snmpsharpnet and using that as a datagram within a pcap.net packet, so what happens is that I am able to successfully send and receive a valid response from the agent(confirmed with wireshark) although I am not able to decode the packet properly. When using snmpsharpnet I receive invalid asn.1 errors and when using another ber decoder I only get a part of it.

I am almost sure that the reason why this is happening is because I have a ber encoded packet inside of a datagram. So this would have multiple encoding types.

I figure a way around this would be to send a valid ber encoded snmp packet using snmpsharpnet and capture it and saved it into a pcap file, so I can send this single packet out and change the IP and mac address on the way out. I am just wondering if I am going to run into the exact same issue doing this, or if you have another idea for the first approach?

Also I am going to post my new code here. I noticed others have asked about using SNMP with pcap.net, so I figure it may be useful even though I cant decode the packet properly. I was going to wait until it was working properly although I'll post what I have now.
Mar 24, 2014 at 3:31 AM
Edited Mar 24, 2014 at 3:36 AM
Here it is:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using PcapDotNet.Packets;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Core;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport;
using SnmpSharpNet;

namespace SnmpTool
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private MacAddress sourceMac;
        private IpV4Address sourceAddress;
        private MacAddress destMac;
        private IpV4Address destAddress;
        private ushort destPort;
        private ushort sourcePort;             

        public void Run(PacketDevice device)
        {
            using (PacketCommunicator communicator = device.Open(65536, // name of the device
                                                                              PacketDeviceOpenAttributes.Promiscuous,
                // promiscuous mode
                                                                              1000)) // read timeout
            {
                sendPacket(communicator);
                recievePacket(communicator);
            }
        }
        private void sendPacket(PacketCommunicator communicator)
        {

           //Not capturing packets right now
            //captureReply(selectedDevice);


                // SNMP community name
                OctetString community = new OctetString("public");

                // Define agent parameters class
                AgentParameters param = new AgentParameters(community);
                // Set SNMP version to 2 (GET-BULK only works with SNMP ver 2 and 3)
                param.Version = SnmpVersion.Ver2;


                // Pdu class used for all requests
                Pdu pdu = new Pdu(PduType.Get);
                pdu.VbList.Add("0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0"); //OiD


                // Make SNMP request
                SnmpV2Packet packetv2 = new SnmpV2Packet();
                packetv2.Community.Set(community);
                packetv2.Pdu.Set(pdu);
                byte[] snmppacket = packetv2.encode();
                Packet packet =
                PacketBuilder.Build(DateTime.Now,
                                        new EthernetLayer
                                            {
                                                Source = sourceMac,
                                                Destination = destMac,
                                            },
                                        new IpV4Layer
                                            {
                                                Source = sourceAddress,
                                                CurrentDestination = destAddress,
                                                Ttl = 64,
                                                Identification = 100,
                                            },
                                        new UdpLayer
                                            {
                                                DestinationPort = destPort,
                                                SourcePort = sourcePort, //58300
                                                Checksum = null,
                                                // Will be filled automatically.
                                                CalculateChecksumValue = true,
                                            },
                                        new PayloadLayer
                                            {
                                                Data = new Datagram(snmppacket)
                                            });

                communicator.SendPacket(packet);
        
        }


        private void recievePacket(PacketCommunicator communicator)
        {
          
            communicator.SetFilter("udp and src " + destAddress + " and dst " + sourceAddress + " and src port " + destPort);
            Packet packet;
            while (true)
            {
                if (communicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Ok)
                {
                    //Write our packet to text file
                    using (StreamWriter writer = new StreamWriter("snmpinfo.txt", true))
                    {
                        IpV4Datagram ip = packet.Ethernet.IpV4;
                        UdpDatagram udp = ip.Udp;
                        writer.WriteLine(ip.Source + ":" + udp.SourcePort + " -> " + ip.Destination + ":" + udp.DestinationPort + Environment.NewLine + udp.Decode(Encoding.ASCII) + Environment.NewLine + udp.Payload.Decode(Encoding.ASCII));
                    }
                }
                else if (communicator.ReceivePacket(out packet) == PacketCommunicatorReceiveResult.Timeout)
                {
                    //Timeout- Execute code
                }

            }
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;

            if (allDevices.Count == 0)
            {
                listBox2.Items.Add("No interfaces found! Make sure WinPcap is installed.");
                return;
            }

            // Print the list
            for (int i = 0; i != allDevices.Count; ++i)
            {
                LivePacketDevice device = allDevices[i];
                listBox2.Items.Add((i + 1) + ". " + device.Name);
                if (device.Description != null)
                    listBox2.Items.Add(" (" + device.Description + ")");
                else
                    listBox2.Items.Add(" (No description available)");
            }
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;


            int deviceIndex = 0;
            do
            {
                string deviceIndexString = listBox2.SelectedIndex.ToString();
                if (!int.TryParse(deviceIndexString, out deviceIndex) ||
                    deviceIndex < 1 || deviceIndex > allDevices.Count)
                {
                    deviceIndex = 0;
                }
            } while (deviceIndex == 0);

            // Take the selected adapter
            PacketDevice selectedDevice = allDevices[deviceIndex - 1];
           
            sourceMac = new MacAddress("00:00:00:00:00:00");
            destMac = new MacAddress("00:00:00:00:00:00");
            sourceAddress = new IpV4Address("00.00.000.00");
            destAddress = new IpV4Address("00.00.000.000");
            sourcePort = 58501;
            destPort = 161;

            Run(selectedDevice);
        }
    }
}
Mar 25, 2014 at 8:01 AM
I realized that my issue is because the packets are fragmented and that is why I can't decode them. Wireshark automatically reassembled them so I overlooked that. Can you offer any advice with fragmenting the packets in pcap.net? I don't want to have to interface tshark command line to do the capturing, unless I have to so any help would be great.
Coordinator
Mar 28, 2014 at 5:48 AM
Hi Autogamer,

Do you mean that what you need is to defragment IPv4 fragmented packets?
What exactly is the problem?

Boaz.
Mar 30, 2014 at 6:37 PM
My issue was that I was expecting pcap.net to defrag the packets and I was expecting an SNMP packet once I realized I was only getting the fragmented ipv4 fragmented packets, I had tried receiving the fragmented packets and reassembling them by adding them into a memory stream and then converting the memory stream to a byte array and then decoding the byte array via snmpsharp although I still had issues. Could be with my implementation or maybe even the fact that pcap.net is wrapping the snmp packet bytes and causing snmpsharp to have issues decoding.

I figured it would be easier for me to receive the packets via Tshark, since Tshark can decode the SNMP packets without issue on it's own without the need for using sharpsnmp to decode them so I can get the OID values.

Thanks for replying.
Mar 30, 2014 at 6:39 PM
Sorry I now understand the confusion. In the post you were replying to I mean "Defragmenting the ipv4" packets.
Coordinator
Apr 4, 2014 at 2:10 PM
Yes, Pcap.Net currently offers per-packet processing.
If you need to process multiple packets together using Pcap.Net, you will need to implement that yourself.