1 /*
2 * **
3 * ** Copyright (C) 2005 Meder Kydyraliev <meder@o0o.nu>
4 * ** Copyright (C) 2001-2005 Fyodor Yarochkin <fygrave@tigerteam.net>,
5 * ** Ofir Arkin <ofir@sys-security.com>
6 * **
7 * ** This program is free software; you can redistribute it and/or modify
8 * ** it under the terms of the GNU General Public License as published by
9 * ** the Free Software Foundation; either version 2 of the License, or
10 * ** (at your option) any later version.
11 * **
12 * **
13 * ** This program is distributed in the hope that it will be useful,
14 * ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * ** GNU General Public License for more details.
17 * **
18 * ** You should have received a copy of the GNU General Public License
19 * ** along with this program; if not, write to the Free Software
20 * ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * */
22
23 #include "xprobe.h"
24 #define _XPROBE_MODULE
25 #include "xplib.h"
26 #include "xprobe_module.h"
27 #include "xprobe_module_hdlr.h"
28 #include "target.h"
29 #include "interface.h"
30 #include "cmd_opts.h"
31 #include "config_set.h"
32 #include "snmp_mod.h"
33
34 extern Interface *ui;
35 extern Cmd_Opts *copts;
36 extern Config_Set *cfg;
37
snmp_mod_init(Xprobe_Module_Hdlr * pt,char * nm)38 int snmp_mod_init(Xprobe_Module_Hdlr *pt, char *nm) {
39 SNMP_Mod *snmp= new SNMP_Mod;
40 snmp->set_name(nm);
41 xprobe_mdebug(XPROBE_DEBUG_MODULES, "Initializing the SNMP module\n");
42 pt->register_module(snmp);
43 pt->add_keyword(snmp->get_id(), "snmp_sysdescr");
44 return OK;
45 }
46
SNMP_Mod(void)47 SNMP_Mod::SNMP_Mod(void): Xprobe_Module(XPROBE_MODULE_OSTEST, "fingerprint:snmp", "SNMPv2c fingerprinting module") {
48
49 }
50
~SNMP_Mod(void)51 SNMP_Mod::~SNMP_Mod(void) {
52 }
53
54
parse_keyword(int os_id,const char * kwd,const char * val)55 int SNMP_Mod::parse_keyword(int os_id, const char *kwd, const char *val) {
56 string descr(val);
57
58 xprobe_debug(XPROBE_DEBUG_SIGNATURES, "Parsing for %i : %s = %s\n", os_id, kwd, val);
59 sysdescrs.insert(pair<int, string>(os_id, descr));
60 return OK;
61 }
62
init(void)63 int SNMP_Mod::init(void) {
64 xprobe_debug(XPROBE_DEBUG_MODULES, "%s module initialized\n", get_name());
65 return OK;
66 }
67
exec(Target * tg,OS_Matrix * os)68 int SNMP_Mod::exec(Target *tg, OS_Matrix *os) {
69 char snmp_request_start[]=
70 "\x30"
71 "\x26" // length of the data that followd
72 "\x02\x01\x01" // version 2c
73 "\x04" // string
74 "\x03"; // length of community string
75 // community string here
76 char snmp_request_end[]=
77 "\xa0\x1c" // PDU GET
78 "\x02\x04\x22\xa2\x3d\x23" // request ID
79 "\x02\x01\x00" // Err status (NO ERR)
80 "\x02\x01\x00" // Err index (NO ERR)
81 "\x30\x0e\x30\x0c\x06\x08\x2b\x06\x01\x02\x01\x01\x01\x00" // SNMPv2 MIBD sysDescr.0
82 "\x05\x00"; // value NULL
83
84 int sock, retval;
85 unsigned int i, packlen;
86 unsigned char *packet, buf[2048];
87 unsigned long request_id;
88 struct sockaddr_in to;
89 vector<string> tokens;
90 vector<string> snmpstrings;
91 vector<unsigned long> snmpints;
92 map<int, string>::iterator iter;
93 SNMP snmp;
94
95
96 if (!tg->port_is_open(IPPROTO_UDP, 161)) {
97 ui->error("[-] %s: need UDP port 161 open\n", get_name());
98 return FAIL;
99 }
100 bzero(&to, sizeof(to));
101 to.sin_family = AF_INET;
102 to.sin_port = htons(161);
103 to.sin_addr = tg->get_addr();
104
105 if ((sock = xp_lib::OpenUDPSocket(&to, NULL)) == FAIL) {
106 ui->error("[-] %s: OpenUDPSocket() failed (%s)!\n", get_name(), strerror(errno));
107 return FAIL;
108 }
109
110 /*
111 * get a vector of community strings to try
112 */
113 xp_lib::tokenize(cfg->get_comstrings().c_str(), ',', &tokens);
114
115 for (i=0; i < tokens.size(); i++) {
116 xprobe_debug(XPROBE_DEBUG_MODULES, "SNMP trying community string: %s\n", tokens[i].c_str());
117 request_id = rand();
118
119 /*
120 * set request ID
121 */
122 snmp_request_end[4] = (unsigned char)(request_id & 0xFF);
123 snmp_request_end[5] = (unsigned char)((request_id >> 8) & 0xFF);
124 snmp_request_end[6] = (unsigned char)((request_id >> 16) & 0xFF);
125 snmp_request_end[7] = (unsigned char)((request_id >> 24) & 0xFF);
126
127 packlen = tokens[i].size() + sizeof(snmp_request_start)-1 + sizeof(snmp_request_end)-1;
128 packet = new unsigned char[packlen];
129 snmp_request_start[6] = tokens[i].size(); // comunity string length
130 snmp_request_start[1] = packlen - 2; // length of the ASN sequence
131
132 /*
133 * construct the SNMP request (ugly)
134 */
135 memcpy(packet, snmp_request_start, sizeof(snmp_request_start)-1);
136 memcpy(packet+sizeof(snmp_request_start)-1, tokens[i].c_str(), tokens[i].size());
137 memcpy(packet+sizeof(snmp_request_start)-1+tokens[i].size(), snmp_request_end, sizeof(snmp_request_end)-1);
138
139 if ((retval = send(sock, packet, packlen, 0)) < 0) {
140 if (errno == ECONNREFUSED)
141 tg->add_port(IPPROTO_UDP, 161, XPROBE_TARGETP_CLOSED);
142 ui->error("[-] %s: send() failed (%s)\n", get_name(), strerror(errno));
143 return FAIL;
144 }
145 delete []packet;
146 retval = xp_lib::RecvTimeout(sock, buf, sizeof(buf), 1);
147 if (retval == 0) {
148 // timeout
149 continue;
150 } else if (retval == FAIL) {
151 ui->error("[-] %s: RecvTimeout() failed!\n", get_name());
152 return FAIL;
153 }
154 xprobe_debug(XPROBE_DEBUG_MODULES, "%s got %d bytes\n", get_name(), retval);
155 if (snmp.parse(buf, retval) == FAIL) {
156 ui->error("[-] %s: SNMP::parse() failed!\n", get_name());
157 return FAIL;
158 }
159 snmp.get_strings(snmpstrings);
160 snmp.get_integers(snmpints);
161 if (snmpstrings.size() < SNMP_MIN_STRINGS) {
162 ui->error("[-] %s: Invalid number of strings %d (min is %d)\n",
163 get_name(), snmpstrings.size(), SNMP_MIN_STRINGS);
164 return FAIL;
165 }
166 if (snmpints.size() < SNMP_MIN_INTS) {
167 ui->error("[-] %s: Invalid number of integers %d (min is %d)\n",
168 get_name(), snmpints.size(), SNMP_MIN_INTS);
169 return FAIL;
170 }
171 if (snmpints[SNMP_REQUESTID_IX] != htonl(request_id)) {
172 ui->error("[-] %s: Got invalid request id from remote target 0x%lx (expected 0x%lx)\n",
173 get_name(), snmpints[SNMP_REQUESTID_IX], htonl(request_id));
174 return FAIL;
175 }
176 ui->msg("[+] SNMP [Community: %s] [sysDescr.0: %s]\n",
177 snmpstrings[SNMP_COMMUNITY_IX].c_str(), snmpstrings[SNMP_SYSDESCR_IX].c_str());
178
179 /*
180 * perform fingerprint matching
181 */
182 for (iter = sysdescrs.begin(); iter != sysdescrs.end(); iter++) {
183
184 string::size_type mypos = snmpstrings[SNMP_SYSDESCR_IX].find(iter->second);
185 if (mypos == string::npos) {
186 os->add_result(get_id(), iter->first, XPROBE_MATCH_NO);
187 } else {
188 os->add_result(get_id(), iter->first, XPROBE_MATCH_YES);
189 }
190 }
191
192 break;
193 }
194 close(sock);
195 return OK;
196 }
197
fini(void)198 int SNMP_Mod::fini(void) {
199 xprobe_debug(XPROBE_DEBUG_MODULES, "%s module has been deinitilized\n", get_name());
200 return OK;
201 }
202
203