1
/* $Id: icmp_echo_id.cc,v 1.15 2005/02/08 20:00:51 mederchik Exp $ */
3
** Copyright (C) 2001 Fyodor Yarochkin <fygrave@tigerteam.net>,
4
** Ofir Arkin <ofir@sys-security.com>
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.
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.
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.
25
#include "usi++/usi++.h"
28
#define _XPROBE_MODULE
30
#include "xprobe_module.h"
31
#include "xprobe_module_param.h"
32
#include "xprobe_module_hdlr.h"
33
#include "interface.h"
35
#include "icmp_echo_id.h"
39
/* initialization function */
41
int icmp_echo_id_mod_init(Xprobe_Module_Hdlr *pt, char *nm) {
43
ICMP_Echo_Id_Mod *module = new ICMP_Echo_Id_Mod;
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");
58
ICMP_Echo_Id_Mod::ICMP_Echo_Id_Mod(void): Xprobe_Module(XPROBE_MODULE_OSTEST, "fingerprint:icmp_echo","ICMP Echo request fingerprinting module") {
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;
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));
77
ICMP_Echo_Id_Mod::~ICMP_Echo_Id_Mod(void) {
78
map <string, Xprobe_Module_Param_ICMP *>::iterator s_i;
80
/* free check objects */
81
for (s_i = kwd_chk.begin(); s_i != kwd_chk.end(); s_i++)
86
int ICMP_Echo_Id_Mod::init(void) {
88
xprobe_debug(XPROBE_DEBUG_MODULES, "%s module initialized\n", get_name());
93
int ICMP_Echo_Id_Mod::exec(Target *tg, OS_Matrix *os) {
96
xprobe_debug(XPROBE_DEBUG_MODULES, "--%s module has been executed against: %s\n", get_name(),
97
inet_ntoa(tg->get_addr()));
100
ret = do_icmp_ping(tg);
102
if (!ret) return FAIL;
106
int ICMP_Echo_Id_Mod::fini(void) {
107
xprobe_debug(XPROBE_DEBUG_MODULES, "%s module has been deinitilized\n", get_name());
111
void ICMP_Echo_Id_Mod::sig_insert(int os_id, int val) {
113
if (sig.find(os_id) != sig.end()) {
114
ui->msg("OS %i - duplicate signature\n", os_id);
117
sig.insert(pair <int, int>(os_id, val));
121
void ICMP_Echo_Id_Mod::sig_ttl_insert(int os_id, int val) {
123
if (sig_ttl.find(os_id) != sig_ttl.end()) {
124
ui->msg("OS %i - dublicate signature\n", os_id);
128
sig_ttl.insert(pair <int, int>(os_id, 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;
138
xprobe_debug(XPROBE_DEBUG_SIGNATURES, "Parsing for %i : %s = %s\n",
140
if ((s_i=kwd_chk.find(kwd)) != kwd_chk.end()) {
141
return((*s_i).second->parse_param(os_id, val));
143
ui->msg("Ooops..none matched %s %s\n", kwd, val);
148
int ICMP_Echo_Id_Mod::do_icmp_ping(Target *tg) {
154
unsigned short int icmpp_id;
155
struct in_addr local, remote;
156
map <string, Xprobe_Module_Param_ICMP *>::iterator s_i;
158
/* our lamyer randomizer ;-p */
161
local = tg->get_interface_addr();
162
remote = tg->get_addr();
164
ICMP icmpp(inet_ntoa(remote));
165
ICMP sn(inet_ntoa(local));
166
sn.init_device(tg->get_interface(), 0, 1500);
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());
175
icmpp.set_icmpId(icmpp_id);
176
icmpp.set_type(ICMP_ECHO);
177
icmpp.set_code(123); /* our test with non-0 icmp code */
179
icmpp.set_fragoff(IP_DF);
185
ret = icmpp.send_ping_payload();
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) {
194
xprobe_debug(XPROBE_DEBUG_MODULES, "[%s] Received reply.\n", get_name());
196
// if (ret < 1) done = 1; /* timeout */
198
done = 1; /* timeout */
199
xprobe_debug(XPROBE_DEBUG_MODULES, "[%s] Timed out, no reply received.\n", get_name());
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));
207
if (tg->generate_sig())
208
generate_signature(tg, &sn, &icmpp);
215
void ICMP_Echo_Id_Mod::generate_signature(Target *tg, ICMP *pack, ICMP *orig) {
216
string keyword, value;
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]
225
if (!pack->timeout()) {
226
tg->signature("icmp_echo_reply", "y");
227
keyword = "icmp_echo_code";
228
if (pack->get_code() == 0)
232
tg->signature(keyword, value);
233
keyword= "icmp_echo_ip_id";
234
if (pack->get_id() == 0)
236
else if (pack->get_id() == orig->get_id())
240
tg->signature(keyword, value);
241
keyword= "icmp_echo_tos_bits";
242
if (pack->get_tos() == 0)
246
tg->signature(keyword, value);
247
keyword = "icmp_echo_df_bit";
248
if (pack->get_fragoff() & IP_DF)
252
tg->signature(keyword, value);
253
keyword = "icmp_echo_reply_ttl";
254
ttl = pack->get_ttl() + tg->get_distance();
264
tg->signature(keyword, value);
266
tg->signature("# No ICMP Echo reply received", "");
267
tg->signature("icmp_echo_reply", "n");
268
tg->signature("icmp_echo_code", "");
269
tg->signature("icmp_echo_ip_id", "");
270
tg->signature("icmp_echo_tos_bits","");
271
tg->signature("icmp_echo_df_bit", "");
272
tg->signature("icmp_echo_reply_ttl", "");
279
int ICMP_Echo_Code_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
281
xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ECHO code %i\n", ip_pkt->get_code());
282
return (add_param(ip_pkt->get_code(),orig_pkt->get_code(), os));
285
int ICMP_Echo_Id_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
287
xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ip id %i\n", ip_pkt->get_id());
288
return (add_param(ip_pkt->get_id(), orig_pkt->get_id(), os));
291
int ICMP_Echo_Tos_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
293
xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ip tos 0x%x\n", ip_pkt->get_tos());
294
return (add_param(ip_pkt->get_tos(), orig_pkt->get_tos(), os));
298
int ICMP_Echo_Df_Bit_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
300
xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ip df %i\n",
301
(ip_pkt->get_fragoff() & IP_DF) !=0?1:0);
302
return (add_param(((ip_pkt->get_fragoff() & IP_DF) != 0), ((orig_pkt->get_fragoff() & IP_DF) != 0), os));
305
int ICMP_Echo_Reply_Ttl_Chk::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
307
xprobe_debug(XPROBE_DEBUG_MODULES, "ICMP ip ttl %i", ip_pkt->get_ttl());
308
return (add_param(ip_pkt->get_ttl(), orig_pkt->get_ttl(), os));
311
int ICMP_Echo_Reply_Check::check_param(ICMP *ip_pkt, ICMP *orig_pkt, OS_Matrix *os) {
312
int gotp=ip_pkt->timeout() ? 0 : 1;
315
add_param(gotp, 0, os);