source: trunk/src/samhain_setpwd.c@ 38

Last change on this file since 38 was 22, checked in by rainer, 19 years ago

Minor code revisions.

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