Как исправить проблему переименования этого метода с Java 8 ASM - PullRequest
1 голос
/ 27 сентября 2019

Недавно я запрограммировал Обфускатор с 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();
        }
    }
...