#include "config_xor.h" #ifdef HAVE_BROKEN_INCLUDES #define _ANSI_C_SOURCE #define _POSIX_SOURCE #endif #include #include #include #include #include #include #include #include #include #ifdef SH_STEALTH char * globber(const char * string); #define _(string) globber(string) #define N_(string) string #else #define _(string) string #define N_(string) string #endif #ifdef SH_STEALTH #ifndef SH_MAX_GLOBS #define SH_MAX_GLOBS 32 #endif char * globber(const char * str) { register int i, j; static int count = -1; static char glob[SH_MAX_GLOBS][128]; ++count; if (count > (SH_MAX_GLOBS-1) ) count = 0; j = strlen(str); if (j > 127) j = 127; for (i = 0; i < j; ++i) { if (str[i] != '\n' && str[i] != '\t') glob[count][i] = str[i] ^ XOR_CODE; else glob[count][i] = str[i]; } glob[count][j] = '\0'; return glob[count]; } #endif /* This is a very inefficient algorithm, but there is really no * need for anything more elaborated here. Can handle NULL's in haystack * (not in needle), which strstr() apparently cannot. */ char * my_strstr (char * haystack, char * needle, int haystack_size) { register int i = 0, j = 0; register int siz; register char * ptr = haystack; register int len; siz = strlen(needle); len = haystack_size - siz; while (j < len) { i = 0; while (i < siz) { if (needle[i] != ptr[i]) break; if (i == (siz-1)) return ptr; ++i; } ++ptr; ++j; } return NULL; } /* fread() does not return the number of chars read, thus we need to * read only a small number of bytes, in order not to expand the binary * too much with the last fwrite(). Too lazy to fix this now. */ #define GRAB_SIZE 1024 int readhexchar ( char c ) { if ( c >= '0' && c <= '9' ) return c - '0'; else if ( c >= 'a' && c <= 'f' ) return c - 'a' + 10; else if ( c >= 'A' && c <= 'F' ) return c - 'A' + 10; else return -1; } int main (int argc, char * argv[]) { /* the default password */ unsigned char TcpFlag[9] = { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7 }; unsigned char BadFlag[9] = { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF }; char * found_it; int i; int suc = 0; int badcnt = 0; char * newn; int oldf; int newf; unsigned long bytecount; char in[9]; int j, k; char ccd; char * str; char * buf = (char *) malloc(GRAB_SIZE); size_t dat; char * newpwd = (char *) malloc(5 * 8 + 2); char * oldpwd = (char *) malloc(5 * 8 + 2); memset (newpwd, '\0', 5 * 8 + 2); memset (oldpwd, '\0', 5 * 8 + 2); if (argc < 4) { fprintf (stderr, _("\nUsage: samhain_setpwd "\ "\n\n")); fprintf (stderr, _(" This program is a utility that will:\n")); fprintf (stderr, _(" - search in the binary executable "\ "for samhain's\n")); fprintf (stderr, _(" compiled-in default password,\n")); fprintf (stderr, _(" - change it to ,\n")); fprintf (stderr, _(" - and output the modified binary to "\ ".\n\n")); fprintf (stderr, _(" To allow for non-printable chars, "\ " must be\n")); fprintf (stderr, _(" a 16-digit hexadecimal "\ "number (only 0-9,A-F allowed in input),\n")); fprintf (stderr, _(" thus corresponding"\ " to an 8-byte password.\n\n")); fprintf (stderr, _(" Example: 'samhain_setpwd samhain new "\ "4142434445464748'\n")); fprintf (stderr, _(" takes the file 'samhain', sets the password to "\ "'ABCDEFGH'\n")); fprintf (stderr, _(" ('A' = 41 hex, 'B' = 42 hex, ...) "\ "and outputs the result\n")); fprintf (stderr, _(" to 'samhain.new'.\n")); return EXIT_FAILURE; } if (strlen(argv[3]) != 16) { fprintf (stdout, _("ERROR %s has not exactly 16 chars\n"), argv[0]); fflush(stdout); return EXIT_FAILURE; } str = &argv[3][0]; i = 0; while (i < 16) { k = i/2; j = 0; if (2*k == i) in[k] = 0; while (j < 16) { if (-1 != readhexchar(str[i])) { in[k] += readhexchar(str[i]) * (i == 2*k ? 16 : 1); break; } ++j; if (j == 16) { fprintf(stdout, _("ERROR Invalid char %c\n"), str[i]); fflush(stdout); return EXIT_FAILURE; } } ++i; } in[8] = '\0'; /* ---- initialize ----- */ (void) umask (0); srand(time(NULL) ^ getpid()); bytecount = 0; /* ---- open files ----- */ oldf = open(argv[1], O_RDONLY); newn = (char *) malloc (strlen(argv[1])+strlen(argv[2])+2); strcpy(newn, argv[1]); strcat(newn, "."); strcat(newn, argv[2]); newf = open(newn, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU); if (oldf < 0) { fprintf(stdout, _("ERROR Cannot open input file %s.\n"), argv[1]); fflush(stdout); return EXIT_FAILURE; } if (newf < 0) { fprintf(stdout, _("ERROR Cannot open output file %s.\n"), newn); fflush(stdout); return EXIT_FAILURE; } /* ---- scan file ----- */ while (1) { dat = read (oldf, buf, GRAB_SIZE); if (dat == 0) break; bytecount += dat; while ( (found_it = my_strstr(buf, (char *) TcpFlag, GRAB_SIZE)) != NULL) { suc = 1; fprintf (stdout, _("INFO old password found\n")); fflush(stdout); for (i = 0; i < 8; ++i) { sprintf(&oldpwd[i*2], _("%02x"), (unsigned char) *found_it); sprintf(&newpwd[i*2], _("%02x"), (unsigned char) in[i]); *found_it = in[i]; ++found_it; } fprintf (stdout, _("INFO replaced: %s by: %s\n"), oldpwd, newpwd); fflush(stdout); } while ( (found_it = my_strstr(buf, (char *) BadFlag, GRAB_SIZE)) != NULL) { badcnt++; /* fprintf (stderr, _("INFO old filler found\n")); */ for (i = 0; i < 8; ++i) { sprintf(&oldpwd[i*2], _("%02x"), (unsigned char) *found_it); ccd = (unsigned char) (256.0 * rand()/(RAND_MAX+1.0)); sprintf(&newpwd[i*2], _("%02x"), (unsigned char) ccd); *found_it = ccd; ++found_it; } /* fprintf (stderr, _("INFO replaced: %s by: %s\n"), oldpwd, newpwd); */ } write (newf, buf, dat); } if (suc == 1 && badcnt == 7) { fprintf (stdout, _("INFO finished\n")); close (newf); close (oldf); fflush(stdout); return (0); } lseek (oldf, 0, SEEK_SET); lseek (newf, 0, SEEK_SET); fprintf (stdout, _("INFO Not found in first pass.\n")); fprintf (stdout, _("INFO Second pass ..\n")); /* offset the start point */ dat = read (oldf, buf, (GRAB_SIZE / 2)); write (newf, buf, dat); bytecount = 0; suc = 0; badcnt = 0; while (1) { dat = read (oldf, buf, GRAB_SIZE); if (dat == 0) break; bytecount += dat; while ( (found_it = my_strstr(buf, (char *) TcpFlag, GRAB_SIZE)) != NULL) { suc = 1; fprintf (stdout, _("INFO old password found\n")); for (i = 0; i < 8; ++i) { sprintf(&oldpwd[i*2], _("%02x"), (unsigned char) *found_it); sprintf(&newpwd[i*2], _("%02x"), (unsigned char) in[i]); *found_it = in[i]; ++found_it; } fprintf (stdout, _("INFO Replaced: %s by: %s\n"), oldpwd, newpwd); } while ( (found_it = my_strstr(buf, (char *) BadFlag, GRAB_SIZE)) != NULL) { badcnt++; /* fprintf (stderr, _("INFO old filler found\n")); */ for (i = 0; i < 8; ++i) { sprintf(&oldpwd[i*2], _("%02x"), (unsigned char) *found_it); ccd = (unsigned char) (256.0 * rand()/(RAND_MAX+1.0)); sprintf(&newpwd[i*2], _("%02x"), (unsigned char) ccd); *found_it = ccd; ++found_it; } /* fprintf (stderr, _("INFO Replaced: %s by: %s\n"), oldpwd, newpwd);*/ } write (newf, buf, dat); } close (newf); close (oldf); if (suc == 1 && badcnt == 7) { fprintf (stdout, _("INFO finished\n")); fflush(stdout); return 0; } if (suc == 0 || badcnt < 7) { fprintf (stdout, _("ERROR incomplete replacement\n")); } else { fprintf (stdout, _("ERROR bad replacement\n")); } fflush(stdout); return EXIT_FAILURE; }