diff --git a/osscan2.cc b/osscan2.cc index 4e160c00a..7f86bd03d 100644 --- a/osscan2.cc +++ b/osscan2.cc @@ -146,338 +146,12 @@ u16 prbWindowSz[] = { 1, 63, 4, 4, 16, 512, 3, 128, 256, 1024, 31337, 32768, 655 */ static struct timeval now; -class OFProbe; -class HostOsScanStats; -class HostOsScan; -class HostOsScanInfo; -class OsScanInfo; + /* Global to store performance info */ os_scan_performance_vars_t perf; -class OFProbe -{ -public: - OFProbe(); - - /* The literal string for the current probe type. */ - const char *typestr(); - - /* Type of the probe: for what os fingerprinting test? */ - OFProbeType type; - - /* Subid of this probe to separate different tcp/udp/icmp. */ - int subid; - - int tryno; /* Try (retransmission) number of this probe */ - - /* A packet may be timedout for a while before being retransmitted - due to packet sending rate limitations */ - bool retransmitted; - - struct timeval sent; - - /* Time the previous probe was sent, if this is a retransmit (tryno > 0) */ - struct timeval prevSent; -}; - -/* - * HostOsScanStats stores the status for a host being scanned - * in a scan round. - */ -class HostOsScanStats -{ - friend class HostOsScan; -public: - HostOsScanStats(Target *t); - ~HostOsScanStats(); - void initScanStats(); - - struct eth_nfo *fill_eth_nfo(struct eth_nfo *eth, eth_t *ethsd) const; - - void addNewProbe(OFProbeType type, int subid); - void removeActiveProbe(list::iterator probeI); - -/* Get an active probe from active probe list identified by probe type - and subid. returns probesActive.end() if there isn't one. */ - list::iterator getActiveProbe(OFProbeType type, int subid); - void moveProbeToActiveList(list::iterator probeI); - void moveProbeToUnSendList(list::iterator probeI); - unsigned int numProbesToSend() {return probesToSend.size();} - unsigned int numProbesActive() {return probesActive.size();} - - FingerPrint *getFP() {return FP;} - - Target *target; /* the Target */ - struct seq_info si; - struct ipid_info ipid; - - /* - * distance, distance_guess: hop count between us and the target. - * - * Possible values of distance: - * 0: when scan self; - * 1: when scan a target on the same network segment; - * >=1: not self, not same network and nmap has got the icmp reply to the U1 probe. - * -1: none of the above situations. - * - * Possible values of distance_guess: - * -1: nmap fails to get a valid ttl by all kinds of probes. - * >=1: a guessing value based on ttl. - */ - int distance; - int distance_guess; - - /* Returns the amount of time taken between sending 1st tseq probe - and the last one. Zero is - returned if we didn't send the tseq probes because there was no - open tcp port */ - double timingRatio(); - -private: - /* Ports of the targets used in os fingerprinting. */ - int openTCPPort, closedTCPPort, closedUDPPort; - - /* Probe list used in tests. At first, probes are linked in - * probesToSend; when a probe is sent, it will be removed from - * probesToSend and appended to probesActive. If any probes in - * probesActive are timedout, they will be moved to probesToSend and - * sent again till expired. - */ - list probesToSend; - list probesActive; - - /* A record of total number of probes that have been sent to this - * host, including restranmited ones. */ - unsigned int num_probes_sent; - /* Delay between two probes. */ - unsigned int sendDelayMs; - /* When the last probe is sent. */ - struct timeval lastProbeSent; - - osscan_timing_vals_t timing; - - /* - * Fingerprint of this target. When a scan is completed, it'll - * finally be passed to hs->target->FPR->FPs[x]. - */ - FingerPrint *FP; - FingerTest *FPtests[NUM_FPTESTS]; -#define FP_TSeq FPtests[0] -#define FP_TOps FPtests[1] -#define FP_TWin FPtests[2] -#define FP_TEcn FPtests[3] -#define FP_T1_7_OFF 4 -#define FP_T1 FPtests[4] -#define FP_T2 FPtests[5] -#define FP_T3 FPtests[6] -#define FP_T4 FPtests[7] -#define FP_T5 FPtests[8] -#define FP_T6 FPtests[9] -#define FP_T7 FPtests[10] -#define FP_TUdp FPtests[11] -#define FP_TIcmp FPtests[12] - struct AVal *TOps_AVs[6]; /* 6 AVs of TOps */ - struct AVal *TWin_AVs[6]; /* 6 AVs of TWin */ - - /* The following are variables to store temporary results - * during the os fingerprinting process of this host. - */ - u16 lastipid; - struct timeval seq_send_times[NUM_SEQ_SAMPLES]; - - int TWinReplyNum; /* how many TWin replies are received. */ - int TOpsReplyNum; /* how many TOps replies are received. Actually it is the same with TOpsReplyNum. */ - - struct ip *icmpEchoReply; /* To store one of the two icmp replies */ - int storedIcmpReply; /* Which one of the two icmp replies is stored? */ - - struct udpprobeinfo upi; /* info of the udp probe we sent */ -}; - -/* These are statistics for the whole group of Targets */ -class ScanStats { -public: - ScanStats(); - - /* Returns true if the system says that sending is OK. */ - bool sendOK(); - - osscan_timing_vals_t timing; - struct timeout_info to; /* rtt/timeout info */ - - /* Total number of active probes */ - int num_probes_active; - /* Number of probes sent in total. */ - int num_probes_sent; - int num_probes_sent_at_last_wait; -}; - -/* - * HostOsScan does the scan job, setting and using the status of a host in - * the host's HostOsScanStats. - */ -class HostOsScan -{ -public: - HostOsScan(Target *t); /* OsScan need a target to set eth stuffs */ - ~HostOsScan(); - - pcap_t *pd; - ScanStats *stats; - - /* (Re)Initial the parameters that will be used during the scan.*/ - void reInitScanSystem(); - - void buildSeqProbeList(HostOsScanStats *hss); - void updateActiveSeqProbes(HostOsScanStats *hss); - - void buildTUIProbeList(HostOsScanStats *hss); - void updateActiveTUIProbes(HostOsScanStats *hss); - - /* send the next probe in the probe list of the hss */ - void sendNextProbe(HostOsScanStats *hss); - - /* Process one response. - * If the response is useful, return true. */ - bool processResp(HostOsScanStats *hss, struct ip *ip, unsigned int len, struct timeval *rcvdtime); - - /* Make up the fingerprint. */ - void makeFP(HostOsScanStats *hss); - - /* Check whether the host is sendok. If not, fill _when_ with the - * time when it will be sendOK and return false; else, fill it with - * now and return true. - */ - bool hostSendOK(HostOsScanStats *hss, struct timeval *when); - - /* Check whether it is ok to send the next seq probe to the host. If - * not, fill _when_ with the time when it will be sendOK and return - * false; else, fill it with now and return true. - */ - bool hostSeqSendOK(HostOsScanStats *hss, struct timeval *when); - - - /* How long I am currently willing to wait for a probe response - before considering it timed out. Uses the host values from - target if they are available, otherwise from gstats. Results - returned in MICROseconds. */ - unsigned long timeProbeTimeout(HostOsScanStats *hss); - - /* If there are pending probe timeouts, fills in when with the time - * of the earliest one and returns true. Otherwise returns false - * and puts now in when. - */ - bool nextTimeout(HostOsScanStats *hss, struct timeval *when); - - /* Adjust various timing variables based on pcket receipt. */ - void adjust_times(HostOsScanStats *hss, OFProbe *probe, struct timeval *rcvdtime); - -private: - /* Probe send functions. */ - void sendTSeqProbe(HostOsScanStats *hss, int probeNo); - void sendTOpsProbe(HostOsScanStats *hss, int probeNo); - void sendTEcnProbe(HostOsScanStats *hss); - void sendT1_7Probe(HostOsScanStats *hss, int probeNo); - void sendTUdpProbe(HostOsScanStats *hss, int probeNo); - void sendTIcmpProbe(HostOsScanStats *hss, int probeNo); - /* Response process functions. */ - bool processTSeqResp(HostOsScanStats *hss, struct ip *ip, int replyNo); - bool processTOpsResp(HostOsScanStats *hss, struct tcp_hdr *tcp, int replyNo); - bool processTWinResp(HostOsScanStats *hss, struct tcp_hdr *tcp, int replyNo); - bool processTEcnResp(HostOsScanStats *hss, struct ip *ip); - bool processT1_7Resp(HostOsScanStats *hss, struct ip *ip, int replyNo); - bool processTUdpResp(HostOsScanStats *hss, struct ip *ip); - bool processTIcmpResp(HostOsScanStats *hss, struct ip *ip, int replyNo); - - /* Generic sending functions used by the above probe functions. */ - int send_tcp_probe(HostOsScanStats *hss, - int ttl, bool df, u8* ipopt, int ipoptlen, - u16 sport, u16 dport, u32 seq, u32 ack, - u8 reserved, u8 flags, u16 window, u16 urp, - u8 *options, int optlen, - char *data, u16 datalen); - int send_icmp_echo_probe(HostOsScanStats *hss, - u8 tos, bool df, u8 pcode, - unsigned short id, u16 seq, u16 datalen); - int send_closedudp_probe(HostOsScanStats *hss, - int ttl, u16 sport, u16 dport); - - void makeTSeqFP(HostOsScanStats *hss); - void makeTOpsFP(HostOsScanStats *hss); - void makeTWinFP(HostOsScanStats *hss); - - bool get_tcpopt_string(struct tcp_hdr *tcp, int mss, char *result, int maxlen); - - int rawsd; /* raw socket descriptor */ - eth_t *ethsd; /* Ethernet handle */ - - unsigned int tcpSeqBase, tcpAck; /* Seq&Ack value used in TCP probes */ - int tcpMss; /* tcp Mss value used in TCP probes */ - int udpttl; /* ttl value used in udp probe. */ - unsigned short icmpEchoId, icmpEchoSeq; /* Icmp Echo Id&Seq value used in ICMP probes*/ - - /* Source port number in TCP probes. Different probe will use - * arbitrary offset value of it. */ - int tcpPortBase; - int udpPortBase; -}; - -/* - * The overall os scan information of a host: - * - Fingerprints gotten from every scan round; - * - Maching results of these fingerprints. - * - Is it timeout/completed? - * - ... - */ -class HostOsScanInfo -{ -public: - HostOsScanInfo(Target *t, OsScanInfo *OSI); - ~HostOsScanInfo(); - - Target *target; /* the Target */ - OsScanInfo *OSI; /* The OSI which contains this HostOsScanInfo */ - FingerPrint **FPs; /* Fingerprints of the host */ - FingerPrintResults *FP_matches; /* Fingerprint-matching results */ - bool timedOut; - bool isCompleted; - HostOsScanStats *hss; /* Scan status of the host in one scan round */ -}; - -/* - * Maintain a link of incomplete HostOsScanInfo. - */ -class OsScanInfo -{ -public: - OsScanInfo(vector &Targets); - ~OsScanInfo(); - - /* If you remove from this, you had better adjust nextI too (or call - resetHostIterator() afterward). Don't let this list get empty, - then add to it again, or you may mess up nextI (I'm not sure) */ - list incompleteHosts; - float starttime; - - unsigned int numIncompleteHosts() {return incompleteHosts.size();} - HostOsScanInfo *findIncompleteHost(struct sockaddr_storage *ss); - /* A circular buffer of the incompleteHosts. nextIncompleteHost() gives - the next one. The first time it is called, it will give the - first host in the list. If incompleteHosts is empty, returns - NULL. */ - HostOsScanInfo *nextIncompleteHost(); - /* Resets the host iterator used with nextIncompleteHost() to the - beginning. If you remove a host from incompleteHosts, call this - right afterward */ - void resetHostIterator() { nextI = incompleteHosts.begin(); } - - int removeCompletedHosts(); -private: - unsigned int numInitialTargets; - list::iterator nextI; -}; OFProbe::OFProbe() { diff --git a/osscan2.h b/osscan2.h index fa6ed3931..79165167c 100644 --- a/osscan2.h +++ b/osscan2.h @@ -98,8 +98,10 @@ #include "global_structures.h" #include "nbase.h" #include - +#include +#include "Target.h" class Target; +using namespace std; /****************************************************************************** @@ -195,5 +197,342 @@ void os_scan2(std::vector &Targets); int get_initial_ttl_guess(u8 ttl); int get_ipid_sequence(int numSamples, int *ipids, int islocalhost); + +/****************************************************************************** + * CLASS DEFINITIONS * + ******************************************************************************/ +class OFProbe; +class HostOsScanStats; +class HostOsScan; +class HostOsScanInfo; +class OsScanInfo; + +class OFProbe +{ +public: + OFProbe(); + + /* The literal string for the current probe type. */ + const char *typestr(); + + /* Type of the probe: for what os fingerprinting test? */ + OFProbeType type; + + /* Subid of this probe to separate different tcp/udp/icmp. */ + int subid; + + int tryno; /* Try (retransmission) number of this probe */ + + /* A packet may be timedout for a while before being retransmitted + due to packet sending rate limitations */ + bool retransmitted; + + struct timeval sent; + + /* Time the previous probe was sent, if this is a retransmit (tryno > 0) */ + struct timeval prevSent; +}; + +/* + * HostOsScanStats stores the status for a host being scanned + * in a scan round. + */ +class HostOsScanStats +{ + friend class HostOsScan; +public: + HostOsScanStats(Target *t); + ~HostOsScanStats(); + void initScanStats(); + + struct eth_nfo *fill_eth_nfo(struct eth_nfo *eth, eth_t *ethsd) const; + + void addNewProbe(OFProbeType type, int subid); + void removeActiveProbe(list::iterator probeI); + +/* Get an active probe from active probe list identified by probe type + and subid. returns probesActive.end() if there isn't one. */ + list::iterator getActiveProbe(OFProbeType type, int subid); + void moveProbeToActiveList(list::iterator probeI); + void moveProbeToUnSendList(list::iterator probeI); + unsigned int numProbesToSend() {return probesToSend.size();} + unsigned int numProbesActive() {return probesActive.size();} + + FingerPrint *getFP() {return FP;} + + Target *target; /* the Target */ + struct seq_info si; + struct ipid_info ipid; + + /* + * distance, distance_guess: hop count between us and the target. + * + * Possible values of distance: + * 0: when scan self; + * 1: when scan a target on the same network segment; + * >=1: not self, not same network and nmap has got the icmp reply to the U1 probe. + * -1: none of the above situations. + * + * Possible values of distance_guess: + * -1: nmap fails to get a valid ttl by all kinds of probes. + * >=1: a guessing value based on ttl. + */ + int distance; + int distance_guess; + + /* Returns the amount of time taken between sending 1st tseq probe + and the last one. Zero is + returned if we didn't send the tseq probes because there was no + open tcp port */ + double timingRatio(); + +private: + /* Ports of the targets used in os fingerprinting. */ + int openTCPPort, closedTCPPort, closedUDPPort; + + /* Probe list used in tests. At first, probes are linked in + * probesToSend; when a probe is sent, it will be removed from + * probesToSend and appended to probesActive. If any probes in + * probesActive are timedout, they will be moved to probesToSend and + * sent again till expired. + */ + list probesToSend; + list probesActive; + + /* A record of total number of probes that have been sent to this + * host, including restranmited ones. */ + unsigned int num_probes_sent; + /* Delay between two probes. */ + unsigned int sendDelayMs; + /* When the last probe is sent. */ + struct timeval lastProbeSent; + + osscan_timing_vals_t timing; + + /* + * Fingerprint of this target. When a scan is completed, it'll + * finally be passed to hs->target->FPR->FPs[x]. + */ + FingerPrint *FP; + FingerTest *FPtests[NUM_FPTESTS]; +#define FP_TSeq FPtests[0] +#define FP_TOps FPtests[1] +#define FP_TWin FPtests[2] +#define FP_TEcn FPtests[3] +#define FP_T1_7_OFF 4 +#define FP_T1 FPtests[4] +#define FP_T2 FPtests[5] +#define FP_T3 FPtests[6] +#define FP_T4 FPtests[7] +#define FP_T5 FPtests[8] +#define FP_T6 FPtests[9] +#define FP_T7 FPtests[10] +#define FP_TUdp FPtests[11] +#define FP_TIcmp FPtests[12] + struct AVal *TOps_AVs[6]; /* 6 AVs of TOps */ + struct AVal *TWin_AVs[6]; /* 6 AVs of TWin */ + + /* The following are variables to store temporary results + * during the os fingerprinting process of this host. + */ + u16 lastipid; + struct timeval seq_send_times[NUM_SEQ_SAMPLES]; + + int TWinReplyNum; /* how many TWin replies are received. */ + int TOpsReplyNum; /* how many TOps replies are received. Actually it is the same with TOpsReplyNum. */ + + struct ip *icmpEchoReply; /* To store one of the two icmp replies */ + int storedIcmpReply; /* Which one of the two icmp replies is stored? */ + + struct udpprobeinfo upi; /* info of the udp probe we sent */ +}; + +/* These are statistics for the whole group of Targets */ +class ScanStats { +public: + ScanStats(); + + /* Returns true if the system says that sending is OK. */ + bool sendOK(); + + osscan_timing_vals_t timing; + struct timeout_info to; /* rtt/timeout info */ + + /* Total number of active probes */ + int num_probes_active; + /* Number of probes sent in total. */ + int num_probes_sent; + int num_probes_sent_at_last_wait; +}; + +/* + * HostOsScan does the scan job, setting and using the status of a host in + * the host's HostOsScanStats. + */ +class HostOsScan +{ +public: + HostOsScan(Target *t); /* OsScan need a target to set eth stuffs */ + ~HostOsScan(); + + pcap_t *pd; + ScanStats *stats; + + /* (Re)Initial the parameters that will be used during the scan.*/ + void reInitScanSystem(); + + void buildSeqProbeList(HostOsScanStats *hss); + void updateActiveSeqProbes(HostOsScanStats *hss); + + void buildTUIProbeList(HostOsScanStats *hss); + void updateActiveTUIProbes(HostOsScanStats *hss); + + /* send the next probe in the probe list of the hss */ + void sendNextProbe(HostOsScanStats *hss); + + /* Process one response. + * If the response is useful, return true. */ + bool processResp(HostOsScanStats *hss, struct ip *ip, unsigned int len, struct timeval *rcvdtime); + + /* Make up the fingerprint. */ + void makeFP(HostOsScanStats *hss); + + /* Check whether the host is sendok. If not, fill _when_ with the + * time when it will be sendOK and return false; else, fill it with + * now and return true. + */ + bool hostSendOK(HostOsScanStats *hss, struct timeval *when); + + /* Check whether it is ok to send the next seq probe to the host. If + * not, fill _when_ with the time when it will be sendOK and return + * false; else, fill it with now and return true. + */ + bool hostSeqSendOK(HostOsScanStats *hss, struct timeval *when); + + + /* How long I am currently willing to wait for a probe response + before considering it timed out. Uses the host values from + target if they are available, otherwise from gstats. Results + returned in MICROseconds. */ + unsigned long timeProbeTimeout(HostOsScanStats *hss); + + /* If there are pending probe timeouts, fills in when with the time + * of the earliest one and returns true. Otherwise returns false + * and puts now in when. + */ + bool nextTimeout(HostOsScanStats *hss, struct timeval *when); + + /* Adjust various timing variables based on pcket receipt. */ + void adjust_times(HostOsScanStats *hss, OFProbe *probe, struct timeval *rcvdtime); + +private: + /* Probe send functions. */ + void sendTSeqProbe(HostOsScanStats *hss, int probeNo); + void sendTOpsProbe(HostOsScanStats *hss, int probeNo); + void sendTEcnProbe(HostOsScanStats *hss); + void sendT1_7Probe(HostOsScanStats *hss, int probeNo); + void sendTUdpProbe(HostOsScanStats *hss, int probeNo); + void sendTIcmpProbe(HostOsScanStats *hss, int probeNo); + /* Response process functions. */ + bool processTSeqResp(HostOsScanStats *hss, struct ip *ip, int replyNo); + bool processTOpsResp(HostOsScanStats *hss, struct tcp_hdr *tcp, int replyNo); + bool processTWinResp(HostOsScanStats *hss, struct tcp_hdr *tcp, int replyNo); + bool processTEcnResp(HostOsScanStats *hss, struct ip *ip); + bool processT1_7Resp(HostOsScanStats *hss, struct ip *ip, int replyNo); + bool processTUdpResp(HostOsScanStats *hss, struct ip *ip); + bool processTIcmpResp(HostOsScanStats *hss, struct ip *ip, int replyNo); + + /* Generic sending functions used by the above probe functions. */ + int send_tcp_probe(HostOsScanStats *hss, + int ttl, bool df, u8* ipopt, int ipoptlen, + u16 sport, u16 dport, u32 seq, u32 ack, + u8 reserved, u8 flags, u16 window, u16 urp, + u8 *options, int optlen, + char *data, u16 datalen); + int send_icmp_echo_probe(HostOsScanStats *hss, + u8 tos, bool df, u8 pcode, + unsigned short id, u16 seq, u16 datalen); + int send_closedudp_probe(HostOsScanStats *hss, + int ttl, u16 sport, u16 dport); + + void makeTSeqFP(HostOsScanStats *hss); + void makeTOpsFP(HostOsScanStats *hss); + void makeTWinFP(HostOsScanStats *hss); + + bool get_tcpopt_string(struct tcp_hdr *tcp, int mss, char *result, int maxlen); + + int rawsd; /* raw socket descriptor */ + eth_t *ethsd; /* Ethernet handle */ + + unsigned int tcpSeqBase, tcpAck; /* Seq&Ack value used in TCP probes */ + int tcpMss; /* tcp Mss value used in TCP probes */ + int udpttl; /* ttl value used in udp probe. */ + unsigned short icmpEchoId, icmpEchoSeq; /* Icmp Echo Id&Seq value used in ICMP probes*/ + + /* Source port number in TCP probes. Different probe will use + * arbitrary offset value of it. */ + int tcpPortBase; + int udpPortBase; +}; + + + +/* + * Maintain a link of incomplete HostOsScanInfo. + */ +class OsScanInfo +{ +public: + OsScanInfo(vector &Targets); + ~OsScanInfo(); + + /* If you remove from this, you had better adjust nextI too (or call + resetHostIterator() afterward). Don't let this list get empty, + then add to it again, or you may mess up nextI (I'm not sure) */ + list incompleteHosts; + float starttime; + + unsigned int numIncompleteHosts() {return incompleteHosts.size();} + HostOsScanInfo *findIncompleteHost(struct sockaddr_storage *ss); + /* A circular buffer of the incompleteHosts. nextIncompleteHost() gives + the next one. The first time it is called, it will give the + first host in the list. If incompleteHosts is empty, returns + NULL. */ + HostOsScanInfo *nextIncompleteHost(); + /* Resets the host iterator used with nextIncompleteHost() to the + beginning. If you remove a host from incompleteHosts, call this + right afterward */ + void resetHostIterator() { nextI = incompleteHosts.begin(); } + + int removeCompletedHosts(); +private: + unsigned int numInitialTargets; + list::iterator nextI; +}; + + +/* + * The overall os scan information of a host: + * - Fingerprints gotten from every scan round; + * - Maching results of these fingerprints. + * - Is it timeout/completed? + * - ... + */ +class HostOsScanInfo +{ +public: + HostOsScanInfo(Target *t, OsScanInfo *OSI); + ~HostOsScanInfo(); + + Target *target; /* the Target */ + OsScanInfo *OSI; /* The OSI which contains this HostOsScanInfo */ + FingerPrint **FPs; /* Fingerprints of the host */ + FingerPrintResults *FP_matches; /* Fingerprint-matching results */ + bool timedOut; + bool isCompleted; + HostOsScanStats *hss; /* Scan status of the host in one scan round */ +}; + + #endif /*OSSCAN2_H*/