source: trunk/src/samhain_setpwd.c @ 452

Last change on this file since 452 was 415, checked in by katerina, 9 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.