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