mike (Michael Stefanik) (01/20/91)
In article <72651@bu.edu.bu.edu> bucsf.bu.edu!jdubb (jay dubb) writes: > I am going to write a self-modifying executable (along the lines of >what Mie Bria talked about in article 822: have an executable contain >a time/date string which it can modify and use, to stop working past a >certain date). I've never been known as "Mie Bria" before. :-) Since a few people have asked me about this (in mail, etc.) on how to go about modifying an image, I'll provide some sample code. THe basic idea is this: the user executes a program; within this program is a static string that contains some unique characters, followed by a date stamp. The program then overlays itself (using exec()) with a small program who's job it is to validate the image. This small program searches for this stamp, checks to see if it is valid, and updates the stamp. If the image is not valid, it marks it as invalid (therefore, setting the clock forward again won't let the sneaky user get by) and terminates. If the image is valid, then it overlays itself with the original image, and the program executes normally. The reason that two programs are used is because UNIX will lock the image during execution so that you cannot alter it; the multiple exec's get around this problem. Note that when you first execute the program from the command line, argv[0] contains the name of the program; when the security program re-execs the program, argv[0] is empty, thereby letting the program know that the security program fired it up. Obviously, any C programmer with a modicum of skill could get around this, but it would put a damper on the run-of-the-mill user. No flaming please ... the code may not be beautiful, but then again, it sorta works (for me at least :-) ---[ cut here and call it "program.c" ]-------------------------------------- /* program.c a sample program */ #include <stdio.h> char stamp[16] = "XfuG00000000000"; main(argc,argv) int argc; char *argv[]; { if ( strlen(argv[0]) > 0 ) execlp("security","security",argv[0],NULL); printf("My stamp is %s\n",&stamp[4]); exit(0); } ---[ cut here and call it "security.c" ]------------------------------------- /* @(#)security.c 1.1 stamp an image with the current date this program takes one argument, which is the name of an image that has a predefined "marker" (in this case, "DATE") which is followed by a date specification and checks that date against a possible "clock rollback" if stamp detects a rollback, it exits with an error status; otherwise, it proceeds to re-exec the image that started it */ #include <stdio.h> #include <fcntl.h> #include <sys/types.h> #include <unistd.h> char *target = "XfuG"; main(argc,argv) int argc; char *argv[]; { if ( argc != 2 ) exit(1); if ( patch(argv[1]) == 0 ) execlp(argv[1],"",NULL); } patch(file) char *file; { long loc = 0L, count = 0L, bytes = 0L; int fd; char *block, *buf, *ptr; if ( (block = (char *)malloc(32768)) == NULL ) return(1); buf = block; if ( (fd = open(file,O_RDWR)) == -1 ) return(1); ptr = target; while ( read(fd,buf,32768) != 0 ) { loc = 0; while ( loc != 32768 ) { ++bytes; if ( *buf == *ptr ) { if ( *++ptr == 0 ) { alter(fd,bytes); close(fd); free(block); return(0); } } else ptr = target; ++loc; ++buf; } buf = block; } close(fd); free(block); return(1); } alter(fd,off) int fd; long off; { char stamp[12]; long when, now; lseek(fd,off,SEEK_SET); read(fd,stamp,12); if ( strcmp(stamp,"INVALID") == 0 ) { fprintf(stderr,"This program has been disabled!\n"); exit(1); } when = atol(stamp); time(&now); lseek(fd,-12,SEEK_CUR); if ( now < when ) { fprintf(stderr,"A security violation has occurred.\n"); strcpy(stamp,"INVALID"); write(fd,stamp,12); exit(1); } sprintf(stamp,"%ld",now); write(fd,stamp,12); } ---[ end of example ]-------------------------------------------------------- Compile both programs in the current working directory, make sure that your PATH includes the current directory, and that the 'program' image is read/writable. Enter the command: $ program Then try setting the clock back, execute 'program' again. Then set the clock forwards to the real time, and execute 'program' again. To actually make this usuable, you will have to resolve the search path, and do a few other things, but at least I got you started... -- Michael Stefanik, Systems Engineer (JOAT), Briareus Corporation UUCP: ...!uunet!bria!mike -- technoignorami (tek'no-ig'no-ram`i) a group of individuals that are constantly found to be saying things like "Well, it works on my DOS machine ..."