source: trunk/src/samhain_setpwd.c@ 170

Last change on this file since 170 was 170, checked in by katerina, 17 years ago

Plenty of compiler warnings fixed, SQL query length fixed, doc update.

File size: 11.5 KB
RevLine 
[1]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>
[22]10#include <sys/wait.h>
[1]11#include <sys/stat.h>
12#include <fcntl.h>
[22]13#include <errno.h>
14#include <sys/time.h>
[1]15#include <time.h>
16
[22]17#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
18#include <sched.h>
19#endif
[1]20
[22]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
[1]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;
[22]230 size_t nlen;
[1]231 int oldf;
232 int newf;
[170]233 int ret;
[1]234
235 unsigned long bytecount;
236
237 char in[9];
238 int j, k;
239 char ccd;
240 char * str;
241
242 char * buf = (char *) malloc(GRAB_SIZE);
243 size_t dat;
244 char * newpwd = (char *) malloc(5 * 8 + 2);
245 char * oldpwd = (char *) malloc(5 * 8 + 2);
246
247 memset (newpwd, '\0', 5 * 8 + 2);
248 memset (oldpwd, '\0', 5 * 8 + 2);
249
250
251 if (argc < 4)
252 {
253 fprintf (stderr, _("\nUsage: samhain_setpwd <filename> <suffix> "\
254 "<new_password>\n\n"));
255 fprintf (stderr, _(" This program is a utility that will:\n"));
256 fprintf (stderr, _(" - search in the binary executable <filename> "\
257 "for samhain's\n"));
258 fprintf (stderr, _(" compiled-in default password,\n"));
259 fprintf (stderr, _(" - change it to <new_password>,\n"));
260 fprintf (stderr, _(" - and output the modified binary to "\
261 "<filename>.<suffix>\n\n"));
262 fprintf (stderr, _(" To allow for non-printable chars, "\
263 "<new_password> must be\n"));
264 fprintf (stderr, _(" a 16-digit hexadecimal "\
265 "number (only 0-9,A-F allowed in input),\n"));
266 fprintf (stderr, _(" thus corresponding"\
267 " to an 8-byte password.\n\n"));
268 fprintf (stderr, _(" Example: 'samhain_setpwd samhain new "\
269 "4142434445464748'\n"));
270 fprintf (stderr, _(" takes the file 'samhain', sets the password to "\
271 "'ABCDEFGH'\n"));
272 fprintf (stderr, _(" ('A' = 41 hex, 'B' = 42 hex, ...) "\
273 "and outputs the result\n"));
274 fprintf (stderr, _(" to 'samhain.new'.\n"));
275 return EXIT_FAILURE;
276 }
277
278 if (strlen(argv[3]) != 16)
279 {
280 fprintf (stdout, _("ERROR <new_password> %s has not exactly 16 chars\n"),
281 argv[0]);
282 fflush(stdout);
283 return EXIT_FAILURE;
284 }
285
286
287 str = &argv[3][0];
288 i = 0;
289 while (i < 16)
290 {
291 k = i/2; j = 0;
292 if (2*k == i) in[k] = 0;
293 while (j < 16)
294 {
295 if (-1 != readhexchar(str[i]))
296 {
297 in[k] += readhexchar(str[i]) * (i == 2*k ? 16 : 1);
298 break;
299 }
300 ++j;
301 if (j == 16)
302 {
303 fprintf(stdout, _("ERROR Invalid char %c\n"), str[i]);
304 fflush(stdout);
305 return EXIT_FAILURE;
306 }
307 }
308 ++i;
309 }
310 in[8] = '\0';
311
312 /* ---- initialize -----
313 */
314 (void) umask (0);
315
[22]316 taus_seed();
[1]317
318 bytecount = 0;
319
320
321 /* ---- open files -----
322 */
323
324 oldf = open(argv[1], O_RDONLY);
325
[22]326 nlen = strlen(argv[1])+strlen(argv[2])+2;
327 newn = (char *) malloc (nlen);
328 strncpy(newn, argv[1], nlen); newn[nlen-1] = '\0';
329 strncat(newn, ".", nlen); newn[nlen-1] = '\0';
330 strncat(newn, argv[2], nlen); newn[nlen-1] = '\0';
[1]331 newf = open(newn, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
332
333 if (oldf < 0)
334 {
335 fprintf(stdout, _("ERROR Cannot open input file %s.\n"), argv[1]);
336 fflush(stdout);
337 return EXIT_FAILURE;
338 }
339 if (newf < 0)
340 {
341 fprintf(stdout, _("ERROR Cannot open output file %s.\n"), newn);
342 fflush(stdout);
343 return EXIT_FAILURE;
344 }
345
346 /* ---- scan file -----
347 */
348
349
350 while (1)
351 {
352 dat = read (oldf, buf, GRAB_SIZE);
353 if (dat == 0)
354 break;
355
356 bytecount += dat;
357
358 while ( (found_it = my_strstr(buf, (char *) TcpFlag, GRAB_SIZE)) != NULL)
359 {
360 suc = 1;
361 fprintf (stdout, _("INFO old password found\n"));
362 fflush(stdout);
363 for (i = 0; i < 8; ++i)
364 {
365 sprintf(&oldpwd[i*2], _("%02x"),
366 (unsigned char) *found_it);
367 sprintf(&newpwd[i*2], _("%02x"),
368 (unsigned char) in[i]);
369 *found_it = in[i];
370 ++found_it;
371 }
372 fprintf (stdout, _("INFO replaced: %s by: %s\n"),
373 oldpwd, newpwd);
374 fflush(stdout);
375 }
376
377 while ( (found_it = my_strstr(buf, (char *) BadFlag, GRAB_SIZE)) != NULL)
378 {
379 badcnt++;
380 /* fprintf (stderr, _("INFO old filler found\n")); */
381 for (i = 0; i < 8; ++i)
382 {
383 sprintf(&oldpwd[i*2], _("%02x"),
384 (unsigned char) *found_it);
385
[22]386 ccd = (unsigned char) (256.0 * (taus_get()/(TAUS_MAX+1.0)));
[1]387 sprintf(&newpwd[i*2], _("%02x"),
388 (unsigned char) ccd);
389 *found_it = ccd;
390
391 ++found_it;
392 }
393 /* fprintf (stderr, _("INFO replaced: %s by: %s\n"),
394 oldpwd, newpwd);
395 */
396 }
397
398
[170]399 ret = write (newf, buf, dat);
400 if (dat > 0 && ret < 0)
401 {
402 fprintf(stdout, _("ERROR Cannot write to output file %s.\n"), newn);
403 fflush(stdout);
404 return EXIT_FAILURE;
405 }
[1]406 }
407
408 if (suc == 1 && badcnt == 7)
409 {
410 fprintf (stdout, _("INFO finished\n"));
411 close (newf);
412 close (oldf);
413 fflush(stdout);
414 return (0);
415 }
416
417 lseek (oldf, 0, SEEK_SET);
418 lseek (newf, 0, SEEK_SET);
419
420 fprintf (stdout, _("INFO Not found in first pass.\n"));
421 fprintf (stdout, _("INFO Second pass ..\n"));
422
423 /* offset the start point
424 */
425
426 dat = read (oldf, buf, (GRAB_SIZE / 2));
[170]427 ret = write (newf, buf, dat);
428 if (dat > 0 && ret < 0)
429 {
430 fprintf(stdout, _("ERROR Cannot write to output file %s.\n"), newn);
431 fflush(stdout);
432 return EXIT_FAILURE;
433 }
[1]434
435 bytecount = 0;
436 suc = 0;
437 badcnt = 0;
438
439 while (1)
440 {
441 dat = read (oldf, buf, GRAB_SIZE);
442 if (dat == 0)
443 break;
444
445 bytecount += dat;
446
447 while ( (found_it = my_strstr(buf, (char *) TcpFlag, GRAB_SIZE)) != NULL)
448 {
449 suc = 1;
450 fprintf (stdout, _("INFO old password found\n"));
451 for (i = 0; i < 8; ++i)
452 {
453 sprintf(&oldpwd[i*2], _("%02x"),
454 (unsigned char) *found_it);
455 sprintf(&newpwd[i*2], _("%02x"),
456 (unsigned char) in[i]);
457 *found_it = in[i];
458 ++found_it;
459 }
460 fprintf (stdout, _("INFO Replaced: %s by: %s\n"),
461 oldpwd, newpwd);
462 }
463
464 while ( (found_it = my_strstr(buf, (char *) BadFlag, GRAB_SIZE)) != NULL)
465 {
466 badcnt++;
467 /* fprintf (stderr, _("INFO old filler found\n")); */
468 for (i = 0; i < 8; ++i)
469 {
470 sprintf(&oldpwd[i*2], _("%02x"),
471 (unsigned char) *found_it);
472
[22]473 ccd = (unsigned char) (256.0 * taus_get()/(TAUS_MAX+1.0));
[1]474 sprintf(&newpwd[i*2], _("%02x"),
475 (unsigned char) ccd);
476 *found_it = ccd;
477
478 ++found_it;
479 }
480 /* fprintf (stderr, _("INFO Replaced: %s by: %s\n"),
481 oldpwd, newpwd);*/
482 }
483
[170]484 ret = write (newf, buf, dat);
485 if (dat > 0 && ret < 0)
486 {
487 fprintf(stdout, _("ERROR Cannot write to output file %s.\n"), newn);
488 fflush(stdout);
489 return EXIT_FAILURE;
490 }
[1]491 }
492
493 close (newf);
494 close (oldf);
495
496 if (suc == 1 && badcnt == 7)
497 {
498 fprintf (stdout, _("INFO finished\n"));
499 fflush(stdout);
500 return 0;
501 }
502
503 if (suc == 0 || badcnt < 7)
504 {
505 fprintf (stdout, _("ERROR incomplete replacement\n"));
506 }
507 else
508 {
509 fprintf (stdout, _("ERROR bad replacement\n"));
510 }
511 fflush(stdout);
512 return EXIT_FAILURE;
513}
Note: See TracBrowser for help on using the repository browser.