diff --git a/examples/arpspoofing.cpp b/examples/arpspoofing.cpp index d013a46..53e0cc1 100644 --- a/examples/arpspoofing.cpp +++ b/examples/arpspoofing.cpp @@ -74,7 +74,7 @@ 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: [Interface=eth0]\n") + if(argc < 3 && cout << "Usage: " << *argv << " [Interface=eth0]\n") return 1; uint32_t gw, victim, own_ip; uint8_t own_hw[6]; diff --git a/examples/portscan.cpp b/examples/portscan.cpp new file mode 100644 index 0000000..5f9c0d6 --- /dev/null +++ b/examples/portscan.cpp @@ -0,0 +1,116 @@ +/* + * 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 + */ + +#include +#include +#include +#include +#include "ip.h" +#include "tcp.h" +#include "ethernetII.h" +#include "sniffer.h" +#include "utils.h" +#include "packetsender.h" + + +using namespace std; +using namespace Tins; + +struct ThreadData { + string interface; + string ip; +}; + +struct ScanHandler { + bool operator() (PDU *pdu) { + EthernetII *eth = dynamic_cast(pdu); + if(eth) { + IP *ip = dynamic_cast(pdu->inner_pdu()); + if(ip) { + TCP *tcp = dynamic_cast(ip->inner_pdu()); + if(tcp) { + if(tcp->get_flag(TCP::RST)) + cout << "Port: " << tcp->sport() << " closed\n"; + else if(tcp->get_flag(TCP::SYN)) + cout << "Port: " << tcp->sport() << " open\n"; + } + } + } + return true; + } +}; + + +Sniffer *sniffer; + +void send_syns(const string &iface, uint32_t dest_ip, int argc, char *argv[]) { + uint32_t own_ip; + if(!Utils::interface_ip(iface, own_ip) && cout << "Error obtaining interface ip.\n") + return; + PacketSender sender; + TCP *tcp = new TCP(); + IP ip(dest_ip, own_ip, tcp); + tcp->set_flag(TCP::SYN, 1); + while(argc--) { + uint32_t port = atoi(*(argv++)); + tcp->dport(port); + sender.send(&ip); + } +} + +void *thread_proc(void *param) { + ThreadData *data = (ThreadData*)param; + ScanHandler handler; + AbstractSnifferHandler *my_handler = new SnifferHandler(&handler); + sniffer->sniff_loop("tcp and ip src " + data->ip, my_handler); + cout << "Listo\n"; + delete my_handler; + return 0; +} + +int main(int argc, char *argv[]) { + if(argc < 3 && cout << "Usage: " << *argv << " [port2] [port3]\n") + return 1; + uint32_t ip; + try { + ip = Utils::resolve_ip(argv[1]); + } + catch(...) { + cout << "IP address is not valid.\n"; + return 2; + } + string iface = Utils::interface_from_ip(ip); + if(!iface.size() && cout << "Could not locate gateway interface for given ip address\n") + return 3; + sniffer = new Sniffer(iface, 300); + ThreadData data; + data.interface = iface; + data.ip = argv[1]; + pthread_t thread; + pthread_create(&thread, 0, thread_proc, &data); + + send_syns(iface, ip, argc - 2, argv + 2); + + sleep(5); + + pthread_cancel(thread); + delete sniffer; +} diff --git a/include/sniffer.h b/include/sniffer.h index 6f9b3a4..1adfd71 100644 --- a/include/sniffer.h +++ b/include/sniffer.h @@ -1,3 +1,25 @@ +/* + * 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 + */ + + #ifndef __SNIFFER_H #define __SNIFFER_H @@ -71,6 +93,11 @@ namespace Tins { * \param max_packets The maximum amount of packets to sniff. 0 == infinite. */ void sniff_loop(const std::string &filter, AbstractSnifferHandler *cback_handler, uint32_t max_packets = 0); + + /** + * \brief Stops sniffing loops. + */ + void stop_sniff(); private: bool compile_set_filter(const std::string &filter, bpf_program &prog); diff --git a/include/utils.h b/include/utils.h index 55b4318..41da69e 100644 --- a/include/utils.h +++ b/include/utils.h @@ -97,7 +97,8 @@ namespace Tins { */ std::set network_interfaces(); - /** \brief Lookup the ip address of the given interface. + /** + * \brief Lookup the ip address of the given interface. * * If the lookup fails, false will be returned, true otherwise. * \param iface The interface from which to extract the ip address. @@ -105,7 +106,8 @@ namespace Tins { */ bool interface_ip(const std::string &iface, uint32_t &ip); - /** \brief Lookup the hardware address of the given interface. + /** + * \brief Lookup the hardware address of the given interface. * * If the lookup fails, false will be returned, true otherwise. * \param iface The interface from which to extract the hardware address. @@ -114,7 +116,8 @@ namespace Tins { */ bool interface_hwaddr(const std::string &iface, uint8_t *buffer); - /** \brief Lookup the interface identifier. + /** + * \brief Lookup the interface identifier. * * If the lookup fails, false will be returned, true otherwise. * \param iface The interface from which to extract the identifier. @@ -122,7 +125,18 @@ namespace Tins { */ bool interface_id(const std::string &iface, uint32_t &id); - /** \brief Convert 32 bit integer into network byte order. + /** + * \brief Finds the gateway interface matching the given ip. + * + * This function find the interface which would be the gateway + * when sending a packet to the given ip. + * \param ip The ip of the interface we are looking for. + * \return The interface's name. + */ + std::string interface_from_ip(uint32_t ip); + + /** + * \brief Convert 32 bit integer into network byte order. * * \param data The data to convert. */ diff --git a/src/sniffer.cpp b/src/sniffer.cpp index 057f43a..434539d 100644 --- a/src/sniffer.cpp +++ b/src/sniffer.cpp @@ -1,3 +1,25 @@ +/* + * 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 + */ + + #include #include "sniffer.h" #include "ethernetII.h" @@ -54,6 +76,10 @@ Tins::PDU *Tins::Sniffer::next_pdu(const string &filter) { return ret; } +void Tins::Sniffer::stop_sniff() { + pcap_breakloop(handle); +} + void Tins::Sniffer::sniff_loop(const std::string &filter, AbstractSnifferHandler *cback_handler, uint32_t max_packets) { bpf_program prog; if(compile_set_filter(filter, prog)) { diff --git a/src/utils.cpp b/src/utils.cpp index a47453d..295cade 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -76,6 +77,29 @@ struct HWAddressCollector { } }; +bool from_hex(const string &str, uint32_t &result) { + unsigned i(0); + result = 0; + while(i < str.size()) { + uint8_t tmp; + if(str[i] >= 'A' && str[i] <= 'F') + tmp = (str[i] - 'A' + 10); + else if(str[i] >= '0' && str[i] <= '9') + tmp = (str[i] - '0'); + else + return false; + result = (result << 4) | tmp; + i++; + } + return true; +} + +void skip_line(istream &input) { + int c = 0; + while(c != '\n' && input) + c = input.get(); +} + /** \endcond */ uint32_t Tins::Utils::ip_to_int(const string &ip) { @@ -179,6 +203,26 @@ bool Tins::Utils::resolve_hwaddr(const string &iface, uint32_t ip, uint8_t *buff return false; } +string Tins::Utils::interface_from_ip(uint32_t ip) { + ifstream input("/proc/net/route"); + bool match(false); + string iface; + string destination, mask; + uint32_t destination_int, mask_int; + skip_line(input); + while(!match) { + input >> iface >> destination; + for(unsigned i(0); i < 6; ++i) + input >> mask; + from_hex(destination, destination_int); + from_hex(mask, mask_int); + if((ip & mask_int) == destination_int) + return iface; + skip_line(input); + } + return ""; +} + set Tins::Utils::network_interfaces() { InterfaceCollector collector; generic_iface_loop(collector);