diff --git a/README.md b/README.md index a821f2a..eef5fb6 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,11 @@ Caesium is a powerful Java bytecode obfuscator written by [sim0n](https://github * Polymorph * Reference (invokedynamics) * String +* Trim (Currently only trims math functions) ## Notes You have to add every dependency your jar relies on. +Caesium is very optimised and the performance loss shouldn't be more than 5-10% (unless you're using reference mutation) ## Usage - Run the jar. diff --git a/pom.xml b/pom.xml index f45aad0..5b5b7e5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.sim0n caesium - 1.0.8 + 1.0.9 diff --git a/src/main/java/dev/sim0n/caesium/mutator/impl/NumberMutator.java b/src/main/java/dev/sim0n/caesium/mutator/impl/NumberMutator.java index 7d7523a..2a52831 100644 --- a/src/main/java/dev/sim0n/caesium/mutator/impl/NumberMutator.java +++ b/src/main/java/dev/sim0n/caesium/mutator/impl/NumberMutator.java @@ -42,7 +42,7 @@ public void handle(ClassWrapper wrapper) { } while ((insn = insn.getNext()) != null); }); - if (numbers > 5000) // this is wayyy too much + if (numbers > 1000) // this is wayyy too much return; insns.forEach(instructions -> { diff --git a/src/main/java/dev/sim0n/caesium/mutator/impl/ReferenceMutator.java b/src/main/java/dev/sim0n/caesium/mutator/impl/ReferenceMutator.java index 88e313e..7a33b91 100644 --- a/src/main/java/dev/sim0n/caesium/mutator/impl/ReferenceMutator.java +++ b/src/main/java/dev/sim0n/caesium/mutator/impl/ReferenceMutator.java @@ -90,7 +90,6 @@ public void handle(ClassWrapper wrapper) { newSig = Type.getMethodDescriptor(origReturnType, args); - switch (opcode) { case INVOKEVIRTUAL: case INVOKESTATIC: diff --git a/src/main/java/dev/sim0n/caesium/mutator/impl/StringMutator.java b/src/main/java/dev/sim0n/caesium/mutator/impl/StringMutator.java index 3bb3e2f..5153379 100644 --- a/src/main/java/dev/sim0n/caesium/mutator/impl/StringMutator.java +++ b/src/main/java/dev/sim0n/caesium/mutator/impl/StringMutator.java @@ -31,6 +31,8 @@ public class StringMutator extends ClassMutator { private String keyField = getRandomName(); private String decryptMethodName = getRandomName(); + private String initName; + private String bsmName = getRandomName(); private String bsmSig = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/Object;"; private Handle bsmHandle = null; @@ -60,6 +62,7 @@ public void handle(ClassWrapper wrapper) { keyField = getRandomName(); decryptMethodName = getRandomName(); + initName = getRandomName(); bsmName = getRandomName(); bsmHandle = new Handle(H_INVOKESTATIC, target.name, bsmName, bsmSig); @@ -197,7 +200,7 @@ public String encryptString(String s) { instance.init(Cipher.ENCRYPT_MODE, keyFactory.generateSecret(new DESKeySpec(keys)), new IvParameterSpec(new byte[8])); - return new String(Base64.getEncoder().encode(instance.doFinal(s.getBytes(Charsets.ISO_8859_1)))); + return new String(Base64.getEncoder().encode(instance.doFinal(s.getBytes(Charsets.UTF_8)))); } catch (Exception e) { e.printStackTrace(); } @@ -439,13 +442,13 @@ public InsnList getClinitInstructions(ClassNode owner) { LabelNode l2 = new LabelNode(); instructions.add(l2); - instructions.add(new MethodInsnNode(INVOKESTATIC, owner.name, "_init", "()V", false)); + instructions.add(new MethodInsnNode(INVOKESTATIC, owner.name, initName, "()V", false)); return instructions; } public MethodNode makeInit(ClassNode owner) { - MethodNode mv = new MethodNode(ACC_PRIVATE + ACC_STATIC, "_init","()V", null,null); + MethodNode mv = new MethodNode(ACC_PRIVATE + ACC_STATIC, initName,"()V", null,null); mv.visitCode(); Label l0 = new Label(); @@ -604,8 +607,9 @@ public MethodNode makeInit(ClassNode owner) { mv.visitLabel(l19); mv.visitLineNumber(126, l19); mv.visitFrame(F_SAME, 0, null, 0, null); + // TODO: this can break classes with huge amount of strings // generate completely random fake strings - for (int i = 0; i < stringCount * ThreadLocalRandom.current().nextInt(5, 20); i++) { + for (int i = 0; i < 1; i++) { mv.visitFieldInsn(GETSTATIC, owner.name, stringField2, "[Ljava/lang/String;"); ASMUtil.visitOptimisedInt(mv, i); @@ -622,7 +626,7 @@ public MethodNode makeInit(ClassNode owner) { mv.visitLineNumber(130, l21); mv.visitFrame(F_SAME, 0, null, 0, null); // generate completely random fake strings - for (int i = 0; i < Math.min(5, stringCount) * ThreadLocalRandom.current().nextInt(5, 20); i++) { + for (int i = 0; i < 1; i++) { mv.visitFieldInsn(GETSTATIC, owner.name, stringField2, "[Ljava/lang/String;"); ASMUtil.visitOptimisedInt(mv, i); diff --git a/src/main/java/dev/sim0n/caesium/util/classwriter/CaesiumClassWriter.java b/src/main/java/dev/sim0n/caesium/util/classwriter/CaesiumClassWriter.java index 33e24df..350d0bb 100644 --- a/src/main/java/dev/sim0n/caesium/util/classwriter/CaesiumClassWriter.java +++ b/src/main/java/dev/sim0n/caesium/util/classwriter/CaesiumClassWriter.java @@ -13,6 +13,8 @@ import dev.sim0n.caesium.exception.CaesiumException; import dev.sim0n.caesium.util.wrapper.impl.ClassWrapper; +import javax.swing.*; + public class CaesiumClassWriter extends ClassWriter { public CaesiumClassWriter(int flags) { super(flags); @@ -30,6 +32,7 @@ protected String getCommonSuperClass(final String type1, final String type2) { // TODO Auto-generated catch block e.printStackTrace(); } + String second = null; try { second = deriveCommonSuperName(type2, type1); @@ -37,6 +40,7 @@ protected String getCommonSuperClass(final String type1, final String type2) { // TODO Auto-generated catch block e.printStackTrace(); } + if (!"java/lang/Object".equals(first)) return first; @@ -49,9 +53,8 @@ protected String getCommonSuperClass(final String type1, final String type2) { // TODO Auto-generated catch block e.printStackTrace(); } - return "java/lang/Object"; - + return "java/lang/Object"; } private String deriveCommonSuperName(String type1, String type2) throws CaesiumException { @@ -74,8 +77,10 @@ else if (Modifier.isInterface(first.access) || Modifier.isInterface(second.acces private ClassNode returnClazz(String ref) throws CaesiumException { ClassWrapper clazz = PreRuntime.getClassPath().get(ref); - if (clazz == null) + if (clazz == null) { + JOptionPane.showMessageDialog(null, "Couldn't find " + ref + " in classpath.", "Error", JOptionPane.ERROR_MESSAGE); throw new CaesiumException(ref + " does not exist in classpath!", null); + } return clazz.node; } @@ -83,15 +88,17 @@ private ClassNode returnClazz(String ref) throws CaesiumException { private boolean isAssignableFrom(String type1, String type2) throws CaesiumException { if ("java/lang/Object".equals(type1)) return true; + if (type1.equals(type2)) return true; returnClazz(type1); returnClazz(type2); ClassTree firstTree = getTree(type1); - if (firstTree == null) { + + if (firstTree == null) throw new CaesiumException("Could not find " + type1 + " in the built class hierarchy", null); - } + Set allChildren = new HashSet<>(); Deque toProcess = new ArrayDeque<>(firstTree.subClasses); while (!toProcess.isEmpty()) {