Advertisement
Guest User

Untitled

a guest
Apr 13th, 2014
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 14.74 KB | None | 0 0
  1. package modify;
  2.  
  3. import java.io.ByteArrayInputStream;
  4. import java.io.ByteArrayOutputStream;
  5. import java.io.DataInputStream;
  6. import java.io.DataOutputStream;
  7. import java.io.FileInputStream;
  8. import java.io.IOException;
  9. import java.util.Vector;
  10.  
  11. /**
  12.  *
  13.  * @author kiriman
  14.  */
  15. public class Modify {
  16.  
  17.     private static final int MAGIC = 0xCAFEBABE; // О_о
  18.     private static final int CLASS = 7;
  19.     private static final int FIELDREF = 9;
  20.     private static final int METHODREF = 10;
  21.     private static final int INTERFACEMETHODREF = 11;
  22.     private static final int STRING = 8;
  23.     private static final int INTEGER = 3;
  24.     private static final int FLOAT = 4;
  25.     private static final int LONG = 5;
  26.     private static final int DOUBLE = 6;
  27.     private static final int NAMEANDTYPE = 12;
  28.     private static final int UTF8 = 1;
  29.     private static int class_version, // Версия класса
  30.             count_constants_cp, // Количество констант
  31.             max_stack; // Максимальный размер стека
  32.     private static byte[] tag_cp, // Тэги записей в пуле
  33.             code; // Основной код
  34.     private static Vector cpool, // Сами записи
  35.             indexC;
  36.     private static boolean fuck_ob;
  37.  
  38.     private static int getIndex(int p, int l) {
  39.         int a1, a2;
  40.         a1 = (p >> l) & 0xff;
  41.         a2 = (p >> (l - 8)) & 0xff;
  42.         return ((a1 << 8) | (a2)) - 1;
  43.     }
  44.  
  45.     public static byte[] modifyClass(FileInputStream fis, String name_class) {
  46.         try {
  47.             DataInputStream dis = new DataInputStream(fis);
  48.             dis.readInt(); // MAGIC
  49.             class_version = dis.readInt();
  50.             count_constants_cp = dis.readUnsignedShort();
  51.             tag_cp = new byte[count_constants_cp];
  52.             cpool = new Vector();
  53.             Vector mref = new Vector(); // Для METHODREF записей
  54.             Vector temp_i = new Vector();
  55.             int skip = 10; // Кол-во прочтенных байт(int + int + short)
  56.             boolean z = false;
  57.             fuck_ob = false;
  58.  
  59.             for (int i = 0; i < count_constants_cp - 1; i++) {
  60.                 tag_cp[i] = dis.readByte();
  61.                 if (tag_cp[i] == 0) {
  62.                     fuck_ob = true;
  63.                     System.out.println("fuck");
  64.                     break;
  65.                 }
  66.                 skip++;
  67.                 switch (tag_cp[i]) {
  68.                     case METHODREF:
  69.                         int lol = dis.readInt();
  70.                         temp_i.addElement(new Integer(i + 1));
  71.                         cpool.addElement(new Integer(lol));
  72.                         mref.addElement(new Integer(lol));
  73.                         skip += 4;
  74.                         break;
  75.                     case UTF8:
  76.                         String s = dis.readUTF();
  77.                         skip += s.length() + 2;
  78.                         cpool.addElement(s);
  79.                         if (s.contains("getResourceAsStream")) {
  80.                             z = true; // Шоу продолжается!
  81.                         }
  82.                         break;
  83.                     case NAMEANDTYPE:
  84.                     case INTERFACEMETHODREF:
  85.                     case FIELDREF:
  86.                     case INTEGER:
  87.                     case FLOAT:
  88.                         cpool.addElement(new Integer(dis.readInt()));
  89.                         skip += 4;
  90.                         break;
  91.                     case DOUBLE:
  92.                         cpool.addElement(new Double(dis.readDouble()));
  93.                         cpool.addElement(new Double(dis.readDouble()));
  94.                         skip += 16;
  95.                         break;
  96.                     case LONG:
  97.                         cpool.addElement(new Long(dis.readLong()));
  98.                         skip += 8;
  99.                         break;
  100.                     case CLASS:
  101.                     case STRING:
  102.                         cpool.addElement(new Short(dis.readShort()));
  103.                         skip += 2;
  104.                         break;
  105.                 }
  106.             }
  107.  
  108.             if (!z) { // Класс годится для эмуляции
  109.                 return null;
  110.             }
  111.  
  112.             /*
  113.              * Разбор METHODREF записей на составляющие(индекс класса и имя метода с типом возвращаемых значений)
  114.              * проверяем, есть ли нужный нам метод - InputStream getResourceAsStream(String)
  115.              * и изменяем класс, ведь его индекс у нас найдется
  116.              */
  117.             indexC = new Vector();
  118.             int i = 0;
  119.             for (Object e : mref) {
  120.                 int m = ((Integer) e).intValue();
  121.                 int index_class = getClassIndex(getIndex(m, 24));
  122.                 if (getNameAndType(getIndex(m, 8)).equals("name=getResourceAsStream, type=(Ljava/lang/String;)Ljava/io/InputStream;")) {
  123.                     indexC.addElement(temp_i.elementAt(i));
  124.                     cpool.setElementAt(name_class, index_class);
  125.                 }
  126.                 i++;
  127.             }
  128.             code = new byte[(int) fis.getChannel().size() - skip];
  129.             dis.read(code);
  130.             dis.close();
  131.             fis.close();
  132.  
  133.             rebuildClassFile();
  134.  
  135.             return code;
  136.  
  137.         } catch (IOException ex) {
  138.             ex.printStackTrace();
  139.         }
  140.         return null;
  141.     }
  142.  
  143.     private static int getClassIndex(int index) {
  144.         if (tag_cp[index] == CLASS || tag_cp[index] == STRING) {
  145.             Object element = cpool.elementAt(index);
  146.             return ((Short) element).shortValue() - 1;
  147.         } else {
  148.             return index;
  149.         }
  150.     }
  151.  
  152.     private static String getNameAndType(int index) {
  153.         int nat = ((Integer) (cpool.elementAt(index))).intValue();
  154.         String name = (String) cpool.elementAt(getIndex(nat, 24));
  155.         String type = (String) cpool.elementAt(getIndex(nat, 8));
  156.         return "name=" + name + ", type=" + type;
  157.     }
  158.  
  159.     private static void rebuildClassFile() {
  160.         try {
  161.             // Собираем класс заново!
  162.             ByteArrayOutputStream baos = new ByteArrayOutputStream();
  163.             DataOutputStream dos = new DataOutputStream(baos);
  164.             // Constant Pool
  165.             dos.writeInt(MAGIC);
  166.             dos.writeInt(class_version);
  167.             dos.writeShort(count_constants_cp);
  168.             for (int i = 0; i < count_constants_cp - 1; i++) {
  169.                 dos.writeByte(tag_cp[i]);
  170.                 switch (tag_cp[i]) {
  171.                     case UTF8:
  172.                         dos.writeUTF((String) cpool.elementAt(i));
  173.                         break;
  174.                     case NAMEANDTYPE:
  175.                     case INTERFACEMETHODREF:
  176.                     case METHODREF:
  177.                     case FIELDREF:
  178.                     case INTEGER:
  179.                     case FLOAT:
  180.                         dos.writeInt(((Integer) (cpool.elementAt(i))).intValue());
  181.                         break;
  182.                     case DOUBLE:
  183.                         dos.writeDouble(((Double) (cpool.elementAt(i))).doubleValue());
  184.                         dos.writeDouble(((Double) (cpool.elementAt(++i))).doubleValue());
  185.                         break;
  186.                     case LONG:
  187.                         dos.writeLong(((Long) (cpool.elementAt(i))).longValue());
  188.                         break;
  189.                     case CLASS:
  190.                     case STRING:
  191.                         dos.writeShort(((Short) (cpool.elementAt(i))).shortValue());
  192.                         break;
  193.                 }
  194.             }
  195.             ByteArrayInputStream bais = new ByteArrayInputStream(code);
  196.             DataInputStream dis = new DataInputStream(bais);
  197.             int f = fuck_ob ? dis.read() : dis.readUnsignedShort(); // Флаги доступа класса
  198.             dos.writeShort(dis.readUnsignedShort()); // this и super
  199.             dos.writeShort(dis.readUnsignedShort());
  200.             // Интерфейсы
  201.             int count_interfaces = dis.readUnsignedShort(); // Кол-во задействованных интерфейсов
  202.             System.out.println("count_interfaces = " + count_interfaces);
  203.             dos.writeShort(count_interfaces);
  204.             for (int i = 0; i < count_interfaces; i++) {
  205.                 dos.writeShort(dis.readUnsignedShort()); // Запись интерфейса(ссылка на запись в пуле)
  206.             }
  207.             // Переменные
  208.             int count_vars = dis.readUnsignedShort(); // Кол-во переменных
  209.             System.out.println("count_vars = " + count_vars);
  210.             dos.writeShort(count_vars);
  211.             for (int i = 0; i < count_vars; i++) {
  212.                 dos.writeShort(dis.readUnsignedShort()); // Флаг доступа
  213.                 dos.writeShort(dis.readUnsignedShort()); // Ссылка на запись в пуле(имя переменной)
  214.                 dos.writeShort(dis.readUnsignedShort()); // Дескриптор
  215.                 readAttr(dis, dos);
  216.             }
  217.             // Методы
  218.             int count_methods;
  219.             dos.writeShort(count_methods = dis.readUnsignedShort()); // Кол-во методов
  220.             for (int i = 0; i < count_methods; i++) {
  221.                 dos.writeShort(dis.readShort()); // Флаг доступа
  222.                 int name_index = dis.readShort();
  223.                 System.out.println("Loading method: " + cpool.elementAt(name_index - 1));
  224.                 dos.writeShort(name_index);
  225.                 dos.writeShort(dis.readShort()); // Дескриптор
  226.                 int count_attr = dis.readShort();
  227.                 dos.writeShort(count_attr);
  228.                 /*
  229.                  * Тут нас интересует атрибут "Code" и размер стека
  230.                  * Здесь же ищем все опкоды 0xB6 и исправляем
  231.                  */
  232.                 for (int j = 0; j < count_attr; j++) {
  233.                     int attr_name_index = dis.readUnsignedShort();
  234.                     dos.writeShort(attr_name_index);
  235.                     int len = dis.readInt();
  236.                     //System.out.println("len = " + len);
  237.                     dos.writeInt(len);
  238.                     String name = (String) cpool.elementAt(attr_name_index - 1);
  239.                     System.out.println(name);
  240.                     if (name.equals("Code")) {
  241.                         max_stack = dis.readUnsignedShort();
  242.                         int max_locals = dis.readUnsignedShort();
  243.                         int code_length = dis.readInt();
  244.                         byte[] data = new byte[code_length];
  245.                         dis.read(data);
  246.                         byte[] b = editOpcode(data);
  247.                         dos.writeShort(max_stack);
  248.                         dos.writeShort(max_locals);
  249.                         dos.writeInt(code_length);
  250.                         dos.write(b);
  251.                         int exceptions_table_length = dis.readUnsignedShort();
  252.                         dos.writeShort(exceptions_table_length);
  253.                         for (int k = 0; k < exceptions_table_length; k++) {
  254.                             int start_pc = dis.readUnsignedShort();
  255.                             dos.writeShort(start_pc);
  256.                             int end_pc = dis.readUnsignedShort();
  257.                             dos.writeShort(end_pc);
  258.                             int handler_pc = dis.readUnsignedShort();
  259.                             dos.writeShort(handler_pc);
  260.                             int catch_type = dis.readUnsignedShort();
  261.                             dos.writeShort(catch_type);
  262.                         }
  263.                         readAttr(dis, dos);
  264.                     } else {
  265.                         byte[] data = new byte[len];
  266.                         dis.read(data);
  267.                         dos.write(data);
  268.                     }
  269.                 }
  270.             }
  271.             readAttr(dis, dos);
  272.             code = baos.toByteArray();
  273.             dis.close();
  274.             bais.close();
  275.             dos.close();
  276.             baos.close();
  277.         } catch (IOException ex) {
  278.             ex.printStackTrace();
  279.         }
  280.     }
  281.  
  282.     private static void readAttr(DataInputStream dis, DataOutputStream dos) {
  283.         try {
  284.             int count_attr = dis.readUnsignedShort(); // Кол-во атрибутов
  285.             dos.writeShort(count_attr);
  286.             for (int j = 0; j < count_attr; j++) {
  287.                 dos.writeShort(dis.readUnsignedShort()); // Ссылка на запись в пуле(имя атрибута)
  288.                 int len = dis.readInt(); // Длина атрибута
  289.                 dos.writeInt(len);
  290.                 byte[] data = new byte[len];
  291.                 dis.read(data);
  292.                 dos.write(data);
  293.             }
  294.         } catch (IOException ex) {
  295.             ex.printStackTrace();
  296.         }
  297.     }
  298.  
  299.     /*
  300.      *
  301.      * Изменяем опкоды B6 - invokevirtuals на B8 - invokestatic в основном коде!
  302.      * Чтоб получить из этого:
  303.      * getClass().getResourceAs..;
  304.      * вот это:
  305.      * getClass();
  306.      * NewClass.getResourceAs..;
  307.      */
  308.     private static byte[] editOpcode(byte[] code) {
  309.         byte[] data = null;
  310.         ByteArrayInputStream bais = new ByteArrayInputStream(code);
  311.         DataInputStream dis = new DataInputStream(bais);
  312.         ByteArrayOutputStream bois = new ByteArrayOutputStream();
  313.         DataOutputStream dos = new DataOutputStream(bois);
  314.         try {
  315.             int b = 0;
  316.             boolean z = false;
  317.             while ((b = dis.read()) != -1) {
  318.                 z = false;
  319.                 if (b == 0xb6) {
  320.                     int index = dis.readShort();
  321.                     for (Object e : indexC) {
  322.                         if (index == ((Integer) e).intValue()) {
  323.                             max_stack++;
  324.                             dos.write(0xb8);
  325.                             dos.writeShort(index);
  326.                             z = true;
  327.                             break;
  328.                         }
  329.                     }
  330.                     if (!z) {
  331.                         dos.write(b);
  332.                         dos.writeShort(index);
  333.                     }
  334.                 } else {
  335.                     dos.write(b);
  336.                 }
  337.             }
  338.             dis.close();
  339.             bais.close();
  340.             data = bois.toByteArray();
  341.             dos.close();
  342.             bois.close();
  343.         } catch (IOException ex) {
  344.             ex.printStackTrace();
  345.         }
  346.         return data;
  347.     }
  348. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement