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)
23 typedef unsigned int UINT32;
24 #elif defined(HAVE_LONG_32)
25 typedef unsigned long UINT32;
26 #elif defined(HAVE_SHORT_32)
27 typedef unsigned short UINT32;
28 #endif
29 
30 #define TAUS_MAX 4294967295UL
31 
32 static UINT32 taus_state[3];
33 
taus_get()34 static 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 
taus_seed()44 static 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
138 char * 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
globber(const char * str)150 char * 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  */
my_strstr(char * haystack,char * needle,int haystack_size)176 char * 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 
readhexchar(char c)207 int 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 
main(int argc,char * argv[])218 int 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 }
516