31.12.2013 / 14:51 | |
kiriman Пользователь Сейчас: Offline
Имя: Кирилл Откуда: Красноярск Регистрация: 18.01.2010
| Наверное надо все methodref читать и проверять из чего они состоят. А потом менять у них класс, если name называется getResourceAsStream, а тип (Ljava/lang/String Ljava/io/InputStream; ! При этом надеясь, что в другом классе нет реализации getResourceAsStream(ну или заморочиться и проверять) |
31.12.2013 / 16:25 | |
kiriman Пользователь Сейчас: Offline
Имя: Кирилл Откуда: Красноярск Регистрация: 18.01.2010
| Наброски есть. Точнее уже почти все
|
31.12.2013 / 16:54 | |
kiriman Пользователь Сейчас: Offline
Имя: Кирилл Откуда: Красноярск Регистрация: 18.01.2010
| Найк, пиши/звони в скайп kiriman90. Там помогу
|
31.12.2013 / 18:36 | |
kiriman Пользователь Сейчас: Offline
Имя: Кирилл Откуда: Красноярск Регистрация: 18.01.2010
| Кстати говоря, помогу не словом, а кодом) Вот наброски http://pastebin.com/3CvQ9RgB |
31.12.2013 / 18:47 | |
kiriman Пользователь Сейчас: Offline
Имя: Кирилл Откуда: Красноярск Регистрация: 18.01.2010
| Вот так справились с кпулом) Осталось в основном коде поменять опкоды и все сохранить.
|
31.12.2013 / 21:21 | |
Naik Пользователь Сейчас: Offline
Имя: %name% Регистрация: 14.03.2010
| kiriman (31.12.2013/16:54) Найк, пиши/звони в скайп kiriman90. Там помогуспс, но сейчас вряд ли, конкурс то идет) Код гляну, спасибо.
Через javaassist практически сделал замену, но не собирается измененный класс, т.к. не видит ни одного системного класса, придется вручную заменять, а жалко, там удобное API именно для таких целей есть.
Изменено Naik (31.12 / 21:31) (всего 1 раз) |
31.12.2013 / 21:23 | |
kiriman Пользователь Сейчас: Offline
Имя: Кирилл Откуда: Красноярск Регистрация: 18.01.2010
| Naik, да я уже сам почти написал
|
31.12.2013 / 21:36 | |
kiriman Пользователь Сейчас: Offline
Имя: Кирилл Откуда: Красноярск Регистрация: 18.01.2010
| Вот такой вот вроде рабочий говнокод http://pastebin.com/XGRRAdh5Всегда пожалуйста |
31.12.2013 / 22:32 | |
kiriman Пользователь Сейчас: Offline
Имя: Кирилл Откуда: Красноярск Регистрация: 18.01.2010
| Немного косячно, разберусь завтра. Не все опкоды исправляет
|
31.12.2013 / 22:50 | |
Naik Пользователь Сейчас: Offline
Имя: %name% Регистрация: 14.03.2010
| kiriman, Что-то у меня не работает вообще. Вызываю ModifyClass.work("/dir/my.class", "/dir/_converted/my.class") и выдает EOFException (помечено где в комментарии). Вот код. Прикрепил тестовый мидлет и выхлоп твоего класса. Открыть спойлер Закрыть спойлер package ua.naiksoftware.j2meloader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Vector;
import filelog.Log;
import java.io.File;
/**
*
* @author kiriman
*/
public class ModifyClass {
private static String pathToClass, saveToClass;
private static final String tag = ModifyClass.class.getName();
private static final int MAGIC = 0xCAFEBABE; // О_о
public static final int CLASS = 7;
public static final int FIELDREF = 9;
public static final int METHODREF = 10;
public static final int INTERFACEMETHODREF = 11;
public static final int STRING = 8;
public static final int INTEGER = 3;
public static final int FLOAT = 4;
public static final int LONG = 5;
public static final int DOUBLE = 6;
public static final int NAMEANDTYPE = 12;
public static final int UTF8 = 1;
private static int class_version, // версия класса
count_constants_cp; // количество констант
private static byte[] tag_cp, // тэги записей в пуле
code; // основной код
private static Vector cpool, mref, // сами записи
indexC;
public static void work(String path, String save) {
Log.d(tag, "in: " + path + " out: " + save);
pathToClass = path;
saveToClass = save;
if (!isModifyClass()) {
Log.d(tag, "no");
} else {
Log.d(tag, "yes");
}
}
private static int divInt(int p, int l) {
int a1, a2;
a1 = (p >> l) & 0xff;
a2 = (p >> (l - 8)) & 0xff;
return ((a1 << 8) | (a2)) - 1;
}
private static boolean isModifyClass() {
try {
FileInputStream fis = new FileInputStream(pathToClass);
DataInputStream dis = new DataInputStream(fis);
dis.readInt(); // MAGIC
class_version = dis.readInt();
count_constants_cp = dis.readShort();
tag_cp = new byte[count_constants_cp];
cpool = new Vector();
mref = new Vector(); // для METHODREF записей
Vector temp_i = new Vector();
int skip = 10; // кол-во прочтенных байт(int + int + short)
boolean z = false;
for (int i = 0; i < count_constants_cp; i++) {
tag_cp[i] = dis.readByte();
skip++;
switch (tag_cp[i]) {
case METHODREF:
int lol = dis.readInt();
temp_i.addElement(new Integer(i + 1));
cpool.addElement(new Integer(lol));
mref.addElement(new Integer(lol));
skip += 4;
break;
case UTF8:
String s = dis.readUTF();
skip += s.length() + 2;
cpool.addElement(s);
if (s.contains("getResourceAsStream")) {
z = true; // шоу продолжается!
}
break;
case NAMEANDTYPE:
case INTERFACEMETHODREF:
case FIELDREF:
case INTEGER:
case FLOAT:
cpool.addElement(new Integer(dis.readInt()));
skip += 4;
break;
case DOUBLE:
case LONG:
cpool.addElement(new Long(dis.readLong()));
skip += 8;
break;
case CLASS:
case STRING:
cpool.addElement(new Short(dis.readShort()));
skip += 2;
break;
}
}
if (!z) { // класс годится для эмуляции
return false;
}
/*
* разбор METHODREF записей на составляющие(индекс класса и имя метода с типом возвращаемых значений)
* проверяем, есть ли нужный нам метод - InputStream getResourceAsStream(String)
* и изменяем класс, ведь его индекс у нас найдется
*/
indexC = new Vector();
int i = 0;
for (Object e : mref) {
int m = ((Integer) e).intValue();
int class_index = divInt(m, 24);
class_index = getClassIndex(class_index);
int nat_index = divInt(m, 8);
if (getNameAndType(nat_index).equals("name=getResourceAsStream, type=(Ljava/lang/String;)Ljava/io/InputStream;")) {
indexC.addElement(temp_i.elementAt(i));
cpool.setElementAt("SomeClass", class_index); // аллилуйя!!!
}
i++;
}
code = new byte[(int) fis.getChannel().size() - skip];
dis.read(code);
dis.close();
fis.close();
skip = 0;
mref = null;
editOpcode();
} catch (IOException ex) {
Log.d(tag, ex.getMessage());
throw new RuntimeException(ex);
}
return true;
}
private static int getClassIndex(int index) {
Object element = cpool.elementAt(index);
int k = ((Short) element).shortValue() - 1;
if (tag_cp[index] == CLASS) {
return k;
} else {
return index;
}
}
private static String getNameAndType(int index) {
int nat = ((Integer) (cpool.elementAt(index))).intValue();
int index_name = divInt(nat, 24);
String name = (String) cpool.elementAt(index_name);
int index_type = divInt(nat, 8);
String type = (String) cpool.elementAt(index_type);
return "name=" + name + ", type=" + type;
}
/*
*
* Изменяем опкоды B6 - invokevirtuals на B8 - invokestatic в основном коде!
* Чтоб получить из этого:
* getClass().getResourceAs..
* вот это:
* SomeClass.getResourceAs..
*/
private static void editOpcode() {
try {
// Собираем класс заново!
File file = new File(saveToClass);
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
// Constant Pool
dos.writeInt(MAGIC);
dos.writeInt(class_version);
dos.writeShort(count_constants_cp);
for (int i = 0; i < count_constants_cp; i++) {
dos.writeByte(tag_cp[i]);
switch (tag_cp[i]) {
case UTF8:
dos.writeUTF((String) cpool.elementAt(i));
break;
case NAMEANDTYPE:
case INTERFACEMETHODREF:
case METHODREF:
case FIELDREF:
case INTEGER:
case FLOAT:
dos.writeInt(((Integer) (cpool.elementAt(i))).intValue());
break;
case DOUBLE:
case LONG:
dos.writeLong(((Long) (cpool.elementAt(i))).longValue());
break;
case CLASS:
case STRING:
dos.writeShort(((Short) (cpool.elementAt(i))).shortValue());
break;
}
}
// Code
ByteArrayInputStream bais = new ByteArrayInputStream(code);
DataInputStream dis = new DataInputStream(bais);
int b = 0;
boolean z = false;
while ((b = dis.read()) != -1) {
z = false;
int index = dis.readShort(); // ТУТ ОШЫПКА
if (b == 182) {
for (Object e : indexC) {
if (index == ((Integer) e).intValue()) {
dos.write(184);
dos.writeShort(index);
z = true;
break;
}
}
}
if (!z) {
dos.write(b);
dos.writeShort(index);
}
}
code = null;
dis.close();
bais.close();
dos.close();
fos.close();
} catch (IOException ex) {
Log.d(tag, ex.getMessage());
throw new RuntimeException(ex);
}
}
}
Попробовал еще 1 мидлет, тоже запинается на первом классе. Изменено Naik (31.12 / 22:59) (всего 1 раз)
Прикрепленные файлы: Test.jar (2.12 кб.) Скачано 242 раза Main.class.jar (0.63 кб.) Скачано 223 раза |