From adedcfda672e753830e2ca927bd4853e42667a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D1=84=D1=80=D0=B5=D0=BC=D0=BE=D0=B2=20=D0=94=D0=BC?= =?UTF-8?q?=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Mon, 28 Feb 2022 15:09:59 +0300 Subject: [PATCH 1/3] Main class reference update in MANIFEST file added (in non-Packager mode). --- .../src/main/java/me/superblaubeere27/jobf/JObfImpl.java | 4 ++-- .../jobf/processors/name/NameObfuscation.java | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java index ae28d3d..13b123b 100644 --- a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java @@ -83,7 +83,7 @@ public class JObfImpl { public static HashMap files = new HashMap<>(); private static List preProcessors; public JObfScript script; - private boolean mainClassChanged; + public boolean mainClassChanged; private final List nameObfuscationProcessors = new ArrayList<>(); private String mainClass; private Map classPath = new HashMap<>(); @@ -112,7 +112,7 @@ public String getMainClass() { return mainClass; } - private void setMainClass(String mainClass) { + public void setMainClass(String mainClass) { this.mainClass = mainClass; } diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java index 441f732..1d4f443 100644 --- a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java @@ -126,6 +126,7 @@ public void transformPost(JObfImpl inst, HashMap nodes) { classWrappers.forEach(classWrapper -> { boolean excluded = this.isClassExcluded(classWrapper); + boolean isMainClass = JObfImpl.INSTANCE.getMainClass().replace('.', '/').equals(classWrapper.originalName); AtomicBoolean builtHierarchy = new AtomicBoolean(false); for (MethodWrapper method : classWrapper.methods) { @@ -179,8 +180,14 @@ public void transformPost(JObfImpl inst, HashMap nodes) { classWrapper.classNode.access &= ~Opcodes.ACC_PRIVATE; classWrapper.classNode.access &= ~Opcodes.ACC_PROTECTED; classWrapper.classNode.access |= Opcodes.ACC_PUBLIC; + String obfuscatedClassName = getPackageName() + NameUtils.generateClassName(); + if (isMainClass) { + JObfImpl.INSTANCE.setMainClass(obfuscatedClassName); + JObfImpl.INSTANCE.mainClassChanged = true; + } + + putMapping(mappings, classWrapper.originalName, obfuscatedClassName); - putMapping(mappings, classWrapper.originalName, getPackageName() + NameUtils.generateClassName()); classCounter.incrementAndGet(); }); From 52f9ceed259361c6d77f660a5ea5d05da160698a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D1=84=D1=80=D0=B5=D0=BC=D0=BE=D0=B2=20=D0=94=D0=BC?= =?UTF-8?q?=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Fri, 25 Mar 2022 09:04:39 +0300 Subject: [PATCH 2/3] 1) FXML file update function 2) AgentLoadClass update functuion 3) Add support for skipping class remap by script --- .../me/superblaubeere27/jobf/JObfImpl.java | 59 ++++++++---- .../jobf/processors/name/NameObfuscation.java | 46 +++++++--- .../jobf/utils/FXMLControllerData.java | 46 ++++++++++ .../jobf/utils/FXMLParser.java | 90 +++++++++++++++++++ .../me/superblaubeere27/jobf/utils/Utils.java | 28 +++++- 5 files changed, 238 insertions(+), 31 deletions(-) create mode 100644 obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLControllerData.java create mode 100644 obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLParser.java diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java index 13b123b..f1cfe19 100644 --- a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java @@ -10,15 +10,7 @@ package me.superblaubeere27.jobf; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -60,10 +52,7 @@ import me.superblaubeere27.jobf.processors.name.NameObfuscation; import me.superblaubeere27.jobf.processors.optimizer.Optimizer; import me.superblaubeere27.jobf.processors.packager.Packager; -import me.superblaubeere27.jobf.utils.ClassTree; -import me.superblaubeere27.jobf.utils.MissingClassException; -import me.superblaubeere27.jobf.utils.NameUtils; -import me.superblaubeere27.jobf.utils.Utils; +import me.superblaubeere27.jobf.utils.*; import me.superblaubeere27.jobf.utils.scheduler.ScheduledRunnable; import me.superblaubeere27.jobf.utils.scheduler.Scheduler; import me.superblaubeere27.jobf.utils.script.JObfScript; @@ -84,8 +73,10 @@ public class JObfImpl { private static List preProcessors; public JObfScript script; public boolean mainClassChanged; + public boolean agentClassChanged; private final List nameObfuscationProcessors = new ArrayList<>(); private String mainClass; + private String agentClass; private Map classPath = new HashMap<>(); private Map hierarchy = new HashMap<>(); private Set libraryClassnodes = new HashSet<>(); @@ -94,6 +85,7 @@ public class JObfImpl { private boolean invokeDynamic; private final JObfSettings settings = new JObfSettings(); private int threadCount = Math.max(1, Runtime.getRuntime().availableProcessors()); + private final Map fxmlControllerClasses = new HashMap<>(); public JObfImpl() { @@ -108,6 +100,12 @@ public static HashMap getClasses() { return classes; } + public FXMLControllerData getFXMLControllerDataByClassName(String className) { + return this.fxmlControllerClasses.values().stream() + .filter(fxmlControllerData -> fxmlControllerData.getOriginalClassName().equals(className)) + .findFirst().orElse(null); + } + public String getMainClass() { return mainClass; } @@ -116,6 +114,14 @@ public void setMainClass(String mainClass) { this.mainClass = mainClass; } + public String getAgentClass() { + return agentClass; + } + + public void setAgentClass(String agentClass) { + this.agentClass = agentClass; + } + public ClassTree getTree(String ref) { if (!hierarchy.containsKey(ref)) { ClassWrapper wrapper = classPath.get(ref); @@ -380,6 +386,7 @@ public void processJar(Configuration config) throws IOException { throw new FileNotFoundException("Could not open output file: " + e.getMessage()); } setMainClass(null); + setAgentClass(null); log.info("... Finished after " + Utils.formatTime(System.currentTimeMillis() - startTime)); @@ -436,6 +443,13 @@ public void processJar(Configuration config) throws IOException { } else { if (entryName.equals("META-INF/MANIFEST.MF")) { setMainClass(Utils.getMainClass(new String(entryData, StandardCharsets.UTF_8))); + setAgentClass(Utils.getAgentClass(new String(entryData, StandardCharsets.UTF_8))); + } + if (entryName.endsWith(".fxml")) { + String className = FXMLParser.getControllerClassName(new ByteArrayInputStream(entryData)); + if (className != null) { + this.fxmlControllerClasses.put(entryName, new FXMLControllerData(className.replace('.', '/'))); + } } files.put(entryName, entryData); @@ -627,13 +641,26 @@ public void processJar(Configuration config) throws IOException { if (entryName.equals("META-INF/MANIFEST.MF")) { if (Packager.INSTANCE.isEnabled()) { entryData = Utils.replaceMainClass(new String(entryData, StandardCharsets.UTF_8), Packager.INSTANCE.getDecryptionClassName()).getBytes(StandardCharsets.UTF_8); - } else if (mainClassChanged) { - entryData = Utils.replaceMainClass(new String(entryData, StandardCharsets.UTF_8), mainClass).getBytes(StandardCharsets.UTF_8); - log.info("Replaced Main-Class with " + mainClass); + } else { + if (mainClassChanged) { + entryData = Utils.replaceMainClass(new String(entryData, StandardCharsets.UTF_8), mainClass).getBytes(StandardCharsets.UTF_8); + log.info("Replaced Main-Class with " + mainClass); + } + if (agentClassChanged) { + entryData = Utils.replaceAgentClass(new String(entryData, StandardCharsets.UTF_8), agentClass).getBytes(StandardCharsets.UTF_8); + log.info("Replaced LoaderAgent-Class with " + agentClass); + + } } + log.info("Processed MANIFEST.MF"); } + if (entryName.endsWith(".fxml") && this.fxmlControllerClasses.containsKey(entryName)) { + entryData = FXMLParser.updateFXML(new ByteArrayInputStream(entryData), this.fxmlControllerClasses.get(entryName)); + log.info("Processed FXML file " + entryName); + + } log.info("Copying " + entryName); diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java index 1d4f443..786c2e6 100644 --- a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java @@ -10,17 +10,6 @@ package me.superblaubeere27.jobf.processors.name; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.regex.Pattern; - import lombok.extern.slf4j.Slf4j; import me.superblaubeere27.jobf.JObfImpl; import me.superblaubeere27.jobf.utils.ClassTree; @@ -38,6 +27,12 @@ import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.MethodNode; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Pattern; + @Slf4j(topic = "obfuscator") public class NameObfuscation implements INameObfuscationProcessor { private static final String PROCESSOR_NAME = "NameObfuscation"; @@ -125,9 +120,16 @@ public void transformPost(JObfImpl inst, HashMap nodes) { AtomicInteger classCounter = new AtomicInteger(); classWrappers.forEach(classWrapper -> { + if (!inst.script.remapClass(classWrapper.classNode)) { + log.info(String.format("Skipping by script: %s", classWrapper.classNode.name)); + return; + } boolean excluded = this.isClassExcluded(classWrapper); boolean isMainClass = JObfImpl.INSTANCE.getMainClass().replace('.', '/').equals(classWrapper.originalName); + boolean isAgentClass = JObfImpl.INSTANCE.getAgentClass().replace('.', '/').equals(classWrapper.originalName); AtomicBoolean builtHierarchy = new AtomicBoolean(false); + boolean isFXMLController = JObfImpl.INSTANCE.getFXMLControllerDataByClassName(classWrapper.originalName) + != null; for (MethodWrapper method : classWrapper.methods) { if ((Modifier.isPrivate(method.methodNode.access) || Modifier.isProtected(method.methodNode.access)) && excluded) @@ -158,7 +160,11 @@ public void transformPost(JObfImpl inst, HashMap nodes) { try { if (!isMethodExcluded(classWrapper.originalName, methodWrapper) && canRenameMethodTree(mappings, new HashSet<>(), methodWrapper, classWrapper.originalName)) { - this.renameMethodTree(mappings, new HashSet<>(), methodWrapper, classWrapper.originalName, NameUtils.generateMethodName(classWrapper.originalName, methodWrapper.originalDescription)); + String newMethodName = NameUtils.generateMethodName(classWrapper.originalName, methodWrapper.originalDescription); + if (isFXMLController) { + JObfImpl.INSTANCE.getFXMLControllerDataByClassName(classWrapper.originalName).addMethodData(methodWrapper.originalName, newMethodName); + } + this.renameMethodTree(mappings, new HashSet<>(), methodWrapper, classWrapper.originalName,newMethodName); } } catch (Exception e) { e.printStackTrace(); @@ -167,7 +173,11 @@ public void transformPost(JObfImpl inst, HashMap nodes) { classWrapper.fields.forEach(fieldWrapper -> { if (!isFieldExcluded(classWrapper.originalName, fieldWrapper) && canRenameFieldTree(mappings, new HashSet<>(), fieldWrapper, classWrapper.originalName)) { - this.renameFieldTree(new HashSet<>(), fieldWrapper, classWrapper.originalName, NameUtils.generateFieldName(classWrapper.originalName), mappings); + String newFieldName = NameUtils.generateFieldName(classWrapper.originalName); + if (isFXMLController) { + JObfImpl.INSTANCE.getFXMLControllerDataByClassName(classWrapper.originalName).addFieldData(fieldWrapper.originalName, newFieldName); + } + this.renameFieldTree(new HashSet<>(), fieldWrapper, classWrapper.originalName, newFieldName, mappings); } }); @@ -185,6 +195,14 @@ public void transformPost(JObfImpl inst, HashMap nodes) { JObfImpl.INSTANCE.setMainClass(obfuscatedClassName); JObfImpl.INSTANCE.mainClassChanged = true; } + if (isAgentClass) { + JObfImpl.INSTANCE.setAgentClass(obfuscatedClassName); + JObfImpl.INSTANCE.agentClassChanged = true; + } + if (isFXMLController) { + JObfImpl.INSTANCE.getFXMLControllerDataByClassName(classWrapper.originalName) + .setObfuscatedClassName(obfuscatedClassName); + } putMapping(mappings, classWrapper.originalName, obfuscatedClassName); @@ -220,7 +238,7 @@ public void transformPost(JObfImpl inst, HashMap nodes) { for (int i = 0; i < copy.methods.size(); i++) { classWrapper.methods.get(i).methodNode = copy.methods.get(i); - /*for (AbstractInsnNode insn : methodNode.instructions.toArray()) { // TODO: Fix lambdas + interface + /*for (AbstractInsnNode insn : classWrapper.methods.get(i).methodNode.instructions.toArray()) { // TODO: Fix lambdas + interface if (insn instanceof InvokeDynamicInsnNode) { InvokeDynamicInsnNode indy = (InvokeDynamicInsnNode) insn; if (indy.bsm.getOwner().equals("java/lang/invoke/LambdaMetafactory")) { diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLControllerData.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLControllerData.java new file mode 100644 index 0000000..c5f5179 --- /dev/null +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLControllerData.java @@ -0,0 +1,46 @@ +package me.superblaubeere27.jobf.utils; + +import java.util.HashMap; + +public class FXMLControllerData { + + private final HashMap fieldsData; + private final HashMap methodsData; + private final String originalClassName; + private String obfuscatedClassName; + + public FXMLControllerData(String originalClassName) { + this.fieldsData = new HashMap<>(); + this.methodsData = new HashMap<>(); + this.originalClassName = originalClassName; + this.obfuscatedClassName = null; + } + + public void addFieldData(String originalName, String obfuscatedName) { + this.fieldsData.put(originalName, obfuscatedName); + } + + public void addMethodData(String originalName, String obfuscatedName) { + this.methodsData.put(originalName, obfuscatedName); + } + + public HashMap getFieldsData() { + return fieldsData; + } + + public HashMap getMethodsData() { + return methodsData; + } + + public String getOriginalClassName() { + return originalClassName; + } + + public String getObfuscatedClassName() { + return obfuscatedClassName; + } + + public void setObfuscatedClassName(String obfuscatedClassName) { + this.obfuscatedClassName = obfuscatedClassName; + } +} diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLParser.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLParser.java new file mode 100644 index 0000000..2a82cbb --- /dev/null +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLParser.java @@ -0,0 +1,90 @@ +package me.superblaubeere27.jobf.utils; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class FXMLParser { + + public static String getControllerClassName(InputStream inputStream) { + try { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(inputStream); + Node rootNode = doc.getDocumentElement(); + Node controllerAttribute = rootNode.getAttributes().getNamedItem("fx:controller"); + if (controllerAttribute != null) { + return controllerAttribute.getNodeValue(); + } + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + return null; + } + + public static byte[] updateFXML(InputStream inputStream, FXMLControllerData controllerData) { + try { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(inputStream); + + if (controllerData.getObfuscatedClassName() != null) { + doc.getDocumentElement().setAttribute("fx:controller", controllerData.getObfuscatedClassName()); + } + + XPath xPath = XPathFactory.newInstance().newXPath(); + + String methodExpression = "//@*[contains(., '#')]"; + NodeList methodNodeList = (NodeList) xPath.compile(methodExpression).evaluate(doc, XPathConstants.NODESET); + + for (int index=0; index < methodNodeList.getLength(); index++) { + Node methodNode = methodNodeList.item(index); + if (controllerData.getMethodsData().containsKey(methodNode.getNodeValue().substring(1))) { + methodNode.setNodeValue("#" + controllerData.getMethodsData().get(methodNode.getNodeValue().substring(1))); + } + } + + String fieldExpression = "//@*[name() = 'fx:id']"; + NodeList fieldsNodeList = (NodeList) xPath.compile(fieldExpression).evaluate(doc, XPathConstants.NODESET); + + for (int index=0; index < fieldsNodeList.getLength(); index++) { + Node fieldNode = fieldsNodeList.item(index); + String a = controllerData.getFieldsData().get(fieldNode.getNodeValue()); + if (controllerData.getFieldsData().containsKey(fieldNode.getNodeValue())) { + fieldNode.setNodeValue(controllerData.getFieldsData().get(fieldNode.getNodeValue())); + } + } + + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + Source source = new DOMSource(doc); + + ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream(); + StreamResult result=new StreamResult(byteArrayOutputStream); + transformer.transform(source, result); + return byteArrayOutputStream.toByteArray(); + } catch (ParserConfigurationException | SAXException | IOException | XPathExpressionException | + TransformerException e) { + e.printStackTrace(); + return null; + } + } + +} diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/Utils.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/Utils.java index f24bba0..8bf30fa 100644 --- a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/Utils.java +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/Utils.java @@ -290,7 +290,21 @@ public static String replaceMainClass(String s, String main) { for (String s1 : s.split("\n")) { if (s1.startsWith("Main-Class")) { - sb.append("Main-Class: ").append(main).append("\n"); + sb.append("Main-Class: ").append(main.replace('/','.')).append("\n"); + } else { + sb.append(s1).append("\n"); + } + } + + return sb.toString(); + } + + public static String replaceAgentClass(String s, String agent) { + StringBuilder sb = new StringBuilder(); + + for (String s1 : s.split("\n")) { + if (s1.startsWith("Launcher-Agent-Class")) { + sb.append("Launcher-Agent-Class: ").append(agent.replace('/','.')).append("\n"); } else { sb.append(s1).append("\n"); } @@ -311,6 +325,18 @@ public static String getMainClass(String s) { return mainClass; } + public static String getAgentClass(String s) { + String agentClass = null; + + for (String s1 : s.split("\n")) { + if (s1.startsWith("Launcher-Agent-Class: ")) { + agentClass = s1.substring("Launcher-Agent-Class: ".length()).trim().replace("\r", ""); + } + } + + return agentClass; + } + public static String getInternalName(Type type) { switch (type.toString()) { From 876a43a238d2923fbd80816150b3543a2d614f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D1=84=D1=80=D0=B5=D0=BC=D0=BE=D0=B2=20=D0=94=D0=BC?= =?UTF-8?q?=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Sat, 2 Apr 2022 17:32:02 +0300 Subject: [PATCH 3/3] ExpireDate processor added --- .../annotations/ObfuscationTransformer.java | 3 +- .../me/superblaubeere27/jobf/JObfImpl.java | 16 +-- .../jobf/processors/ExpireDate.java | 123 ++++++++++++++++++ .../jobf/processors/name/NameObfuscation.java | 4 +- .../jobf/utils/FXMLParser.java | 3 +- 5 files changed, 133 insertions(+), 16 deletions(-) create mode 100644 obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/ExpireDate.java diff --git a/obfuscator-annotations/src/main/java/me/superblaubeere27/annotations/ObfuscationTransformer.java b/obfuscator-annotations/src/main/java/me/superblaubeere27/annotations/ObfuscationTransformer.java index 2076c90..5df29e1 100644 --- a/obfuscator-annotations/src/main/java/me/superblaubeere27/annotations/ObfuscationTransformer.java +++ b/obfuscator-annotations/src/main/java/me/superblaubeere27/annotations/ObfuscationTransformer.java @@ -24,5 +24,6 @@ public enum ObfuscationTransformer { INNER_CLASS_REMOVER, NAME_OBFUSCATION, HIDE_MEMBERS, - INLINING + INLINING, + EXPIREDATE } diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java index f1cfe19..32e8b32 100644 --- a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/JObfImpl.java @@ -34,17 +34,7 @@ import com.google.common.io.ByteStreams; import lombok.extern.slf4j.Slf4j; -import me.superblaubeere27.jobf.processors.CrasherTransformer; -import me.superblaubeere27.jobf.processors.HWIDProtection; -import me.superblaubeere27.jobf.processors.HideMembers; -import me.superblaubeere27.jobf.processors.InlineTransformer; -import me.superblaubeere27.jobf.processors.InvokeDynamic; -import me.superblaubeere27.jobf.processors.LineNumberRemover; -import me.superblaubeere27.jobf.processors.NumberObfuscationTransformer; -import me.superblaubeere27.jobf.processors.ReferenceProxy; -import me.superblaubeere27.jobf.processors.ShuffleMembersTransformer; -import me.superblaubeere27.jobf.processors.StaticInitializionTransformer; -import me.superblaubeere27.jobf.processors.StringEncryptionTransformer; +import me.superblaubeere27.jobf.processors.*; import me.superblaubeere27.jobf.processors.flowObfuscation.FlowObfuscator; import me.superblaubeere27.jobf.processors.name.ClassWrapper; import me.superblaubeere27.jobf.processors.name.INameObfuscationProcessor; @@ -301,6 +291,9 @@ public boolean isLoadedCode(ClassNode classNode) { private void addProcessors() { processors.add(new StaticInitializionTransformer(this)); + processors.add(new ExpireDate(this)); + + processors.add(new HWIDProtection(this)); processors.add(new Optimizer()); processors.add(new InlineTransformer(this)); @@ -314,6 +307,7 @@ private void addProcessors() { processors.add(new ShuffleMembersTransformer(this)); + nameObfuscationProcessors.add(new NameObfuscation()); nameObfuscationProcessors.add(new InnerClassRemover()); processors.add(new CrasherTransformer(this)); diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/ExpireDate.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/ExpireDate.java new file mode 100644 index 0000000..e7e4ab4 --- /dev/null +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/ExpireDate.java @@ -0,0 +1,123 @@ +package me.superblaubeere27.jobf.processors; + +import me.superblaubeere27.annotations.ObfuscationTransformer; +import me.superblaubeere27.jobf.IClassTransformer; +import me.superblaubeere27.jobf.JObfImpl; +import me.superblaubeere27.jobf.ProcessorCallback; +import me.superblaubeere27.jobf.utils.values.DeprecationLevel; +import me.superblaubeere27.jobf.utils.values.EnabledValue; +import me.superblaubeere27.jobf.utils.values.NumberValue; +import me.superblaubeere27.jobf.utils.values.StringValue; +import org.objectweb.asm.*; +import org.objectweb.asm.tree.*; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Calendar; +import java.util.List; +import java.util.Random; + +public class ExpireDate implements IClassTransformer { + + private static final String PROCESSOR_NAME = "ExpireDate"; + + private JObfImpl inst; + private EnabledValue enabled = new EnabledValue(PROCESSOR_NAME, DeprecationLevel.GOOD, true); + private StringValue expireDate = new StringValue(PROCESSOR_NAME, "Exprire Date in format DD\\MM\\YYYY", DeprecationLevel.GOOD, + "01\\01\\2023"); + private StringValue message = new StringValue(PROCESSOR_NAME, "Message", DeprecationLevel.GOOD, + "Expired!"); + private NumberValue chance = new NumberValue<>(PROCESSOR_NAME, "Insert Chance", DeprecationLevel.GOOD, + 30); + private NumberValue dayVariation = new NumberValue<>(PROCESSOR_NAME, "Day variation", DeprecationLevel.GOOD, + 3); + + private static Random random = new Random(); + + private final List exceptions = Arrays.asList( + "java/lang/ClassNotFoundException", + "java/lang/IllegalAccessException", + "java/lang/IllegalArgumentException", + "java/lang/NullPointerException", + "java/lang/NumberFormatException", + "java/lang/UnsupportedOperationException", + "java/lang/ClassCastException"); + + + public ExpireDate(JObfImpl inst) { + this.inst = inst; + } + + @Override + public void process(ProcessorCallback callback, ClassNode node) { + if (!enabled.getObject()) return; + + for (MethodNode method: node.methods) { + if (((method.access & Opcodes.ACC_ABSTRACT) != 0) || + ((method.access & Opcodes.ACC_INTERFACE) != 0) || + method.name.equals("main") || + method.name.equals("") || + method.name.equals("")) { + continue; + } + + callback.setForceComputeFrames(); + if (random.nextInt(100) < chance.getObject()) { + return; + } + try { + method.instructions.insert(getInstructions()); + } catch (ParseException e) { + e.printStackTrace(); + } + } + } + + private InsnList getInstructions() throws ParseException { + Calendar calendar = Calendar.getInstance(); + calendar.setTime((new SimpleDateFormat("dd\\MM\\yyyy")).parse(expireDate.getObject())); + calendar.add(Calendar.DATE, random.nextInt(dayVariation.getObject())); + long expireDateLong = calendar.getTimeInMillis(); + + String exception = exceptions.get(random.nextInt(exceptions.size())); + + InsnList instructions = new InsnList(); + instructions.add(new TypeInsnNode(Opcodes.NEW, "java/util/Date")); + instructions.add(new InsnNode(Opcodes.DUP)); + instructions.add(new LdcInsnNode(expireDateLong)); + instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/util/Date", "", "(J)V",false)); + instructions.add(new TypeInsnNode(Opcodes.NEW, "java/util/Date")); + instructions.add(new InsnNode(Opcodes.DUP)); + instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/util/Date", "", "()V", false)); + instructions.add(new InsnNode(Opcodes.SWAP)); + instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/Date", "after", "(Ljava/util/Date;)Z", false)); + LabelNode label = new LabelNode(); + instructions.add(new JumpInsnNode(Opcodes.IFEQ, label)); + + instructions.add(new TypeInsnNode(Opcodes.NEW, "java/util/Date")); + instructions.add(new InsnNode(Opcodes.DUP)); + instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/util/Date", "", "()V", false)); + instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/Date", "getTime", "()J", false)); + instructions.add(new LdcInsnNode(2L)); + instructions.add(new InsnNode(Opcodes.LREM)); + instructions.add(new InsnNode(Opcodes.LCONST_0)); + instructions.add(new InsnNode(Opcodes.LCMP)); + instructions.add(new JumpInsnNode(Opcodes.IFNE, label)); + + instructions.add(new TypeInsnNode(Opcodes.NEW, exception)); + instructions.add(new InsnNode(Opcodes.DUP)); + instructions.add(new LdcInsnNode(message.getObject())); + instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, exception, "", "(Ljava/lang/String;)V", false)); + instructions.add(new InsnNode(Opcodes.ATHROW)); + instructions.add(label); + return instructions; + } + + @Override + public ObfuscationTransformer getType() { + return ObfuscationTransformer.EXPIREDATE; + } + + +} diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java index 786c2e6..ab77c43 100644 --- a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/processors/name/NameObfuscation.java @@ -125,8 +125,8 @@ public void transformPost(JObfImpl inst, HashMap nodes) { return; } boolean excluded = this.isClassExcluded(classWrapper); - boolean isMainClass = JObfImpl.INSTANCE.getMainClass().replace('.', '/').equals(classWrapper.originalName); - boolean isAgentClass = JObfImpl.INSTANCE.getAgentClass().replace('.', '/').equals(classWrapper.originalName); + boolean isMainClass = JObfImpl.INSTANCE.getMainClass() != null && JObfImpl.INSTANCE.getMainClass().replace('.', '/').equals(classWrapper.originalName); + boolean isAgentClass = JObfImpl.INSTANCE.getAgentClass() != null && JObfImpl.INSTANCE.getAgentClass().replace('.', '/').equals(classWrapper.originalName); AtomicBoolean builtHierarchy = new AtomicBoolean(false); boolean isFXMLController = JObfImpl.INSTANCE.getFXMLControllerDataByClassName(classWrapper.originalName) != null; diff --git a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLParser.java b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLParser.java index 2a82cbb..675cac4 100644 --- a/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLParser.java +++ b/obfuscator-core/src/main/java/me/superblaubeere27/jobf/utils/FXMLParser.java @@ -44,7 +44,7 @@ public static byte[] updateFXML(InputStream inputStream, FXMLControllerData cont Document doc = dBuilder.parse(inputStream); if (controllerData.getObfuscatedClassName() != null) { - doc.getDocumentElement().setAttribute("fx:controller", controllerData.getObfuscatedClassName()); + doc.getDocumentElement().setAttribute("fx:controller", controllerData.getObfuscatedClassName().replace('/','.')); } XPath xPath = XPathFactory.newInstance().newXPath(); @@ -64,7 +64,6 @@ public static byte[] updateFXML(InputStream inputStream, FXMLControllerData cont for (int index=0; index < fieldsNodeList.getLength(); index++) { Node fieldNode = fieldsNodeList.item(index); - String a = controllerData.getFieldsData().get(fieldNode.getNodeValue()); if (controllerData.getFieldsData().containsKey(fieldNode.getNodeValue())) { fieldNode.setNodeValue(controllerData.getFieldsData().get(fieldNode.getNodeValue())); }