source: trunk/src/samhain_setpwd.c@ 460

Last change on this file since 460 was 415, checked in by katerina, 12 years ago

Fixes for tickets #314, #315, #316, #317, #318, #319, #320, and #321.

File size: 11.7 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,
282 _("ERROR <new_password> |%s| has not exactly 16 chars\n"),
283 argv[3]);
284 fflush(stdout);
285 return EXIT_FAILURE;
286 }
287
288
289 str = &argv[3][0];
290 i = 0;
291 while (i < 16)
292 {
293 k = i/2; j = 0;
294 if (2*k == i) in[k] = 0;
295 while (j < 16)
296 {
297 if (-1 != readhexchar(str[i]))
298 {
299 in[k] += readhexchar(str[i]) * (i == 2*k ? 16 : 1);
300 break;
301 }
302 ++j;
303 if (j == 16)
304 {
305 fprintf(stdout, _("ERROR Invalid char %c\n"), str[i]);
306 fflush(stdout);
307 return EXIT_FAILURE;
308 }
309 }
310 ++i;
311 }
312 in[8] = '\0';
313
314 /* ---- initialize -----
315 */
316 (void) umask (0);
317
318 taus_seed();
319
320 bytecount = 0;
321
322
323 /* ---- open files -----
324 */
325
326 oldf = open(argv[1], O_RDONLY);
327
328 nlen = strlen(argv[1])+strlen(argv[2])+2;
329 newn = (char *) malloc (nlen);
330 strncpy(newn, argv[1], nlen); newn[nlen-1] = '\0';
331 strncat(newn, ".", nlen); newn[nlen-1] = '\0';
332 strncat(newn, argv[2], nlen); newn[nlen-1] = '\0';
333 newf = open(newn, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
334
335 if (oldf < 0)
336 {
337 fprintf(stdout, _("ERROR Cannot open input file %s.\n"), argv[1]);
338 fflush(stdout);
339 return EXIT_FAILURE;
340 }
341 if (newf < 0)
342 {
343 fprintf(stdout, _("ERROR Cannot open output file %s.\n"), newn);
344 fflush(stdout);
345 return EXIT_FAILURE;
346 }
347
348 /* ---- scan file -----
349 */
350
351
352 while (1)
353 {
354 dat = read (oldf, buf, GRAB_SIZE);
355 if (dat == 0)
356 break;
357
358 bytecount += dat;
359
360 while ( (found_it = my_strstr(buf, (char *) TcpFlag, GRAB_SIZE)) != NULL)
361 {
362 suc = 1;
363 fprintf (stdout, "%s", _("INFO old password found\n"));
364 fflush(stdout);
365 for (i = 0; i < 8; ++i)
366 {
367 sprintf(&oldpwd[i*2], _("%02x"),
368 (unsigned char) *found_it);
369 sprintf(&newpwd[i*2], _("%02x"),
370 (unsigned char) in[i]);
371 *found_it = in[i];
372 ++found_it;
373 }
374 fprintf (stdout, _("INFO replaced: %s by: %s\n"),
375 oldpwd, newpwd);
376 fflush(stdout);
377 }
378
379 while ( (found_it = my_strstr(buf, (char *) BadFlag, GRAB_SIZE)) != NULL)
380 {
381 badcnt++;
382 /* fprintf (stderr, _("INFO old filler found\n")); */
383 for (i = 0; i < 8; ++i)
384 {
385 sprintf(&oldpwd[i*2], _("%02x"),
386 (unsigned char) *found_it);
387
388 ccd = (unsigned char) (256.0 * (taus_get()/(TAUS_MAX+1.0)));
389 sprintf(&newpwd[i*2], _("%02x"),
390 (unsigned char) ccd);
391 *found_it = ccd;
392
393 ++found_it;
394 }
395 /* fprintf (stderr, _("INFO replaced: %s by: %s\n"),
396 oldpwd, newpwd);
397 */
398 }
399
400
401 ret = write (newf, buf, dat);
402 if (dat > 0 && ret < 0)
403 {
404 fprintf(stdout, _("ERROR Cannot write to output file %s.\n"), newn);
405 fflush(stdout);
406 return EXIT_FAILURE;
407 }
408 }
409
410 if (suc == 1 && badcnt == 7)
411 {
412 fprintf (stdout, "%s", _("INFO finished\n"));
413 close (newf);
414 close (oldf);
415 fflush(stdout);
416 return (0);
417 }
418
419 lseek (oldf, 0, SEEK_SET);
420 lseek (newf, 0, SEEK_SET);
421
422 fprintf (stdout, "%s", _("INFO Not found in first pass.\n"));
423 fprintf (stdout, "%s", _("INFO Second pass ..\n"));
424
425 /* offset the start point
426 */
427
428 dat = read (oldf, buf, (GRAB_SIZE / 2));
429 ret = write (newf, buf, dat);
430 if (dat > 0 && ret < 0)
431 {
432 fprintf(stdout, _("ERROR Cannot write to output file %s.\n"), newn);
433 fflush(stdout);
434 return EXIT_FAILURE;
435 }
436
437 bytecount = 0;
438 suc = 0;
439 badcnt = 0;
440
441 while (1)
442 {
443 dat = read (oldf, buf, GRAB_SIZE);
444 if (dat == 0)
445 break;
446
447 bytecount += dat;
448
449 while ( (found_it = my_strstr(buf, (char *) TcpFlag, GRAB_SIZE)) != NULL)
450 {
451 suc = 1;
452 fprintf (stdout, "%s", _("INFO old password found\n"));
453 for (i = 0; i < 8; ++i)
454 {
455 sprintf(&oldpwd[i*2], _("%02x"),
456 (unsigned char) *found_it);
457 sprintf(&newpwd[i*2], _("%02x"),
458 (unsigned char) in[i]);
459 *found_it = in[i];
460 ++found_it;
461 }
462 fprintf (stdout, _("INFO Replaced: %s by: %s\n"),
463 oldpwd, newpwd);
464 }
465
466 while ( (found_it = my_strstr(buf, (char *) BadFlag, GRAB_SIZE)) != NULL)
467 {
468 badcnt++;
469 /* fprintf (stderr, _("INFO old filler found\n")); */
470 for (i = 0; i < 8; ++i)
471 {
472 sprintf(&oldpwd[i*2], _("%02x"),
473 (unsigned char) *found_it);
474
475 ccd = (unsigned char) (256.0 * taus_get()/(TAUS_MAX+1.0));
476 sprintf(&newpwd[i*2], _("%02x"),
477 (unsigned char) ccd);
478 *found_it = ccd;
479
480 ++found_it;
481 }
482 /* fprintf (stderr, _("INFO Replaced: %s by: %s\n"),
483 oldpwd, newpwd);*/
484 }
485
486 ret = write (newf, buf, dat);
487 if (dat > 0 && ret < 0)
488 {
489 fprintf(stdout, _("ERROR Cannot write to output file %s.\n"), newn);
490 fflush(stdout);
491 return EXIT_FAILURE;
492 }
493 }
494
495 close (newf);
496 close (oldf);
497
498 if (suc == 1 && badcnt == 7)
499 {
500 fprintf (stdout, "%s", _("INFO finished\n"));
501 fflush(stdout);
502 return 0;
503 }
504
505 if (suc == 0 || badcnt < 7)
506 {
507 fprintf (stdout, "%s", _("ERROR incomplete replacement\n"));
508 }
509 else
510 {
511 fprintf (stdout, "%s", _("ERROR bad replacement\n"));
512 }
513 fflush(stdout);
514 return EXIT_FAILURE;
515}
Note: See TracBrowser for help on using the repository browser.