From 8fcfd571250ea3659fe7b6fef4799ca10e481cd8 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Sat, 20 Sep 2014 15:11:39 -0300 Subject: [PATCH] Fixed portscan example. --- examples/portscan.cpp | 116 ++++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 38 deletions(-) diff --git a/examples/portscan.cpp b/examples/portscan.cpp index af8550d..e2fb687 100644 --- a/examples/portscan.cpp +++ b/examples/portscan.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -49,27 +50,88 @@ using namespace Tins; typedef std::pair sniffer_data; +class Scanner { +public: + Scanner(const NetworkInterface& interface, const IPv4Address& address, + const vector& ports); + + void run(); +private: + void send_syns(const NetworkInterface &iface, IPv4Address dest_ip); + bool callback(PDU &pdu); + static void *thread_proc(void *param); + void launch_sniffer(); + + NetworkInterface iface; + IPv4Address host_to_scan; + set ports_to_scan; + Sniffer sniffer; +}; + +Scanner::Scanner(const NetworkInterface& interface, const IPv4Address& address, + const vector& ports) +: iface(interface), host_to_scan(address), sniffer(interface.name()) +{ + sniffer.set_filter( + "tcp and ip src " + address.to_string() + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0" + ); + for(size_t i = 0; i < ports.size(); ++i) { + ports_to_scan.insert(atoi(ports[i].c_str())); + } +} + +void *Scanner::thread_proc(void *param) { + Scanner *data = (Scanner*)param; + data->launch_sniffer(); + return 0; +} + +void Scanner::launch_sniffer() +{ + sniffer.sniff_loop(make_sniffer_handler(this, &Scanner::callback)); +} /* Our scan handler. This will receive SYNs and RSTs and inform us * the scanned port's status. */ -bool handler(PDU &pdu) { +bool Scanner::callback(PDU &pdu) +{ + // Find the layers we want. + const IP &ip = pdu.rfind_pdu(); const TCP &tcp = pdu.rfind_pdu(); - // Ok, it's a TCP PDU. Is RST flag on? Then port is closed. - if(tcp.get_flag(TCP::RST)) { - // This indicates we should stop sniffing. - if(tcp.get_flag(TCP::SYN)) - return false; - cout << "Port: " << setw(5) << tcp.sport() << " closed\n"; + // Check if the host that we're scanning sent this packet and + // the source port is one of those that we scanned. + if(ip.src_addr() == host_to_scan && ports_to_scan.count(tcp.sport()) == 1) { + // Ok, it's a TCP PDU. Is RST flag on? Then port is closed. + if(tcp.get_flag(TCP::RST)) { + // This indicates we should stop sniffing. + if(tcp.get_flag(TCP::SYN)) + return false; + cout << "Port: " << setw(5) << tcp.sport() << " closed\n"; + } + // Is SYN flag on? Then port is open! + else if(tcp.flags() == (TCP::SYN | TCP::ACK)) { + cout << "Port: " << setw(5) << tcp.sport() << " open\n"; + } } - // Is SYN flag on? Then port is open! - else if(tcp.flags() == (TCP::SYN | TCP::ACK)) - cout << "Port: " << setw(5) << tcp.sport() << " open\n"; return true; } +void Scanner::run() +{ + pthread_t thread; + // Launch our sniff thread. + pthread_create(&thread, 0, &Scanner::thread_proc, this); + // Start sending SYNs to port. + send_syns(iface, host_to_scan); + + // Wait for our sniffer. + void *dummy; + pthread_join(thread, &dummy); +} + // Send syns to the given ip address, using the destination ports provided. -void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector &ips) { +void Scanner::send_syns(const NetworkInterface &iface, IPv4Address dest_ip) { // Retrieve the addresses. NetworkInterface::Info info = iface.addresses(); PacketSender sender; @@ -82,9 +144,9 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector< // Just some random port. tcp.sport(1337); cout << "Sending SYNs..." << endl; - for(vector::const_iterator it = ips.begin(); it != ips.end(); ++it) { + for(set::const_iterator it = ports_to_scan.begin(); it != ports_to_scan.end(); ++it) { // Set the new port and send the packet! - tcp.dport(atoi(it->c_str())); + tcp.dport(*it); sender.send(ip); } // Wait 1 second. @@ -93,6 +155,7 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector< * by our function, which will in turn return false. */ tcp.set_flag(TCP::RST, 1); + tcp.sport(*ports_to_scan.begin()); // Pretend we're the scanned host... ip.src_addr(dest_ip); // We use an ethernet pdu, otherwise the kernel will drop it. @@ -100,40 +163,17 @@ void send_syns(const NetworkInterface &iface, IPv4Address dest_ip, const vector< sender.send(eth, iface); } -void *thread_proc(void *param) { - // IP address is our parameter. - sniffer_data *data = (sniffer_data*)param; - Sniffer *sniffer = data->first; - sniffer->set_filter("tcp and ip src " + data->second + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0"); - // Sniff loop. Only sniff TCP PDUs comming from the given IP and have either RST or SYN flag on. - sniffer->sniff_loop(handler); - return 0; -} - void scan(int argc, char *argv[]) { IPv4Address ip(argv[1]); // Resolve the interface which will be our gateway NetworkInterface iface(ip); cout << "Sniffing on interface: " << iface.name() << endl; - - // 300 bytes are enough to receive SYNs and RSTs. - SnifferConfiguration config; - config.set_snap_len(300); - Sniffer sniffer(iface.name(), config); - sniffer_data data(&sniffer, argv[1]); - pthread_t thread; - // Launch our sniff thread. - pthread_create(&thread, 0, thread_proc, &data); // Consume arguments argv += 2; argc -= 2; - // Start sending SYNs to port. - send_syns(iface, ip, vector(argv, argv + (argc))); - - // Wait for our sniffer. - void *dummy; - pthread_join(thread, &dummy); + Scanner scanner(iface, ip, vector(argv, argv + (argc))); + scanner.run(); } int main(int argc, char *argv[]) {