summaryrefslogtreecommitdiffstats
path: root/FPEngine.h
diff options
context:
space:
mode:
Diffstat (limited to 'FPEngine.h')
-rw-r--r--FPEngine.h413
1 files changed, 413 insertions, 0 deletions
diff --git a/FPEngine.h b/FPEngine.h
new file mode 100644
index 0000000..e4ce0a1
--- /dev/null
+++ b/FPEngine.h
@@ -0,0 +1,413 @@
+
+/***************************************************************************
+ * FPEngine.h -- Header info for IPv6 OS detection via TCP/IP *
+ * fingerprinting. For more information on how this works in Nmap, see *
+ * http://insecure.org/osdetect/ *
+ * *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap 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. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+/* $Id$ */
+
+#ifndef __FPENGINE_H__
+#define __FPENGINE_H__ 1
+
+#include "nsock.h"
+#include <vector>
+#include "libnetutil/npacket.h"
+
+/* Mention some classes here so we don't have to place the declarations in
+ * the right order (otherwise the compiler complains). */
+class FPHost;
+class FPHost6;
+class FPProbe;
+
+class Target;
+class FingerPrintResultsIPv6;
+struct FingerMatch;
+
+/******************************************************************************
+ * CONSTANT DEFINITIONS *
+ ******************************************************************************/
+
+#define NELEMS(a) (sizeof(a) / sizeof((a)[0]))
+
+#define NUM_FP_PROBES_IPv6_TCP 13
+#define NUM_FP_PROBES_IPv6_ICMPv6 4
+#define NUM_FP_PROBES_IPv6_UDP 1
+/* Total number of IPv6 OS detection probes. */
+#define NUM_FP_PROBES_IPv6 (NUM_FP_PROBES_IPv6_TCP+NUM_FP_PROBES_IPv6_ICMPv6+NUM_FP_PROBES_IPv6_UDP)
+
+/* Even with a successful classification, we may not consider a match good if it
+ is too different from other members of the class. */
+#define FP_NOVELTY_THRESHOLD 15.0
+
+const unsigned int OSDETECT_FLOW_LABEL = 0x12345;
+
+
+
+/* Number of timed probes for IPv6 OS scan. This is, the number of probes that
+ * have specific timing requirements and need to be processed together. This
+ * are the probes that are sent 100ms apart. */
+#define NUM_FP_TIMEDPROBES_IPv6 6
+
+/* Initial congestion window. It is set to the number of timed probes because
+ * hosts need to be able to schedule all of them at once. */
+#define OSSCAN_INITIAL_CWND (NUM_FP_TIMEDPROBES_IPv6)
+
+/* Initial Slow Start threshold. It is set to four times the initial CWND. */
+#define OSSCAN_INITIAL_SSTHRESH (4 * OSSCAN_INITIAL_CWND)
+
+/* Host group size is the number of osscan hosts that are processed in parallel.
+ * Note that this osscan engine always keeps a working group of this many hosts.
+ * in other words, if one host in the group finishes, another is added to it
+ * dynamically. */
+#define OSSCAN_GROUP_SIZE 10
+
+/* Initial retransmission timeout. This is the time we initially wait for a
+ * probe response before retransmitting the original probe. Note that this is
+ * only the initial RTO, used only when no RTT measures have been taken yet.
+ * The actual RTO varies each time we get a response to a probe.
+ * It is set to 3 seconds (3*10^6 usecs) as per RFC 2988. */
+#define OSSCAN_INITIAL_RTO (3*1000000)
+
+
+/******************************************************************************
+ * CLASS DEFINITIONS *
+ ******************************************************************************/
+
+/* This class handles the access to the network. It handles packet transmission
+ * scheduling, packet capture and congestion control. Every FPHost should be
+ * linked to the same instance of this class, so the access to the network can
+ * be managed globally (for the whole OS detection process). */
+class FPNetworkControl {
+
+ private:
+ nsock_pool nsp; /* Nsock pool. */
+ nsock_iod pcap_nsi; /* Nsock Pcap descriptor. */
+ nsock_event_id pcap_ev_id; /* Last pcap read event that was scheduled. */
+ bool first_pcap_scheduled; /* True if we scheduled the first pcap read event. */
+ bool nsock_init; /* True if the nsock pool has been initialized. */
+ int rawsd; /* Raw socket. */
+ std::vector<FPHost *> callers; /* List of users of this instance (used for callbacks).*/
+ int probes_sent; /* Number of unique probes sent (not retransmissions). */
+ int responses_recv; /* Number of probe responses received. */
+ int probes_timedout; /* Number of probes that timeout after all retransms. */
+ float cc_cwnd; /* Current congestion window. */
+ float cc_ssthresh; /* Current Slow Start threshold. */
+
+ int cc_init();
+ int cc_update_sent(int pkts);
+ int cc_report_drop();
+ int cc_update_received();
+
+ public:
+ FPNetworkControl();
+ ~FPNetworkControl();
+ void init(const char *ifname, devtype iftype);
+ int register_caller(FPHost *newcaller);
+ int unregister_caller(FPHost *oldcaller);
+ int setup_sniffer(const char *iface, const char *bfp_filter);
+ void handle_events();
+ int scheduleProbe(FPProbe *pkt, int in_msecs_time);
+ void probe_transmission_handler(nsock_pool nsp, nsock_event nse, void *arg);
+ void response_reception_handler(nsock_pool nsp, nsock_event nse, void *arg);
+ bool request_slots(size_t num_packets);
+ int cc_report_final_timeout();
+
+};
+
+/* +-----------+
+ | FPEngine |
+ +-----------+
+ | |
+ +-----+-----+
+ |
+ +-------+-------+
+ | |
+ | |
+ +-----------+ +-----------+
+ | FPEngine4 | | FPEngine6 |
+ +-----------+ +-----------+
+ | | | |
+ +-----------+ +-----------+ */
+/* This class is the generic fingerprinting engine. */
+class FPEngine {
+
+ protected:
+ size_t osgroup_size;
+
+ public:
+ FPEngine();
+ virtual ~FPEngine();
+ void reset();
+ virtual int os_scan(std::vector<Target *> &Targets) = 0;
+ const char *bpf_filter(std::vector<Target *> &Targets);
+
+};
+
+
+/* This class handles IPv6 OS fingerprinting. Using it is very simple, just
+ * instance it and then call os_scan() with the list of IPv6 targets to
+ * fingerprint. If everything goes well, the internal state of the supplied
+ * target objects will be modified to reflect the results of the fingerprinting
+ * process. */
+class FPEngine6 : public FPEngine {
+
+ private:
+ std::vector<FPHost6 *> fphosts; /* Information about each target to fingerprint */
+
+ public:
+ FPEngine6();
+ ~FPEngine6();
+ void reset();
+ int os_scan(std::vector<Target *> &Targets);
+
+};
+
+
+/* +----------+
+ | FPPacket |
+ +----------+
+ | |
+ +-----+----+
+ |
+ |
+ +-----------+
+ | FPProbe |
+ +-----------+
+ | |
+ +-----+-----+ */
+/* This class represents a generic packet for the OS fingerprinting process */
+class FPPacket {
+
+ protected:
+ PacketElement *pkt; /* Actual packet associated with this FPPacket */
+ bool link_eth; /* Ethernet layer required? */
+ struct eth_nfo eth_hdr; /* Eth info, valid when this->link_eth==true */
+ struct timeval pkt_time; /* Time at which the packet was sent or received */
+
+ int resetTime();
+ void __reset();
+
+ public:
+ FPPacket();
+ ~FPPacket();
+ int setTime(const struct timeval *tv = NULL);
+ struct timeval getTime() const;
+ int setPacket(PacketElement *pkt);
+ int setEthernet(const u8 *src_mac, const u8 *dst_mac, const char *devname);
+ const struct eth_nfo *getEthernet() const;
+ const PacketElement *getPacket() const;
+ size_t getLength() const;
+ u8 *getPacketBuffer(size_t *pkt_len) const;
+ bool is_set() const;
+
+};
+
+/* This class represents a generic OS fingerprinting probe. In other words, it
+ * represents a network packet that Nmap sends to a target in order to
+ * obtain information about the target's TCP/IP stack. */
+class FPProbe : public FPPacket {
+
+ private:
+ const char *probe_id;
+ int probe_no;
+ int retransmissions;
+ int times_replied;
+ bool failed;
+ bool timed;
+
+ public:
+ FPHost *host;
+
+ FPProbe();
+ ~FPProbe();
+ void reset();
+ bool isResponse(PacketElement *rcvd);
+ int setProbeID(const char *id);
+ const char *getProbeID() const;
+ int getRetransmissions() const;
+ int incrementRetransmissions();
+ int getReplies() const;
+ int incrementReplies();
+ int setTimeSent();
+ int resetTimeSent();
+ struct timeval getTimeSent() const;
+ bool probeFailed() const;
+ int setFailed();
+ bool isTimed() const;
+ int setTimed();
+ int changeSourceAddress(struct in6_addr *addr);
+
+};
+
+/* This class represents a generic received packet. */
+struct FPResponse {
+ const char *probe_id;
+ u8 *buf;
+ size_t len;
+ struct timeval senttime, rcvdtime;
+
+ FPResponse(const char *probe_id, const u8 *buf, size_t len,
+ struct timeval senttime, struct timeval rcvdtime);
+ ~FPResponse();
+};
+
+
+/* +-----------+
+ | FPHost |
+ +-----------+
+ | |
+ +-----+-----+
+ |
+ +-------+-------+
+ | |
+ | |
+ +-----------+ +-----------+
+ | FPHost4 | | FPHost6 |
+ +-----------+ +-----------+
+ | | | |
+ +-----------+ +-----------+ */
+/* This class represents a generic host to be fingerprinted. */
+class FPHost {
+
+ protected:
+ unsigned int total_probes; /* Number of different OS scan probes to be sent to targets */
+ unsigned int timed_probes; /* Number of probes that have specific timing requirements */
+ unsigned int probes_sent; /* Number of FPProbes sent (not counting retransmissions) */
+ unsigned int probes_answered; /* Number of FPResponses received */
+ unsigned int probes_unanswered; /* Number of FPProbes that timedout (after all retransmissions) */
+ bool incomplete_fp; /* True if we were unable to send all attempted probes */
+ bool detection_done; /* True if the OS detection process has been completed. */
+ bool timedprobes_sent; /* True if the probes that have timing requirements were sent */
+ Target *target_host; /* Info about the host to fingerprint */
+ FPNetworkControl *netctl; /* Link to the network manager (for scheduling and CC) */
+ bool netctl_registered; /* True if we are already registered in the network controller */
+ u32 tcpSeqBase; /* Base for sequence numbers set in outgoing probes */
+ int open_port_tcp; /* Open TCP port to be used in the OS detection probes */
+ int closed_port_tcp; /* Closed TCP port for the OS detection probes. */
+ int closed_port_udp; /* Closed UDP port. */
+ int tcp_port_base; /* Send TCP probes starting with this port number. */
+ int udp_port_base; /* Send UDP probes with this port number. */
+ u16 icmp_seq_counter; /* ICMPv6 sequence number counter. */
+ int rto; /* Retransmission timeout for the host */
+ int rttvar; /* Round-Trip Time variation (RFC 2988) */
+ int srtt; /* Smoothed Round-Trip Time (RFC 2988) */
+
+ void __reset();
+ int update_RTO(int measured_rtt_usecs, bool retransmission);
+ int choose_osscan_ports();
+
+ private:
+ virtual int build_probe_list() = 0;
+
+ public:
+ struct timeval begin_time;
+
+ FPHost();
+ virtual ~FPHost();
+ virtual bool done() = 0;
+ virtual int schedule() = 0;
+ virtual int callback(const u8 *pkt, size_t pkt_len, const struct timeval *tv) = 0;
+ const struct sockaddr_storage *getTargetAddress();
+ void fail_one_probe();
+
+};
+
+/* This class represents IPv6 hosts to be fingerprinted. The class performs
+ * OS detection asynchronously. To use it, schedule() must be called at regular
+ * intervals until done() returns true. After that, status() will indicate
+ * whether the host was successfully matched with a particular OS or not. */
+class FPHost6 : public FPHost {
+
+ private:
+ FPProbe fp_probes[NUM_FP_PROBES_IPv6]; /* OS detection probes to be sent.*/
+ FPResponse *fp_responses[NUM_FP_PROBES_IPv6]; /* Received responses. */
+ FPResponse *aux_resp[NUM_FP_TIMEDPROBES_IPv6]; /* Aux vector for timed responses */
+
+ int build_probe_list();
+ int set_done_and_wrap_up();
+
+ public:
+ FPHost6(Target *tgt, FPNetworkControl *fpnc);
+ ~FPHost6();
+ void reset();
+ void init(Target *tgt, FPNetworkControl *fpnc);
+ void finish();
+ bool done();
+ int schedule();
+ int callback(const u8 *pkt, size_t pkt_len, const struct timeval *tv);
+ const FPProbe *getProbe(const char *id);
+ const FPResponse *getResponse(const char *id);
+
+ void fill_FPR(FingerPrintResultsIPv6 *FPR);
+
+};
+
+
+/******************************************************************************
+ * Nsock handler wrappers. *
+ ******************************************************************************/
+
+void probe_transmission_handler_wrapper(nsock_pool nsp, nsock_event nse, void *arg);
+void response_reception_handler_wrapper(nsock_pool nsp, nsock_event nse, void *arg);
+
+
+std::vector<FingerMatch> load_fp_matches();
+
+
+#endif /* __FPENGINE_H__ */
+