Недавно я запрограммировал Обфускатор с ASM на Java и хотел переименовать классы, методы и поля.Но проблема в том, что код не работает, он тоже должен, и я понятия не имею, как это исправить.Проблема в том, что если я запутываю jar, каждый метод в классе переименовывается, но иногда (не каждый раз) часть кода не переименовывается, поэтому jar не может быть выполнен.Например,
public abstract class ColorThread implements Runnable
{
@Getter
private final String name;
@Getter
private Thread thread;
public ColorThread(final String name) {
this.name = name;
Runtime.getRuntime().addShutdownHook(new Thread(this::close));
}
@Override
public void run() {
throw new NotOverriddenException("The Thread \"" + getName() + "\" is not overwritten.");
}
/**
* This method interrupts the running thread.
*/
public void close() {
this.getThread().interrupt();
}
public void start() { //<- Method gets renamed e.g "⢍⢖⣕⠟⡨⠣"
this.thread = new Thread(this, this.getName());
thread.start();
}
}
Так что этот класс запутался, но позже в другом коде, который вызывает:
final ConnectThread connectThread = new ConnectThread();
connectThread.start(); // <- this line
строка с connectThread.start ();не переименовывается в «connectThread. ⢍⢖⣕⠟⡨⠣ ();».Если я использую другой класс, который расширяет ColorThread, например ReceiveThread, метод start переименовывается в этот бит кода.
Я каждый раз боролся с этой проблемой, если создал Obfuscator, и из-за этого я завершил проект.Но теперь я хочу спросить здесь, может ли кто-нибудь помочь мне.Извините за этот длинный пост, но я хотел дать все необходимое, чтобы увидеть проблему.
Проект работает на Java 1.8.0_161 с ASM-All как зависимость.
Чтобы прочитатьЯ использую этот метод.Он будет хранить все классы в ArrayList:
try (final JarFile jarFile = new JarFile(inputFile)) {
final Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
while (jarEntryEnumeration.hasMoreElements()) {
final JarEntry jarEntry = jarEntryEnumeration.nextElement();
if (jarEntry.isDirectory())
continue;
final byte[] bytes = this.readInputStream(jarFile.getInputStream(jarEntry));
if (jarEntry.getName().endsWith(".class")) {
if (jarEntry.getName().endsWith("module-info.class"))
continue;
final ClassNode classNode = new ClassNode();
// new ClassReader(bytes).accept(classNode, ClassReader.EXPAND_FRAMES | ClassReader.SKIP_DEBUG);
new ClassReader(bytes).accept(classNode, ClassReader.EXPAND_FRAMES);
this.classes.add(classNode);
} else {
if (jarEntry.getName().contains("MANIFEST.MF"))
continue;
this.files.put(jarEntry.getName(), bytes);
}
}
this.manifest = jarFile.getManifest();
} catch (final Exception ex) {
ex.printStackTrace();
}
После этого я использую свою систему преобразования для переименования методов:
@Override
public void transform(final ArrayList<ClassNode> classes, final HashMap<String, byte[]> files) {
final String mainClass = this.getJarResources().getManifest().getMainAttributes().getValue("Main-Class").replace(".", "/");
final HashMap<String, String> methodNames = new HashMap<>();
for (final ClassNode classNode : classes) {
for (final Object methodObj : classNode.methods) {
if (!(methodObj instanceof MethodNode))
continue;
final MethodNode methodNode = (MethodNode) methodObj;
if (methodNode.name.equals("<init>"))
continue;
if (methodNode.name.equals(mainClass) || methodNode.name.equals("main"))
continue;
methodNames.put(classNode.name + "." + methodNode.name + methodNode.desc, this.generateString(6));
}
}
this.remapClasses(classes, methodNames);
}
Метод remap выглядит следующим образом:
public void remapClasses(final ArrayList<ClassNode> classes, final HashMap<String, String> remappedNames) {
final SimpleRemapper simpleRemapper = new SimpleRemapper(remappedNames);
for (int index = 0; index < classes.size(); index++) {
final ClassNode realNode = classes.get(index);
final ClassNode copyNode = new ClassNode();
final ClassRemapper classRemapper = new ClassRemapper(copyNode, simpleRemapper);
realNode.accept(classRemapper);
classes.set(index, copyNode);
}
}
В конце я пишу файл:
public void writeFile() {
try (final JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(this.outputFile), this.manifest)) {
for (final ClassNode classNode : this.classes) {
final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
jarOutputStream.putNextEntry(new JarEntry(classNode.name + ".class"));
jarOutputStream.write(writer.toByteArray());
jarOutputStream.closeEntry();
}
for (final Map.Entry<String, byte[]> file : this.files.entrySet()) {
final String filePath = file.getKey();
if(filePath.endsWith(".kotlin_module") || filePath.contains("maven") || filePath.contains("3rd-party-licenses"))
continue;
jarOutputStream.putNextEntry(new JarEntry(filePath));
jarOutputStream.write(file.getValue());
jarOutputStream.closeEntry();
}
} catch (final Exception ex) {
ex.printStackTrace();
}
}