1 /* $Id: icmp_echo_id.cc,v 1.16 2005/06/26 11:26:12 mederchik Exp $ */
2 /*
3 ** Copyright (C) 2001 Fyodor Yarochkin <fygrave@tigerteam.net>,
4 **                    Ofir Arkin       <ofir@sys-security.com>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 
22 
23 
24 #include "xprobe.h"
25 #include "usi++/usi++.h"
26 #include <signal.h>
27 #include <setjmp.h>
28 #define _XPROBE_MODULE
29 #include "xplib.h"
30 #include "xprobe_module.h"
31 #include "xprobe_module_param.h"
32 #include "xprobe_module_hdlr.h"
33 #include "interface.h"
34 #include "target.h"
35 #include "icmp_echo_id.h"
36 
37 extern Interface *ui;
38 
39 /* initialization function */
40 
icmp_echo_id_mod_init(Xprobe_Module_Hdlr * pt,char * nm)41 int icmp_echo_id_mod_init(Xprobe_Module_Hdlr *pt, char *nm) {
42 
43     ICMP_Echo_Id_Mod *module = new ICMP_Echo_Id_Mod;
44 
45     module->set_name(nm);
46     xprobe_mdebug(XPROBE_DEBUG_MODULES, "Initializing the ICMP ECHO ID module\n");
47     pt->register_module(module);
48     pt->add_keyword(module->get_id(),"icmp_echo_reply");
49     pt->add_keyword(module->get_id(),"icmp_echo_code");
50     pt->add_keyword(module->get_id(),"icmp_echo_ip_id");
51     pt->add_keyword(module->get_id(),"icmp_echo_tos_bits");
52     pt->add_keyword(module->get_id(),"icmp_echo_df_bit");
53     pt->add_keyword(module->get_id(),"icmp_echo_reply_ttl");
54 
55 return OK;
56 }
57 
ICMP_Echo_Id_Mod(void)58 ICMP_Echo_Id_Mod::ICMP_Echo_Id_Mod(void): Xprobe_Module(XPROBE_MODULE_OSTEST, "fingerprint:icmp_echo","ICMP Echo request fingerprinting module") {
59 
60     ICMP_Echo_Code_Chk *iecc = new ICMP_Echo_Code_Chk;
61     ICMP_Echo_Id_Chk   *ieic = new ICMP_Echo_Id_Chk;
62     ICMP_Echo_Tos_Chk  *ietc = new ICMP_Echo_Tos_Chk;
63     ICMP_Echo_Df_Bit_Chk *iedbc = new ICMP_Echo_Df_Bit_Chk;
64     ICMP_Echo_Reply_Ttl_Chk *iertc = new ICMP_Echo_Reply_Ttl_Chk;
65     ICMP_Echo_Reply_Check *ierc= new ICMP_Echo_Reply_Check;
66 
67     kwd_chk.insert(pair<string, Xprobe_Module_Param_ICMP *>("icmp_echo_reply", ierc));
68     kwd_chk.insert(pair<string, Xprobe_Module_Param_ICMP *>("icmp_echo_code", iecc));
69     kwd_chk.insert(pair<string, Xprobe_Module_Param_ICMP *>("icmp_echo_ip_id", ieic));
70     kwd_chk.insert(pair<string, Xprobe_Module_Param_ICMP *>("icmp_echo_tos_bits", ietc));
71     kwd_chk.insert(pair<string, Xprobe_Module_Param_ICMP *>("icmp_echo_df_bit", iedbc));
72     kwd_chk.insert(pair<string, Xprobe_Module_Param_ICMP *>("icmp_echo_reply_ttl", iertc));
73 
74     return;
75 }
76 
~ICMP_Echo_Id_Mod(void)77 ICMP_Echo_Id_Mod::~ICMP_Echo_Id_Mod(void) {
78     map <string, Xprobe_Module_Param_ICMP *>::iterator s_i;
79 
80 /* free check objects */
81     for (s_i = kwd_chk.begin(); s_i != kwd_chk.end(); s_i++)
82         delete (*s_i).second;
83 
84 }
85 
init(void)86 int ICMP_Echo_Id_Mod::init(void) {
87 
88     xprobe_debug(XPROBE_DEBUG_MODULES, "%s module initialized\n", get_name());
89     return OK;
90 }
91 
92 
exec(Target * tg,OS_Matrix * os)93 int ICMP_Echo_Id_Mod::exec(Target *tg, OS_Matrix *os) {
94     int ret;
95 
96     xprobe_debug(XPROBE_DEBUG_MODULES, "--%s module has been executed against: %s\n", get_name(),
97             inet_ntoa(tg->get_addr()));
98 
99     current_os = os;
100     ret = do_icmp_ping(tg);
101 
102     if (!ret) return FAIL;
103     return OK;
104 }
105 
fini(void)106 int ICMP_Echo_Id_Mod::fini(void) {
107     xprobe_debug(XPROBE_DEBUG_MODULES, "%s module has been deinitilized\n", get_name());
108     return OK;
109 }
110 
sig_insert(int os_id,int val)111 void ICMP_Echo_Id_Mod::sig_insert(int os_id, int val) {
112 
113     if (sig.find(os_id) != sig.end()) {
114         ui->msg("OS %i - duplicate signature\n", os_id);
115         return;
116     }
117     sig.insert(pair <int, int>(os_id, val));
118 
119 }
120 
sig_ttl_insert(int os_id,int val)121 void ICMP_Echo_Id_Mod::sig_ttl_insert(int os_id, int val) {
122 
123     if (sig_ttl.find(os_id) != sig_ttl.end()) {
124         ui->msg("OS %i - dublicate signature\n", os_id);
125         return;
126     }
127 
128     sig_ttl.insert(pair <int, int>(os_id, val));
129 
130 }
131 
132 
133 
134 
parse_keyword(int os_id,const char * kwd,const char * val)135 int ICMP_Echo_Id_Mod::parse_keyword(int os_id, const char *kwd, const char *val)  {
136 	map <string, Xprobe_Module_Param_ICMP *>::iterator s_i;
137 
138     xprobe_debug(XPROBE_DEBUG_SIGNATURES, "Parsing for %i : %s  = %s\n",
139                                                         os_id,  kwd, val);
140 	if ((s_i=kwd_chk.find(kwd)) != kwd_chk.end()) {
141             return((*s_i).second->parse_param(os_id, val));
142 	}
143     ui->msg("Ooops..none matched %s %s\n", kwd, val);
144     return FAIL;
145 
146 };
147 
do_icmp_ping(Target * tg)148 int ICMP_Echo_Id_Mod::do_icmp_ping(Target *tg) {
149 
150     char buf[1024];
151     struct timeval tv;
152     int ret;
153     int done;
154     unsigned short int icmpp_id;
155     struct in_addr local, remote;
156     map <string, Xprobe_Module_Param_ICMP *>::iterator s_i;
157 
158 /* our lamyer randomizer ;-p */
159     srand(time(NULL));
160     icmpp_id = rand();
161     local = tg->get_interface_addr();
162 	remote = tg->get_addr();
163 
164     ICMP icmpp(inet_ntoa(remote));
165     ICMP sn(inet_ntoa(local));
166     sn.init_device(tg->get_interface(), 0, 1500);
167 
168     tv = tg->get_rtt();
169 
170     icmpp.set_src(inet_ntoa(tg->get_interface_addr()));
171 	// set ip id now, instead of letting os do that
172 	// since we need get_id() to return sent ip id
173 	icmpp.set_id(rand());
174 	icmpp.set_seq(256);
175     icmpp.set_icmpId(icmpp_id);
176     icmpp.set_type(ICMP_ECHO);
177     icmpp.set_code(123); /* our test with non-0 icmp code */
178     icmpp.set_tos(6);
179     icmpp.set_fragoff(IP_DF);
180     fflush(stderr);
181     ret = -1;
182 
183     icmpp.timeout(tv);
184     sn.timeout(tv);
185 	ret = icmpp.send_ping_payload();
186     done = 0;
187     while (!done) {
188         ret = sn.sniffpack(buf, sizeof(buf));
189         /* packet response */
190 //        if (ret > 0 && sn.get_src() != local.s_addr
191         if (!sn.timeout() && sn.get_src() == remote.s_addr &&
192 			sn.get_type() == ICMP_ECHOREPLY && sn.get_icmpId() == icmpp_id) {
193 			done = 1;
194 			xprobe_debug(XPROBE_DEBUG_MODULES, "[%s] Received reply.\n", get_name());
195 		}
196 //        if (ret < 1) done = 1; /* timeout */
197         if (sn.timeout()) {
198 			done = 1; /* timeout */
199 			xprobe_debug(XPROBE_DEBUG_MODULES, "[%s] Timed out, no reply received.\n", get_name());
200 		}
201     }
202 
203     if (! sn.timeout()) {
204         for (s_i = kwd_chk.begin(); s_i != kwd_chk.end(); s_i++)
205             ((*s_i).second->check_param(&sn, &icmpp, current_os));
206 
207 		if (tg->generate_sig())
208 			generate_signature(tg, &sn, &icmpp);
209         return OK;
210     }
211     return FAIL;
212 
213 }
214 
generate_signature(Target * tg,ICMP * pack,ICMP * orig)215 void ICMP_Echo_Id_Mod::generate_signature(Target *tg, ICMP *pack, ICMP *orig) {
216 	string keyword, value;
217 	unsigned int ttl;
218 /*
219 #       icmp_echo_code = [0, !0]
220 #       icmp_echo_ip_id = [0, !0, SENT]
221 #       icmp_echo_tos_bits = [0, !0]
222 #       icmp_echo_df_bit = [0, 1]
223 #       icmp_echo_reply_ttl = [>< decimal num]
224 */
225 	if (!pack->timeout()) {
226 		tg->signature("icmp_echo_reply", "y");
227 		keyword = "icmp_echo_code";
228 		if (pack->get_code() == 0)
229 			value="0";
230 		else
231 			value="!0";
232 		tg->signature(keyword, value);
233 		keyword= "icmp_echo_ip_id";
234 		if (pack->get_id() == 0)
235 			value = "0";
236 		else if (pack->get_id() == orig->get_id())
237 			value = "SENT";
238 		else
239 			value = "!0";
240 		tg->signature(keyword, value);
241 		keyword= "icmp_echo_tos_bits";
242 		if (pack->get_tos() == 0)
243 			value="0";
244 		else
245 			value="!0";
246 		tg->signature(keyword, value);
247 		keyword = "icmp_echo_df_bit";
248 		if (pack->get_fragoff() & IP_DF)
249 			value = "1";
250 		else
251 			value ="0";
252 		tg->signature(keyword, value);
253 		keyword = "icmp_echo_reply_ttl";
254 		ttl = pack->get_ttl() + tg->get_distance();
255 		value = "<";
256 		if (ttl <= 32)
257 			value.append("32");
258 		else if (ttl <= 60)
259 			value.append("60");
260 		else if (ttl <= 64)
261 			value.append("64");
262 		else if (ttl <= 128)
263 			value.append("128");
264 		else if (ttl <= 255)
265 			value.append("255");
266 		tg->signature(keyword, value);
267 	} else {
268 		tg->signature("# No ICMP Echo reply received", "");
269 		tg->signature("icmp_echo_reply", "n");
270 		tg->signature("icmp_echo_code", "");
271 		tg->signature("icmp_echo_ip_id", "");
272 		tg->signature("icmp_echo_tos_bits","");
273 		tg->signature("icmp_echo_df_bit", "");
274 		tg->signature("icmp_echo_reply_ttl", "");
275 	}
276 
277 
278 }
279 
280 
check_param(ICMP * ip_pkt,ICMP * orig_pkt,OS_Matrix * os)281 int ICMP_Echo_Code_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
282 
283    xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ECHO code %i\n", ip_pkt->get_code());
284    return (add_param(ip_pkt->get_code(),orig_pkt->get_code(), os));
285 }
286 
check_param(ICMP * ip_pkt,ICMP * orig_pkt,OS_Matrix * os)287 int ICMP_Echo_Id_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
288 
289    xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ip id %i\n", ip_pkt->get_id());
290    return (add_param(ip_pkt->get_id(), orig_pkt->get_id(), os));
291 }
292 
check_param(ICMP * ip_pkt,ICMP * orig_pkt,OS_Matrix * os)293 int ICMP_Echo_Tos_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
294 
295    xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ip tos 0x%x\n", ip_pkt->get_tos());
296    return (add_param(ip_pkt->get_tos(), orig_pkt->get_tos(), os));
297 }
298 
299 
check_param(ICMP * ip_pkt,ICMP * orig_pkt,OS_Matrix * os)300 int ICMP_Echo_Df_Bit_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
301 
302    xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ip df %i\n",
303                         (ip_pkt->get_fragoff() & IP_DF) !=0?1:0);
304    return (add_param(((ip_pkt->get_fragoff() & IP_DF) != 0), ((orig_pkt->get_fragoff() & IP_DF) != 0), os));
305 }
306 
check_param(ICMP * ip_pkt,ICMP * orig_pkt,OS_Matrix * os)307 int ICMP_Echo_Reply_Ttl_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
308 
309    xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ip ttl %i",  ip_pkt->get_ttl());
310    return (add_param(ip_pkt->get_ttl(), orig_pkt->get_ttl(), os));
311 }
312 
check_param(ICMP * ip_pkt,ICMP * orig_pkt,OS_Matrix * os)313 int ICMP_Echo_Reply_Check::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
314 	int gotp=ip_pkt->timeout() ? 0 : 1;
315 	// suspend warning
316 	orig_pkt->timeout();
317 	add_param(gotp, 0, os);
318 	if (!gotp) {
319 		gen_match(5, os);
320 	}
321 	return OK;
322 }
323