0

I took a look at libtins and at the Examples I found the ARP Monitor example. The Code of the Example is this here:

#include <tins/tins.h>
#include <map>
#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::map;
using std::bind;

using namespace Tins;

class arp_monitor {
public:
    void run(Sniffer& sniffer);
private:
    bool callback(const PDU& pdu);

    map<IPv4Address, HWAddress<6>> addresses;
};

void arp_monitor::run(Sniffer& sniffer) {
    sniffer.sniff_loop(
        bind(
            &arp_monitor::callback,
            this,
            std::placeholders::_1
        )
    );
}

bool arp_monitor::callback(const PDU& pdu) {
    // Retrieve the ARP layer
    const ARP& arp = pdu.rfind_pdu<ARP>();
    // Is it an ARP reply?
    if (arp.opcode() == ARP::REPLY) {
        // Let's check if there's already an entry for this address
        auto iter = addresses.find(arp.sender_ip_addr());
        if (iter == addresses.end()) {
            // We haven't seen this address. Save it.
            addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()});
            cout << "[INFO] " << arp.sender_ip_addr() << " is at "
                 << arp.sender_hw_addr() << std::endl;
        }
        else {
            // We've seen this address. If it's not the same HW address, inform it
            if (arp.sender_hw_addr() != iter->second) {
                cout << "[WARNING] " << arp.sender_ip_addr() << " is at " 
                     << iter->second << " but also at " << arp.sender_hw_addr() 
                     << endl;
            }
        }
    }
    return true;
}

int main(int argc, char* argv[]) {
    if(argc != 2) {
        cout << "Usage: " <<* argv << " <interface>" << endl;
        return 1;
    }
    arp_monitor monitor;
    // Sniffer configuration
    SnifferConfiguration config;
    config.set_promisc_mode(true);
    config.set_filter("arp");

    try {
        // Sniff on the provided interface in promiscuous mode
        Sniffer sniffer(argv[1], config);
        
        // Only capture arp packets
        monitor.run(sniffer);
    }
    catch (std::exception& ex) {
        std::cerr << "Error: " << ex.what() << std::endl;
    }
}

I ran this Code as this here:

myprogram.exe eth0

The Result was:

Error: Error opening adapter: The System could not find the given Device. (20)

Definition of the words above:

eth0: My Network Device

libtins: high-level, multiplatform C++ network packet sniffing and crafting library

ARP: Address Resolution Protocol

I ran it at only one User named "Shadow" on Windows

Image of the Users Directory

Community
  • 1
  • 1
0xLyptox
  • 5
  • 4
  • 1
    Are you using windows? ('cause of `myprogram.exe`).. – ichramm Dec 24 '19 at 15:11
  • Check if Tins doesn't provide a way to enumerate devices. Also, whether this works may heavily depend on the user it's executed as, please include that info in your question. – Ulrich Eckhardt Dec 24 '19 at 15:14
  • @JuanRamirez you can compile `.exe` files in Unix systems, too. Just include the `.exe` in the filename when passing with the `-o` parameter. – Joel Trauger Dec 24 '19 at 15:20
  • @JoelTrauger Yes, It is called cross compiling... But `eth0` is a unix interface and a windows program will fail to find any interface with that name. – ichramm Dec 24 '19 at 15:36
  • Did you try running it with administrator privileges? Are you sure that interface is called “eth0”? You can check it via “ipconfig” cmd. – slinkin Dec 24 '19 at 15:41
  • @JoelTrauger Just realized that you did not describe cross-compiling, that's just awkward non-conventional naming. – ichramm Dec 24 '19 at 15:44
  • @JuanRamirez What *is* the conventional way of naming executables in Unix? I always dropped the `.exe` on the end to differentiate them from directories because I was bad at using the `ls` command... – Joel Trauger Dec 24 '19 at 15:50
  • 1
    Check [this answer at unix.stackexchange](https://unix.stackexchange.com/a/7392), it is far more elaborate than anything I could come up with. – ichramm Dec 24 '19 at 16:48

1 Answers1

0

Based on the image that te OP uploaded, I can only conclude that I was right about him running the program on Windows so I'll just copy from libtins's documentation:

In order to capture packets on Windows, you could first list all network interfaces. You can do that easily by using the NetworkInterface class:

// First fetch all network interfaces
vector<NetworkInterface> interfaces = NetworkInterface::all();

// Now iterate them
for (const NetworkInterface& iface : interfaces) {
    // First print the name (GUID)
    cout << "Interface name: " << iface.name();

    // Now print the friendly name, a wstring that will contain something like 
    // "Local Area Connection 2"
    wcout << " (" << iface.friendly_name() << ")" << endl;
}

That small code snippet should provide an output like the following:

Interface name: {6527cc7d-c647-4986-ac10-7784dc1f2439} (Local Area Connection 1)
Interface name: {309d733f-79bb-41ef-aaec-8a7b83d2adcf} (Local Area Connection 2)
Interface name: {55ab969f-80df-4d51-8130-291d54a752a3} (Local Area Connection 3)

This might be enough for you to recognize which is the interface you want to use. You can also resort to getting the default interface, which is very likely the one you want to use, or show the IP addresses of each of them until you recognize them:

// Get the default interface (where the default gateway route is)
NetworkInterface iface = NetworkInterface::default_interface();

// Print the name and the IP address
cout << "Default interface: " << iface.name() 
     << " (" << iface.addresses().ip_addr() << ")" << endl;
ichramm
  • 6,437
  • 19
  • 30