source: trunk/src/samhain_setpwd.c@ 369

Last change on this file since 369 was 212, checked in by katerina, 16 years ago

Lock baseline database (ticket #139) and allow list as input for PortCheckInterface (ticket #140).

File size: 11.6 KB
Line 
1#include "config_xor.h"
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <ctype.h>
7
8#include <unistd.h>
9#include <sys/types.h>
10#include <signal.h>
11#include <sys/wait.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <errno.h>
15#include <sys/time.h>
16#include <time.h>
17
18#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
19#include <sched.h>
20#endif
21
22#if defined(HAVE_INT_32)
23typedef unsigned int UINT32;
24#elif defined(HAVE_LONG_32)
25typedef unsigned long UINT32;
26#elif defined(HAVE_SHORT_32)
27typedef unsigned short UINT32;
28#endif
29
30#define TAUS_MAX 4294967295UL
31
32static UINT32 taus_state[3];
33
34static UINT32 taus_get ()
35{
36
37#define TAUSWORTHE(s,a,b,c,d) ((s &c) <<d) ^ (((s <<a) ^s) >>b)
38 taus_state[0] = TAUSWORTHE (taus_state[0], 13, 19, 4294967294UL, 12);
39 taus_state[1] = TAUSWORTHE (taus_state[1], 2, 25, 4294967288UL, 4);
40 taus_state[2] = TAUSWORTHE (taus_state[2], 3, 11, 4294967280UL, 17);
41 return (taus_state[0] ^ taus_state[1] ^ taus_state[2]);
42}
43
44static void taus_seed ()
45{
46 unsigned char buf[12];
47 unsigned char buf2[12];
48 unsigned char buf3[12];
49 ssize_t count;
50 size_t nbytes = sizeof(buf);
51 size_t where = 0;
52
53 struct timeval t1, t2;
54 UINT32 delta, k[3];
55 int i, j;
56
57 int fd = open ("/dev/urandom", O_RDONLY);
58
59 if (fd == -1)
60 {
61 gettimeofday(&t1, NULL);
62 delta = t1.tv_usec;
63 memcpy(&buf[0], &delta, 4);
64 gettimeofday(&t1, NULL);
65 delta = t1.tv_usec;
66 memcpy(&buf[4], &delta, 4);
67 gettimeofday(&t1, NULL);
68 delta = t1.tv_usec;
69 memcpy(&buf[8], &delta, 4);
70 goto second;
71 }
72
73 do {
74 count = read(fd, &buf[where], nbytes);
75 if (count == -1 && errno == EINTR)
76 continue;
77 where += count;
78 nbytes -= count;
79 } while (nbytes);
80
81 close(fd);
82
83 second:
84 for (i = 0; i < 12; ++i)
85 {
86 gettimeofday(&t1, NULL);
87 if (0 == fork())
88 _exit(EXIT_SUCCESS);
89 wait(NULL);
90 gettimeofday(&t2, NULL);
91 delta = t2.tv_usec - t1.tv_usec;
92 buf2[i] = (unsigned char) delta;
93 }
94
95 for (i = 0; i < 12; ++i)
96 {
97 gettimeofday(&t1, NULL);
98 for (j = 0; j < 32768; ++j)
99 {
100 if (0 == kill (j,0))
101 k[i % 3] ^= j;
102 }
103 gettimeofday(&t2, NULL);
104 delta = t2.tv_usec - t1.tv_usec;
105 buf3[i] ^= (unsigned char) delta;
106 }
107
108 memcpy(&taus_state[0], &buf3[0], 4);
109 memcpy(&taus_state[1], &buf3[4], 4);
110 memcpy(&taus_state[2], &buf3[8], 4);
111
112 taus_state[0] ^= k[0];
113 taus_state[1] ^= k[1];
114 taus_state[2] ^= k[2];
115
116 memcpy(&k[0], &buf2[0], 4);
117 memcpy(&k[1], &buf2[4], 4);
118 memcpy(&k[2], &buf2[8], 4);
119
120 taus_state[0] ^= k[0];
121 taus_state[1] ^= k[1];
122 taus_state[2] ^= k[2];
123
124 memcpy(&k[0], &buf[0], 4);
125 memcpy(&k[1], &buf[4], 4);
126 memcpy(&k[2], &buf[8], 4);
127
128 taus_state[0] ^= k[0];
129 taus_state[1] ^= k[1];
130 taus_state[2] ^= k[2];
131
132 taus_state[0] |= (UINT32) 0x03;
133 taus_state[1] |= (UINT32) 0x09;
134 taus_state[2] |= (UINT32) 0x17;
135}
136
137#ifdef SH_STEALTH
138char * globber(const char * string);
139#define _(string) globber(string)
140#define N_(string) string
141#else
142#define _(string) string
143#define N_(string) string
144#endif
145
146#ifdef SH_STEALTH
147#ifndef SH_MAX_GLOBS
148#define SH_MAX_GLOBS 32
149#endif
150char * globber(const char * str)
151{
152 register int i, j;
153 static int count = -1;
154 static char glob[SH_MAX_GLOBS][128];
155
156 ++count; if (count > (SH_MAX_GLOBS-1) ) count = 0;
157 j = strlen(str);
158 if (j > 127) j = 127;
159
160 for (i = 0; i < j; ++i)
161 {
162 if (str[i] != '\n' && str[i] != '\t')
163 glob[count][i] = str[i] ^ XOR_CODE;
164 else
165 glob[count][i] = str[i];
166 }
167 glob[count][j] = '\0';
168 return glob[count];
169}
170#endif
171
172/* This is a very inefficient algorithm, but there is really no
173 * need for anything more elaborated here. Can handle NULL's in haystack
174 * (not in needle), which strstr() apparently cannot.
175 */
176char * my_strstr (char * haystack, char * needle, int haystack_size)
177{
178 register int i = 0, j = 0;
179 register int siz;
180 register char * ptr = haystack;
181 register int len;
182
183 siz = strlen(needle);
184 len = haystack_size - siz;
185
186 while (j < len)
187 {
188 i = 0;
189 while (i < siz)
190 {
191 if (needle[i] != ptr[i]) break;
192 if (i == (siz-1))
193 return ptr;
194 ++i;
195 }
196 ++ptr; ++j;
197 }
198 return NULL;
199}
200
201/* fread() does not return the number of chars read, thus we need to
202 * read only a small number of bytes, in order not to expand the binary
203 * too much with the last fwrite(). Too lazy to fix this now.
204 */
205#define GRAB_SIZE 1024
206
207int readhexchar ( char c )
208{
209 if ( c >= '0' && c <= '9' )
210 return c - '0';
211 else if ( c >= 'a' && c <= 'f' )
212 return c - 'a' + 10;
213 else if ( c >= 'A' && c <= 'F' )
214 return c - 'A' + 10;
215 else return -1;
216}
217
218int main (int argc, char * argv[])
219{
220 /* the default password
221 */
222 unsigned char TcpFlag[9] = { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7 };
223 unsigned char BadFlag[9] = { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF };
224
225 char * found_it;
226 int i;
227 int suc = 0;
228 int badcnt = 0;
229
230 char * newn;
231 size_t nlen;
232 int oldf;
233 int newf;
234 int ret;
235
236 unsigned long bytecount;
237
238 char in[9];
239 int j, k;
240 char ccd;
241 char * str;
242
243 char * buf = (char *) malloc(GRAB_SIZE);
244 size_t dat;
245 char * newpwd = (char *) malloc(5 * 8 + 2);
246 char * oldpwd = (char *) malloc(5 * 8 + 2);
247
248 memset (newpwd, '\0', 5 * 8 + 2);
249 memset (oldpwd, '\0', 5 * 8 + 2);
250
251
252 if (argc < 4)
253 {
254 fprintf (stderr, "%s", _("\nUsage: samhain_setpwd <filename> <suffix> "\
255 "<new_password>\n\n"));
256 fprintf (stderr, "%s", _(" This program is a utility that will:\n"));
257 fprintf (stderr, "%s", _(" - search in the binary executable "\
258 "<filename> for samhain's\n"));
259 fprintf (stderr, "%s", _(" compiled-in default password,\n"));
260 fprintf (stderr, "%s", _(" - change it to <new_password>,\n"));
261 fprintf (stderr, "%s", _(" - and output the modified binary to "\
262 "<filename>.<suffix>\n\n"));
263 fprintf (stderr, "%s", _(" To allow for non-printable chars, "\
264 "<new_password> must be\n"));
265 fprintf (stderr, "%s", _(" a 16-digit hexadecimal "\
266 "number (only 0-9,A-F allowed in input),\n"));
267 fprintf (stderr, "%s", _(" thus corresponding"\
268 " to an 8-byte password.\n\n"));
269 fprintf (stderr, "%s", _(" Example: 'samhain_setpwd samhain new "\
270 "4142434445464748'\n"));
271 fprintf (stderr, "%s", _(" takes the file 'samhain', sets the "\
272 "password to 'ABCDEFGH'\n"));
273 fprintf (stderr, "%s", _(" ('A' = 41 hex, 'B' = 42 hex, ...) "\
274 "and outputs the result\n"));
275 fprintf (stderr, "%s", _(" to 'samhain.new'.\n"));
276 return EXIT_FAILURE;
277 }
278
279 if (strlen(argv[3]) != 16)
280 {
281 fprintf (stdout, _("ERROR <new_password> %s has not exactly 16 chars\n"),
282 argv[0]);
283 fflush(stdout);
284 return EXIT_FAILURE;
285 }
286
287
288 str = &argv[3][0];
289 i = 0;
290 while (i < 16)
291 {
292 k = i/2; j = 0;
293 if (2*k == i) in[k] = 0;
294 while (j < 16)
295 {
296 if (-1 != readhexchar(str[i]))
297 {
298 in[k] += readhexchar(str[i]) * (i == 2*k ? 16 : 1);
299 break;
300 }
301 ++j;
302 if (j == 16)
303 {
304 fprintf(stdout, _("ERROR Invalid char %c\n"), str[i]);
305 fflush(stdout);
306 return EXIT_FAILURE;
307 }
308 }
309 ++i;
310 }
311 in[8] = '\0';
312
313 /* ---- initialize -----
314 */
315 (void) umask (0);
316
317 taus_seed();
318
319 bytecount = 0;
320
321
322 /* ---- open files -----
323 */
324
325 oldf = open(argv[1], O_RDONLY);
326
327 nlen = strlen(argv[1])+strlen(argv[2])+2;
328 newn = (char *) malloc (nlen);
329 strncpy(newn, argv[1], nlen); newn[nlen-1] = '\0';
330 strncat(newn, ".", nlen); newn[nlen-1] = '\0';
331 strncat(newn, argv[2], nlen); newn[nlen-1] = '\0';
332 newf = open(newn, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
333
334 if (oldf < 0)
335 {
336 fprintf(stdout, _("ERROR Cannot open input file %s.\n"), argv[1]);
337 fflush(stdout);
338 return EXIT_FAILURE;
339 }
340 if (newf < 0)
341 {
342 fprintf(stdout, _("ERROR Cannot open output file %s.\n"), newn);
343 fflush(stdout);
344 return EXIT_FAILURE;
345 }
346
347 /* ---- scan file -----
348 */
349
350
351 while (1)
352 {
353 dat = read (oldf, buf, GRAB_SIZE);
354 if (dat == 0)
355 break;
356
357 bytecount += dat;
358
359 while ( (found_it = my_strstr(buf, (char *) TcpFlag, GRAB_SIZE)) != NULL)
360 {
361 suc = 1;
362 fprintf (stdout, "%s", _("INFO old password found\n"));
363 fflush(stdout);
364 for (i = 0; i < 8; ++i)
365 {
366 sprintf(&oldpwd[i*2], _("%02x"),
367 (unsigned char) *found_it);
368 sprintf(&newpwd[i*2], _("%02x"),
369 (unsigned char) in[i]);
370 *found_it = in[i];
371 ++found_it;
372 }
373 fprintf (stdout, _("INFO replaced: %s by: %s\n"),
374 oldpwd, newpwd);
375 fflush(stdout);
376 }
377
378 while ( (found_it = my_strstr(buf, (char *) BadFlag, GRAB_SIZE)) != NULL)
379 {
380 badcnt++;
381 /* fprintf (stderr, _("INFO old filler found\n")); */
382 for (i = 0; i < 8; ++i)
383 {
384 sprintf(&oldpwd[i*2], _("%02x"),
385 (unsigned char) *found_it);
386
387 ccd = (unsigned char) (256.0 * (taus_get()/(TAUS_MAX+1.0)));
388 sprintf(&newpwd[i*2], _("%02x"),
389 (unsigned char) ccd);
390 *found_it = ccd;
391
392 ++found_it;
393 }
394 /* fprintf (stderr, _("INFO replaced: %s by: %s\n"),
395 oldpwd, newpwd);
396 */
397 }
398
399
400 ret = write (newf, buf, dat);
401 if (dat > 0 && ret < 0)
402 {
403 fprintf(stdout, _("ERROR Cannot write to output file %s.\n"), newn);
404 fflush(stdout);
405 return EXIT_FAILURE;
406 }
407 }
408
409 if (suc == 1 && badcnt == 7)
410 {
411 fprintf (stdout, "%s", _("INFO finished\n"));
412 close (newf);
413 close (oldf);
414 fflush(stdout);
415 return (0);
416 }
417
418 lseek (oldf, 0, SEEK_SET);
419 lseek (newf, 0, SEEK_SET);
420
421 fprintf (stdout, "%s", _("INFO Not found in first pass.\n"));
422 fprintf (stdout, "%s", _("INFO Second pass ..\n"));
423
424 /* offset the start point
425 */
426
427 dat = read (oldf, buf, (GRAB_SIZE / 2));
428 ret = write (newf, buf, dat);
429 if (dat > 0 && ret < 0)
430 {
431 fprintf(stdout, _("ERROR Cannot write to output file %s.\n"), newn);
432 fflush(stdout);
433 return EXIT_FAILURE;
434 }
435
436 bytecount = 0;
437 suc = 0;
438 badcnt = 0;
439
440 while (1)
441 {
442 dat = read (oldf, buf, GRAB_SIZE);
443 if (dat == 0)
444 break;
445
446 bytecount += dat;
447
448 while ( (found_it = my_strstr(buf, (char *) TcpFlag, GRAB_SIZE)) != NULL)
449 {
450 suc = 1;
451 fprintf (stdout, "%s", _("INFO old password found\n"));
452 for (i = 0; i < 8; ++i)
453 {
454 sprintf(&oldpwd[i*2], _("%02x"),
455 (unsigned char) *found_it);
456 sprintf(&newpwd[i*2], _("%02x"),
457 (unsigned char) in[i]);
458 *found_it = in[i];
459 ++found_it;
460 }
461 fprintf (stdout, _("INFO Replaced: %s by: %s\n"),
462 oldpwd, newpwd);
463 }
464
465 while ( (found_it = my_strstr(buf, (char *) BadFlag, GRAB_SIZE)) != NULL)
466 {
467 badcnt++;
468 /* fprintf (stderr, _("INFO old filler found\n")); */
469 for (i = 0; i < 8; ++i)
470 {
471 sprintf(&oldpwd[i*2], _("%02x"),
472 (unsigned char) *found_it);
473
474 ccd = (unsigned char) (256.0 * taus_get()/(TAUS_MAX+1.0));
475 sprintf(&newpwd[i*2], _("%02x"),
476 (unsigned char) ccd);
477 *found_it = ccd;
478
479 ++found_it;
480 }
481 /* fprintf (stderr, _("INFO Replaced: %s by: %s\n"),
482 oldpwd, newpwd);*/
483 }
484
485 ret = write (newf, buf, dat);
486 if (dat > 0 && ret < 0)
487 {
488 fprintf(stdout, _("ERROR Cannot write to output file %s.\n"), newn);
489 fflush(stdout);
490 return EXIT_FAILURE;
491 }
492 }
493
494 close (newf);
495 close (oldf);
496
497 if (suc == 1 && badcnt == 7)
498 {
499 fprintf (stdout, "%s", _("INFO finished\n"));
500 fflush(stdout);
501 return 0;
502 }
503
504 if (suc == 0 || badcnt < 7)
505 {
506 fprintf (stdout, "%s", _("ERROR incomplete replacement\n"));
507 }
508 else
509 {
510 fprintf (stdout, "%s", _("ERROR bad replacement\n"));
511 }
512 fflush(stdout);
513 return EXIT_FAILURE;
514}
Note: See TracBrowser for help on using the repository browser.