我目前正在使用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());
}
我重命名一个方法,该方法返回一个字符串,名为&#34; getToken&#34;到&#34; func_001&#34;! 这非常有效。 但是在另一个类中调用方法,并且方法没有被重命名。所以我需要一些帮助来解决这个问题。
答案 0 :(得分:0)
您需要两次访问所有课程:
在第一轮访问中,仅获得方法名称和描述符的列表(保证在每个范围内都是唯一的)。
此实现将为不同类中具有相同名称和描述的方法赋予相同名称。这可能不是最佳的混淆方法,但是它避免了区分覆盖的方法和恰好被称为相同的方法。
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或外部库中的任何其他方法。为避免这种情况,您可以将要混淆的方法列入白名单,阅读注释以检测被覆盖的方法,然后跳过它们。