ASM исправить другие методы / вызовы методов - PullRequest
0 голосов
/ 06 мая 2018

В настоящее время я работаю над запутыванием вещей с ASM и мне нужна помощь в этом:

Мой текущий код:

public void renameMethods()
    {
        Map<String, byte[]> generatedOutput = new HashMap<>();

        for (ClassNode classNode : classes.values())
        {
            ClassWriter classWriter = new ClassWriter(0);
            ClassVisitor classVisitor = new ClassVisitor(ASM4, classWriter)
            {
                @Override
                public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
                {
                    if (name.equals("getToken") && desc.equals("(I)Ljava/lang/String;"))
                    {
                        return super.visitMethod(access, "func_001", desc, signature, exceptions);
                    }
                    return super.visitMethod(access, name, desc, signature, exceptions);
                }
            };
            classNode.accept(classVisitor);
            generatedOutput.put(classNode.name, classWriter.toByteArray());
        }

        JarUtils.saveAsJar(out, outputJar.getAbsolutePath());
    }

Я переименовываю метод, который возвращает строку, называемую «getToken», в «func_001»! Это прекрасно работает. Но в другом классе я называю метод, и там метод не переименовывается. Поэтому мне нужна помощь, чтобы это исправить.

1 Ответ

0 голосов
/ 10 июля 2018

Вам нужно посетить все классы дважды:

В первом посещении раунда получите только список имен методов и дескрипторов (гарантированно уникальных в каждой области).

Эта реализация даст одно и то же имя методам с одинаковым именем и описанием в разных классах. Это может быть неоптимальным с точки зрения запутывания, но позволяет избежать дифференциации переопределенных методов и методов, которые просто называются одинаковыми.

final List<String> methods = new ArrayList<>();
for (ClassNode classNode : classes.values()) {
    for (MethodNode methodNode : classNode.methods) {
        methods.add(methodNode.name + methodNode.desc);
    }
}

visitor не подключен к устройству записи, поскольку никаких изменений еще не было сделано.

Затем сопоставьте каждое имя с новым запутанным именем (может быть, случайными числами или просто нумерацией методов):

final Map<String, String> map = new HashMap<>();
for (int i = 0; i < methods.size(); i++) {
    String obfName = String.format("func_%03d", i);
    map.put(methods.get(i), obfName);
}

Наконец, посетите каждое тело метода, чтобы соответствующим образом отредактировать каждую инструкцию вызова метода и сохранить измененный результат.

for (ClassNode classNode : classes.values()) {
    ClassWriter classWriter = new ClassWriter(0);
    ClassVisitor visitor = new ClassVisitor(ASM4, classWriter) {
        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            final MethodVisitor mv = super.methodVisitor(access, name, desc, signature, exceptions);
            return new AdviceAdapter(ASM4, mv, access, name, desc) {
                @Override
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    String newName = map.getOrDefault(name + desc, name);
                    return super.visitMethodInsn(opcode, owner, newName, desc, itf);
                }
            };
        }
    };
    classNode.accept(classVisitor);
    generatedOutput.put(classNode.name, classWriter.toByteArray());
}

Примечание : у вас будут проблемы с переопределенными методами из классов, которые вы не изменяете, например String toString() из Object или любых других из Java или внешних библиотек. Чтобы избежать этого, у вас может быть белый список методов, которые вы хотите скрыть, прочитать аннотации, чтобы обнаружить переопределенные методы и пропустить их, например.

...