简体   繁体   English

ASM Fix其他方法/方法调用

[英]ASM Fix Other Methods / Method Calls

I'm currently working at obfuscation stuff with ASM and need some help at that: 我目前正在使用ASM处理混淆问题,并且需要一些帮助:

My current code is: 我当前的代码是:

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());
    }

I'm renaming a Method, which returns an String, called "getToken" to "func_001"! 我正在重命名一个方法,该方法将一个名为“ getToken”的字符串返回到“ func_001”! This works great. 这很好。 But in an another Class im calling the Method, and there the Method isn't renamed. 但是在另一个调用该方法的类中,该方法未重命名。 So I need some help to fix that. 因此,我需要一些帮助来解决该问题。

You need to visit all classes twice: 您需要两次访问所有课程:

In the first round visit only obtain a list of method names and descriptors (guaranteed to be unique in each scope). 在第一轮访问中,仅获得方法名称和描述符的列表(保证在每个范围内都是唯一的)。

This implementation will give the same name to the methods with the same name and description in different classes. 此实现将为不同类中具有相同名称和描述的方法赋予相同名称。 This may not be optimal obfuscation-wise but it avoids differentiating between overridden methods and methods that just happen to be called the same. 这可能不是最佳的混淆方法,但是它避免了在覆盖的方法和恰好被称为相同的方法之间进行区分。

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

The visitor is not connected to the writer, because no modification has been done yet. visitor未连接到编写者,因为尚未进行任何修改。

Then map each name to a new obfuscated name (maybe random numbers or just number the methods): 然后将每个名称映射到一个新的模糊名称(可以是随机数,也可以只是对方法编号):

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);
}

Finally, visit each method body to edit each method call instruction accordingly and save the modified result. 最后,访问每个方法主体以相应地编辑每个方法调用指令并保存修改后的结果。

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());
}

Note : you will have problems with overridden methods from classes that you are not modifying such as String toString() from Object or any other from Java or external libraries. 注意 :您将遇到未修改类的重写方法的问题,例如Object String toString()或Java或外部库的任何其他方法。 To avoid this, you could either have a whitelist of the methods you want to obfuscate, read the annotations to detect overridden methods and skip them, for example. 为了避免这种情况,您可以将要混淆的方法列入白名单,例如阅读注释以检测被覆盖的方法并跳过它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM