Java 使用 ASM 反转 Jar 中的所有字符串
Java reverse all Strings in a Jar with ASM
我试图制作一个程序来反转 jar 中的每个字符串,然后再次执行相同的操作,使其类似于字符串混淆。
例如
普通代码:new String("example");
在 运行 之后:new String(new StringBuilder().append("elpmaxe").reverse().toString()
我的代码:
public class Main {
static String obfuscationFile;
public static void main(String[] args) throws IOException {
obfuscationFile = "C:\Users\Leonhard\Desktop\CrackingTools-v1.0.jar"; // TODO:
// args[0]
File jar = new File(obfuscationFile);
Map<String, byte[]> out = JarUtil.loadNonClassEntries(jar);
Map<String, ClassNode> nodes = JarUtil.loadClasses(jar);
for (ClassNode cn : nodes.values()) {
for (Object mn : cn.methods) {
MethodNode mnode = (MethodNode) mn;
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
if (mnode.name.startsWith("")) {
for (Integer i : reverse(mnode, cw)) {
// TODO: Not needed..
}
}
out.put(cn.name, cw.toByteArray());
}
}
JarUtil.saveAsJarAndClasses(out, nodes, jar.getAbsolutePath().replace(".jar", "") + "_Reverse" + ".jar");
}
private static ArrayList<Integer> reverse(MethodNode method, ClassWriter cw) {
ArrayList<Integer> i = new ArrayList<Integer>();
int e = 0;
for (AbstractInsnNode ain : method.instructions.toArray()) {
e++;
if (ain.getOpcode() == Opcodes.LDC) {
if (ain instanceof LdcInsnNode) {
LdcInsnNode ldc = (LdcInsnNode) ain;
if (ldc.cst instanceof String) {
i.add(e);
ldc.cst = new StringBuilder().append(ldc.cst).reverse().toString();
MethodVisitor mv = null;
mv = cw.visitMethod(method.access, method.name, method.desc, method.signature,
(String[]) method.exceptions.toArray(new String[method.exceptions.size()]));
if (mv != null) {
// mv.visitLineNumber(e, new Label());
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
"(Ljava/lang/String;)Ljava/lang/StringBuilder;", true);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "reverse",
"()Ljava/lang/StringBuilder;", true);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
"()Ljava/lang/String;", true);
mv.visitMaxs(0, 0);
mv.visitEnd();
// System.out.println(method.name + " " +
// method.desc);
}
}
}
}
}
return i;
}
(使用 ASM 5.0.4)
我的错误在哪里/我对 mv.visitMethodInsn() 做错了什么?
编辑:我注意到,它正在与 -noverify 一起使用(但所有字符串都被反转)。没有它我该怎么做才能让它工作?
如果没有关于您遇到的错误或问题的任何信息,很难准确判断出问题所在。但是,我注意到一个错误:
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
"(Ljava/lang/String;)Ljava/lang/StringBuilder;", true);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "reverse",
"()Ljava/lang/StringBuilder;", true);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
"()Ljava/lang/String;", true);
在此代码中,您忘记实际创建您正在使用的 StringBuilder。您需要插入 new
和 invokespecial
指令来创建新的 StringBuilder。
附带说明一下,append 调用是不必要的。您可以将字符串直接传递给 StringBuilder 的构造函数。
我试图制作一个程序来反转 jar 中的每个字符串,然后再次执行相同的操作,使其类似于字符串混淆。 例如
普通代码:new String("example");
在 运行 之后:new String(new StringBuilder().append("elpmaxe").reverse().toString()
我的代码:
public class Main {
static String obfuscationFile;
public static void main(String[] args) throws IOException {
obfuscationFile = "C:\Users\Leonhard\Desktop\CrackingTools-v1.0.jar"; // TODO:
// args[0]
File jar = new File(obfuscationFile);
Map<String, byte[]> out = JarUtil.loadNonClassEntries(jar);
Map<String, ClassNode> nodes = JarUtil.loadClasses(jar);
for (ClassNode cn : nodes.values()) {
for (Object mn : cn.methods) {
MethodNode mnode = (MethodNode) mn;
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
if (mnode.name.startsWith("")) {
for (Integer i : reverse(mnode, cw)) {
// TODO: Not needed..
}
}
out.put(cn.name, cw.toByteArray());
}
}
JarUtil.saveAsJarAndClasses(out, nodes, jar.getAbsolutePath().replace(".jar", "") + "_Reverse" + ".jar");
}
private static ArrayList<Integer> reverse(MethodNode method, ClassWriter cw) {
ArrayList<Integer> i = new ArrayList<Integer>();
int e = 0;
for (AbstractInsnNode ain : method.instructions.toArray()) {
e++;
if (ain.getOpcode() == Opcodes.LDC) {
if (ain instanceof LdcInsnNode) {
LdcInsnNode ldc = (LdcInsnNode) ain;
if (ldc.cst instanceof String) {
i.add(e);
ldc.cst = new StringBuilder().append(ldc.cst).reverse().toString();
MethodVisitor mv = null;
mv = cw.visitMethod(method.access, method.name, method.desc, method.signature,
(String[]) method.exceptions.toArray(new String[method.exceptions.size()]));
if (mv != null) {
// mv.visitLineNumber(e, new Label());
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
"(Ljava/lang/String;)Ljava/lang/StringBuilder;", true);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "reverse",
"()Ljava/lang/StringBuilder;", true);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
"()Ljava/lang/String;", true);
mv.visitMaxs(0, 0);
mv.visitEnd();
// System.out.println(method.name + " " +
// method.desc);
}
}
}
}
}
return i;
}
(使用 ASM 5.0.4)
我的错误在哪里/我对 mv.visitMethodInsn() 做错了什么?
编辑:我注意到,它正在与 -noverify 一起使用(但所有字符串都被反转)。没有它我该怎么做才能让它工作?
如果没有关于您遇到的错误或问题的任何信息,很难准确判断出问题所在。但是,我注意到一个错误:
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
"(Ljava/lang/String;)Ljava/lang/StringBuilder;", true);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "reverse",
"()Ljava/lang/StringBuilder;", true);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
"()Ljava/lang/String;", true);
在此代码中,您忘记实际创建您正在使用的 StringBuilder。您需要插入 new
和 invokespecial
指令来创建新的 StringBuilder。
附带说明一下,append 调用是不必要的。您可以将字符串直接传递给 StringBuilder 的构造函数。