-
Notifications
You must be signed in to change notification settings - Fork 2k
/
hydra-oracle-listener.c
348 lines (300 loc) · 9.73 KB
/
hydra-oracle-listener.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
/*
david:
PASSWORDS_LISTENER in listener.ora can be in clear or in plain mode,
this module support the 2 modes, use -m PLAIN or -m CLEAR on the cmd
line. Default is plain (oracle 10 uses it).
Thanks to Marcell for the plain mode analysis available
at http://marcellmajor.com/frame_listenerhash.html
*/
#include "hydra-mod.h"
#ifndef LIBOPENSSL
#include <stdio.h>
void dummy_oracle_listener() { printf("\n"); }
#else
#include "sasl.h"
#include <openssl/des.h>
#define HASHSIZE 17
extern hydra_option hydra_options;
extern char *HYDRA_EXIT;
char *buf;
unsigned char *hash;
int32_t sid_mechanism = AUTH_PLAIN;
int32_t initial_permutation(unsigned char **result, char *p_str, int32_t *sz) {
int32_t k = 0;
int32_t i = strlen(p_str);
char *buff;
// expand the string with zero so that length is a multiple of 4
while ((i % 4) != 0) {
i = i + 1;
}
*sz = 2 * i;
if ((buff = malloc(i + 4)) == NULL) {
hydra_report(stderr, "[ERROR] Can't allocate memory\n");
return 1;
}
memset(buff, 0, i + 4);
strcpy(buff, p_str);
// swap the order of every byte pair
for (k = 0; k < i; k += 2) {
char bck = buff[k + 1];
buff[k + 1] = buff[k];
buff[k] = bck;
}
// convert to unicode
if ((*result = malloc(2 * i)) == NULL) {
hydra_report(stderr, "[ERROR] Can't allocate memory\n");
free(buff);
return 1;
}
memset(*result, 0, 2 * i);
for (k = 0; k < i; k++) {
(*result)[2 * k] = buff[k];
}
free(buff);
return 0;
}
int32_t ora_hash(unsigned char **orahash, unsigned char *buf, int32_t len) {
int32_t i;
if ((*orahash = malloc(HASHSIZE)) == NULL) {
hydra_report(stderr, "[ERROR] Can't allocate memory\n");
return 1;
}
for (i = 0; i < 8; i++) {
sprintf(((char *)*orahash) + i * 2, "%02X", buf[len - 8 + i]);
}
return 0;
}
int32_t convert_byteorder(unsigned char **result, int32_t size) {
int32_t i = 0;
char *buff;
if ((buff = malloc(size)) == NULL) {
hydra_report(stderr, "[ERROR] Can't allocate memory\n");
return 1;
}
memcpy(buff, *result, size);
while (i < size) {
buff[i + 0] = (*result)[i + 3];
buff[i + 1] = (*result)[i + 2];
buff[i + 2] = (*result)[i + 1];
buff[i + 3] = (*result)[i + 0];
i += 4;
}
memcpy(*result, buff, size);
free(buff);
return 0;
}
int32_t ora_descrypt(unsigned char **rs, unsigned char *result, int32_t siz) {
int32_t i = 0;
char lastkey[8];
DES_key_schedule ks1;
unsigned char key1[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
unsigned char ivec1[] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char *desresult;
memset(ivec1, 0, sizeof(ivec1));
if ((desresult = malloc(siz)) == NULL) {
hydra_report(stderr, "[ERROR] Can't allocate memory\n");
return 1;
}
DES_key_sched((const_DES_cblock *)key1, &ks1);
DES_ncbc_encrypt(result, desresult, siz, &ks1, &ivec1, DES_ENCRYPT);
for (i = 0; i < 8; i++) {
lastkey[i] = desresult[siz - 8 + i];
}
DES_key_sched((const_DES_cblock *)lastkey, &ks1);
memset(desresult, 0, siz);
memset(ivec1, 0, sizeof(ivec1));
DES_ncbc_encrypt(result, desresult, siz, &ks1, &ivec1, DES_ENCRYPT);
if ((*rs = malloc(siz)) == NULL) {
hydra_report(stderr, "[ERROR] Can't allocate memory\n");
free(desresult);
return 1;
}
memcpy(*rs, desresult, siz);
return 0;
}
int32_t ora_hash_password(char *pass) {
// secret hash function comes here, and written to char *hash
int32_t siz = 0;
unsigned char *desresult;
unsigned char *result;
char buff[strlen(pass) + 5];
memset(buff, 0, sizeof(buff));
// concatenate Arb string and convert the resulting string to uppercase
snprintf(buff, sizeof(buff), "Arb%s", pass);
strupper(buff);
if (initial_permutation(&result, buff, &siz)) {
hydra_report(stderr, "[ERROR] ora_hash_password: in initial_permutation\n");
return 1;
}
if (convert_byteorder(&result, siz)) {
hydra_report(stderr, "[ERROR] ora_hash_password: in convert_byteorder\n");
free(result);
return 1;
}
if (ora_descrypt(&desresult, result, siz)) {
hydra_report(stderr, "[ERROR] ora_hash_password: in DES crypt\n");
free(result);
return 1;
}
free(result);
if (ora_hash(&result, desresult, siz)) {
hydra_report(stderr, "[ERROR] ora_hash_password: in extracting Oracle hash\n");
free(desresult);
return 1;
}
memcpy(hash, result, HASHSIZE);
free(desresult);
free(result);
return 0;
}
int32_t start_oracle_listener(int32_t s, char *ip, int32_t port, unsigned char options, char *miscptr, FILE *fp) {
unsigned char tns_packet_begin[22] = {"\x00\x00\x01\x00\x00\x00\x01\x36\x01\x2c\x00\x00\x08\x00\x7f\xff\x86\x0e"
"\x00\x00\x01\x00"};
unsigned char tns_packet_end[32] = {"\x00\x3a\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x09\x94\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00"};
char *empty = "";
char *pass;
char connect_string[200];
char buffer2[260];
int32_t siz = 0;
memset(connect_string, 0, sizeof(connect_string));
memset(buffer2, 0, sizeof(buffer2));
if (strlen(pass = hydra_get_next_password()) == 0)
pass = empty;
if (sid_mechanism == AUTH_PLAIN) {
if ((hash = malloc(HASHSIZE)) == NULL) {
hydra_report(stderr, "[ERROR] Can't allocate memory\n");
return 1;
}
memset(hash, 0, HASHSIZE);
if (ora_hash_password(pass)) {
hydra_report(stderr, "[ERROR] generating Oracle hash\n");
free(hash);
return 1;
}
pass = (char *)hash;
}
snprintf(connect_string, sizeof(connect_string),
"(DESCRIPTION=(CONNECT_DATA=(CID=(PROGRAM=))(COMMAND=reload)("
"PASSWORD=%s)(SERVICE=)(VERSION=169869568)))",
pass);
if (hash != NULL)
free(hash);
if (verbose)
hydra_report(stderr, "[VERBOSE] using connectiong string: %s\n", connect_string);
siz = 2 + sizeof(tns_packet_begin) + 2 + sizeof(tns_packet_end) + strlen(connect_string);
if (siz > 255) {
buffer2[0] = 1;
buffer2[1] = siz - 256;
} else {
buffer2[1] = siz;
}
memcpy(buffer2 + 2, (char *)tns_packet_begin, sizeof(tns_packet_begin));
siz = strlen(connect_string);
if (siz > 255) {
buffer2[2 + sizeof(tns_packet_begin)] = 1;
buffer2[1 + 2 + sizeof(tns_packet_begin)] = siz - 256;
} else {
buffer2[1 + 2 + sizeof(tns_packet_begin)] = siz;
}
memcpy(buffer2 + 2 + sizeof(tns_packet_begin) + 2, (char *)tns_packet_end, sizeof(tns_packet_end));
memcpy(buffer2 + 2 + sizeof(tns_packet_begin) + 2 + sizeof(tns_packet_end), connect_string, strlen(connect_string));
if (hydra_send(s, buffer2, 2 + sizeof(tns_packet_begin) + 2 + sizeof(tns_packet_end) + strlen(connect_string), 0) < 0) {
return 1;
}
if ((buf = hydra_receive_line(s)) == NULL)
return 1;
if (verbose || debug)
hydra_report(stderr, "[VERBOSE] Server answer: %s\n", buf);
if (strstr(buf, "ERR=0") != NULL) {
hydra_report_found_host(port, ip, "oracle-listener", fp);
hydra_completed_pair_found();
} else
hydra_completed_pair();
free(buf);
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
return 3;
return 1;
}
void service_oracle_listener(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
int32_t run = 1, next_run = 1, sock = -1;
int32_t myport = PORT_ORACLE, mysslport = PORT_ORACLE_SSL;
hydra_register_socket(sp);
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
return;
if ((miscptr != NULL) && (strlen(miscptr) > 0)) {
strupper(miscptr);
if (strncmp(miscptr, "CLEAR", 5) == 0)
sid_mechanism = AUTH_CLEAR;
}
if (verbose) {
switch (sid_mechanism) {
case AUTH_CLEAR:
hydra_report(stderr, "[VERBOSE] using SID CLEAR mechanism\n");
break;
case AUTH_PLAIN:
hydra_report(stderr, "[VERBOSE] using SID PLAIN mechanism\n");
break;
}
}
while (1) {
switch (run) {
case 1: /* connect and service init function */
if (sock >= 0)
sock = hydra_disconnect(sock);
// usleepn(300);
if ((options & OPTION_SSL) == 0) {
if (port != 0)
myport = port;
sock = hydra_connect_tcp(ip, myport);
port = myport;
} else {
if (port != 0)
mysslport = port;
sock = hydra_connect_ssl(ip, mysslport, hostname);
port = mysslport;
}
if (sock < 0) {
if (verbose || debug)
hydra_report(stderr, "[ERROR] Child with pid %d terminating, can not connect\n", (int32_t)getpid());
hydra_child_exit(1);
}
/* run the cracking function */
next_run = start_oracle_listener(sock, ip, port, options, miscptr, fp);
if (next_run == 1 && hydra_options.conwait)
sleep(hydra_options.conwait);
break;
case 3: /* clean exit */
if (sock >= 0)
sock = hydra_disconnect(sock);
hydra_child_exit(0);
return;
case 4:
if (sock >= 0)
sock = hydra_disconnect(sock);
hydra_child_exit(2);
return;
default:
hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n");
hydra_child_exit(0);
}
run = next_run;
}
}
int32_t service_oracle_listener_init(char *ip, int32_t sp, unsigned char options, char *miscptr, FILE *fp, int32_t port, char *hostname) {
// called before the childrens are forked off, so this is the function
// which should be filled if initial connections and service setup has to be
// performed once only.
//
// fill if needed.
//
// return codes:
// 0 all OK
// -1 error, hydra will exit, so print a good error message here
return 0;
}
void usage_oracle_listener(const char *service) {
printf("Module oracle-listener / tns is optionally taking the mode the "
"password is stored as, could be PLAIN (default) or CLEAR\n\n");
}
#endif