/* Mutator.java by Mark D. LaDue */

/* January 26, 1997 */

/* Copyright (c) 1997 Mark D. LaDue
   You may study, use, modify, and distribute this example for any purpose.
   This example is provided WITHOUT WARRANTY either expressed or implied.  */

/* This Java application demonstrates how a class can induce mutations in
   itself, remain viable, and take actions based upon its history.  This
   particular class keeps track of the number of times that it's been run,
   reports and updates that number each time it's run, and then deletes
   itself on the sixth attempted run.  Thus a Java trojan could easily
   appear benign, even useful, for the first several runs and then
   suddenly spring a nasty surprise on the hapless user.  Don't count
   on being able to decompile it to source code to see what it's going to
   do - defending it with the hostile application HoseMocha.java could
   eliminiate that possibility. */

import java.io.*;

class Mutator {
    public static void main(String[] argv) {
        String whoami = "Mutator"; // What's the name of this application?
        int num_runs10 = 10; // The number of previous runs plus 10
        int fpointer = 0; // Where are we in the class file?
// How on earth do I use this thing?
        if (argv.length != 0) {
            System.out.println("Try \"java " + whoami + "\".");
            System.exit(1);
        }
// If Mutator.class isn't writeable, then forget the whole deal.
        File testit = new File(whoami + ".class");
        if (!(testit.canWrite())) {
            System.out.println(whoami + ".class must be writeable.  Fix it!");
            System.exit(2);
        }
// Report how many times the Mutator has been run before this time.
        int num_runs = num_runs10 - 10;
        System.out.println("The Mutator has already been run " + num_runs +
                           " time(s).");
// If it's already been run 5 times, then get rid of Mutator.class
// If the source code is present, get rid of it too. 
        if (num_runs >= 5) {
            testit.delete();
            File source = new File(whoami + ".java");
            if (source.exists() && source.canWrite()) {
                source.delete();
            }
            System.out.println("You can kiss the Mutator goodbye now.");
            System.exit(3);
        }
        try {
            RandomAccessFile victim = new RandomAccessFile(whoami + ".class",
                                                           "rw");
// Update the number of runs by 1.
        fpointer = 1071;
        victim.seek(fpointer);
        int changed_byte = (int)victim.readUnsignedByte() + 1;
        victim.seek(fpointer);
        victim.writeByte(changed_byte);
// All the changes are made, so close the file and get out of here 
        victim.close();
        } catch (IOException ioe) {}
    }
}
