From 4cf00d7682e3db4073300ac341094747f76ff932 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Wed, 15 Aug 2012 08:35:02 -0300 Subject: [PATCH] Added a traceroute example and made the existing examples compile. --- examples/Makefile.in | 13 ++-- examples/arpspoofing.cpp | 61 ++++++++-------- examples/traceroute.cpp | 152 +++++++++++++++++++++++++++++++++++++++ include/ipaddress.h | 7 +- 4 files changed, 198 insertions(+), 35 deletions(-) create mode 100644 examples/traceroute.cpp diff --git a/examples/Makefile.in b/examples/Makefile.in index 3efc1af..620c5d9 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -1,11 +1,11 @@ CXX=@CXX@ -CFLAGS=-c -Wall @CFLAGS@ +CXXFLAGS=-c -Wall @CXXFLAGS@ LDFLAGS=-lpcap -ltins -lpthread -SOURCES=arpspoofing.cpp portscan.cpp +SOURCES=arpspoofing.cpp portscan.cpp OBJECTS=$(SOURCES:.cpp=.o) INCLUDE= -EXECUTABLES=arpspoof portscan +EXECUTABLES=arpspoof portscan traceroute all: $(SOURCES) $(EXECUTABLES) @@ -18,9 +18,12 @@ arpspoof: arpspoofing.o portscan: portscan.o $(CXX) portscan.o $(LDFLAGS) -o portscan + +traceroute: + $(CXX) traceroute.cpp -o traceroute -std=c++0x -Wall $(LDFLAGS) .cpp.o: - $(CXX) $(CFLAGS) $(INCLUDE) $< -o $@ + $(CXX) $(CXXFLAGS) $(INCLUDE) $< -o $@ clean: - rm $(OBJECTS) $(EXECUTABLE) + rm $(OBJECTS) $(EXECUTABLES) diff --git a/examples/arpspoofing.cpp b/examples/arpspoofing.cpp index 355c4d2..7b0130f 100644 --- a/examples/arpspoofing.cpp +++ b/examples/arpspoofing.cpp @@ -22,9 +22,10 @@ #include #include -#include +#include #include #include +#include #include #include @@ -32,30 +33,32 @@ using namespace std; using namespace Tins; -int do_arp_spoofing(uint32_t iface, const string &iface_name, uint32_t gw, uint32_t victim, uint32_t own_ip, uint8_t *own_hw) { +int do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim, + const NetworkInterface::Info &info) +{ PacketSender sender; - uint8_t gw_hw[6], victim_hw[6]; + EthernetII::address_type gw_hw, victim_hw; // Resolves gateway's hardware address. - if(!Utils::resolve_hwaddr(iface_name, gw, gw_hw, &sender)) { + if(!Utils::resolve_hwaddr(iface, gw, &gw_hw, &sender)) { cout << "Could not resolve gateway's ip address.\n"; return 5; } // Resolves victim's hardware address. - if(!Utils::resolve_hwaddr(iface_name, victim, victim_hw, &sender)) { + if(!Utils::resolve_hwaddr(iface, victim, &victim_hw, &sender)) { cout << "Could not resolve victim's ip address.\n"; return 6; } // Print out the hw addresses we're using. - cout << " Using gateway hw address: " << Utils::hwaddr_to_string(gw_hw) << "\n"; - cout << " Using victim hw address: " << Utils::hwaddr_to_string(victim_hw) << "\n"; - cout << " Using own hw address: " << Utils::hwaddr_to_string(own_hw) << "\n"; + cout << " Using gateway hw address: " << gw_hw << "\n"; + cout << " Using victim hw address: " << victim_hw << "\n"; + cout << " Using own hw address: " << info.hw_addr << "\n"; /* We tell the gateway that the victim is at out hw address, * and tell the victim that the gateway is at out hw address */ - ARP *gw_arp = new ARP(gw, victim, gw_hw, own_hw), - *victim_arp = new ARP(victim, gw, victim_hw, own_hw); + ARP *gw_arp = new ARP(gw, victim, gw_hw, info.hw_addr), + *victim_arp = new ARP(victim, gw, victim_hw, info.hw_addr); // We are "replying" ARP requests gw_arp->opcode(ARP::REPLY); victim_arp->opcode(ARP::REPLY); @@ -64,8 +67,8 @@ int do_arp_spoofing(uint32_t iface, const string &iface_name, uint32_t gw, uint3 * We include our hw address as the source address * in ethernet layer, to avoid possible packet dropping * performed by any routers. */ - EthernetII to_gw(iface, gw_hw, own_hw, gw_arp); - EthernetII to_victim(iface, victim_hw, own_hw, victim_arp); + EthernetII to_gw(iface, gw_hw, info.hw_addr, gw_arp); + EthernetII to_victim(iface, victim_hw, info.hw_addr, victim_arp); while(true) { // Just send them once every 5 seconds. if(!sender.send(&to_gw) || !sender.send(&to_victim)) @@ -77,31 +80,31 @@ int do_arp_spoofing(uint32_t iface, const string &iface_name, uint32_t gw, uint3 int main(int argc, char *argv[]) { if(argc != 3 && cout << "Usage: " << *argv << " \n") return 1; - uint32_t gw, victim, own_ip; - uint8_t own_hw[6]; + IPv4Address gw, victim; + EthernetII::address_type own_hw; try { // Convert dotted-notation ip addresses to integer. - gw = Utils::ip_to_int(argv[1]); - victim = Utils::ip_to_int(argv[2]); + gw = argv[1]; + victim = argv[2]; } catch(...) { cout << "Invalid ip found...\n"; return 2; } - // Get the interface which will be the gateway for our requests. - string iface = Utils::interface_from_ip(gw); - cout << iface << "\n"; - uint32_t iface_index; - // Lookup the interface id. This will be required while forging packets. - if(!Utils::interface_id(iface, iface_index) && cout << "Interface " << iface << " does not exist!\n") - return 3; - // Find the interface hardware and ip address. - if(!Utils::interface_hwaddr(iface, own_hw) || !Utils::interface_ip(iface, own_ip)) { - cout << "Error fetching addresses from " << iface << "\n"; - return 4; + NetworkInterface iface; + NetworkInterface::Info info; + try { + // Get the interface which will be the gateway for our requests. + iface = gw; + // Lookup the interface id. This will be required while forging packets. + // Find the interface hardware and ip address. + info = iface.addresses(); } - // Poison ARP tables :D - return do_arp_spoofing(iface_index, iface, gw, victim, own_ip, own_hw); + catch(std::runtime_error &ex) { + cout << ex.what() << endl; + return 3; + } + return do_arp_spoofing(iface, gw, victim, info); } diff --git a/examples/traceroute.cpp b/examples/traceroute.cpp new file mode 100644 index 0000000..e8e7202 --- /dev/null +++ b/examples/traceroute.cpp @@ -0,0 +1,152 @@ +/* + * libtins is a net packet wrapper library for crafting and + * interpreting sniffed packets. + * + * Copyright (C) 2011 Nasel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + * Simple traceroute utility. It will probably miss some hops, since + * it doesn't wait much for hosts to answer. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Tins; + +class Traceroute { +public: + typedef std::map result_type; + + Traceroute(NetworkInterface interface, IPv4Address address) + : iface(interface), addr(address) { } + + result_type trace() { + // ICMPs that aren't sent from us. + Sniffer sniffer( + iface.name(), 500, false, + "ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string() + ); + + PacketSender sender; + // Create our handler + auto handler = make_sniffer_handler(this, &Traceroute::sniff_callback); + // We're running + running = true; + // Start the sniff thread + std::thread sniff_thread( + &Sniffer::sniff_loop, + &sniffer, + handler, + 0 + ); + send_packets(sender); + sniff_thread.join(); + // Clear our results and return what we've found + return std::move(results); + } +private: + typedef std::map ttl_map; + + void send_packets(PacketSender &sender) { + // ICMPs are icmp-requests by default + IP ip(addr, iface.addresses().ip_addr, new ICMP()); + // We'll find at most 10 hops. + for(auto i = 1; i <= 10; ++i) { + // Set this "unique" id + ip.id(i); + // Set the time-to-live option + ip.ttl(i); + + // Critical section + { + std::lock_guard _(lock); + ttls[i] = i; + } + + sender.send(&ip); + // Give him a little time + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + running = false; + sender.send(&ip); + } + + bool sniff_callback(PDU *pdu) { + IP *ip = pdu->find_inner_pdu(); + RawPDU *raw = pdu->find_inner_pdu(); + if(ip && raw) { + ttl_map::const_iterator iter; + IP inner_ip; + // This will fail if its a corrupted packet + try { + // Fetch the IP PDU attached to the ICMP response + inner_ip = IP(raw->payload(), raw->header_size()); + } + catch(std::runtime_error &ex) { + return running; + } + // Critical section + { + std::lock_guard _(lock); + iter = ttls.find(inner_ip.id()); + } + + // It's an actual response + if(iter != ttls.end()) { + // Store it + results[inner_ip.id()] = ip->src_addr(); + } + } + return running; + } + + NetworkInterface iface; + IPv4Address addr; + std::atomic running; + ttl_map ttls; + result_type results; + std::mutex lock; +}; + +int main(int argc, char* argv[]) { + if(argc <= 1 && std::cout << "Usage: " << *argv << " \n") + return 1; + try { + IPv4Address addr((std::string(argv[1]))); + Traceroute tracer(addr, addr); + auto results = tracer.trace(); + if(results.empty()) + std::cout << "No hops found" << std::endl; + else { + std::cout << "Results: " << std::endl; + for(const auto &entry : results) { + std::cout << entry.first << " - " << entry.second << std::endl; + } + } + } + catch(std::runtime_error &ex) { + std::cout << "Error - " << ex.what() << std::endl; + return 2; + } +} diff --git a/include/ipaddress.h b/include/ipaddress.h index 71676e7..2433cfb 100644 --- a/include/ipaddress.h +++ b/include/ipaddress.h @@ -44,7 +44,12 @@ namespace Tins { operator uint32_t() const; operator std::string() const; - bool operator==(const std::string &rhs) const; + std::string to_string() const; + + bool operator==(const IPv4Address &rhs) const { + return ip_addr == rhs.ip_addr; + } + bool operator!=(const std::string &rhs) const { return !(*this == rhs); }