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()) {