Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.File;
- import java.io.IOException;
- import java.util.HashMap;
- import java.util.Map;
- import org.objectweb.asm.Opcodes;
- import org.objectweb.asm.commons.ClassRemapper;
- import org.objectweb.asm.commons.Remapper;
- import org.objectweb.asm.tree.AbstractInsnNode;
- import org.objectweb.asm.tree.ClassNode;
- import org.objectweb.asm.tree.InsnList;
- import org.objectweb.asm.tree.InvokeDynamicInsnNode;
- import org.objectweb.asm.tree.LdcInsnNode;
- import org.objectweb.asm.tree.MethodInsnNode;
- import org.objectweb.asm.tree.MethodNode;
- public class Transformer {
- public static void main(String[] args) throws IOException {
- Map<String, ClassNode> map = Utils.loadClasses(new File("CPSMod.jar"));
- Map<String, byte[]> out = new HashMap<>();
- // Patch bytecode bugs
- for (ClassNode cn : map.values()) {
- for (MethodNode mn : cn.methods) {
- InsnList ins = mn.instructions;
- removePops(ins);
- decryptSwaps(ins);
- decryptInvokeDynamics(ins);
- decryptStrings(ins);
- }
- }
- // Rename
- Remapper remapper = new MemberRemapper(map);
- for (ClassNode cn : map.values()) {
- ClassNode node = new ClassNode();
- ClassRemapper adapter = new ClassRemapper(node, remapper);
- cn.accept(adapter);
- map.put(cn.name, node);
- }
- // Recompile
- for (ClassNode cn : map.values())
- out.put(cn.name, Utils.getNodeBytes(cn, true));
- Utils.saveAsJar(out, "updated.jar");
- }
- private static void decryptSwaps(InsnList ins) {
- for (int i = 0; i < ins.size(); i++) {
- AbstractInsnNode ain = ins.get(i);
- if (ain.getOpcode() == Opcodes.SWAP) {
- AbstractInsnNode v1 = ain.getPrevious();
- AbstractInsnNode v2 = ain.getPrevious().getPrevious();
- if (Utils.isConstant(v1) && Utils.isConstant(v2)) {
- ins.remove(v2);
- ins.remove(v1);
- ins.insertBefore(ain, v1);
- ins.insertBefore(ain, v2);
- ins.remove(ain);
- }
- }
- }
- }
- private static void removePops(InsnList ins) {
- for (int i = 0; i < ins.size(); i++) {
- AbstractInsnNode ain = ins.get(i);
- if (ain.getOpcode() == Opcodes.POP) {
- int value = Utils.getPushValue(ain.getPrevious());
- if (value >= 1) {
- ins.remove(ain.getPrevious());
- ins.remove(ain);
- }
- } else if (ain.getOpcode() == Opcodes.POP2) {
- int value1 = Utils.getPushValue(ain.getPrevious());
- int value2 = Utils.getPushValue(ain.getPrevious().getPrevious());
- int sum = value1 + value2;
- if (value1 > 0 && value2 > 0 && sum >= 2) {
- ins.remove(ain.getPrevious());
- ins.remove(ain.getPrevious());
- ins.remove(ain);
- }
- }
- }
- }
- private static void decryptInvokeDynamics(InsnList ins) {
- for (int i = 0; i < ins.size(); i++) {
- AbstractInsnNode ain = ins.get(i);
- if (ain.getOpcode() == Opcodes.INVOKEDYNAMIC) {
- InvokeDynamicInsnNode dyn = (InvokeDynamicInsnNode) ain;
- if (dyn.bsmArgs.length == 4) {
- int opcode = (int) dyn.bsmArgs[0];
- String owner = ((String) dyn.bsmArgs[1]).replace(".", "/");
- String name = (String) dyn.bsmArgs[2];
- String desc = (String) dyn.bsmArgs[3];
- boolean itf = opcode == Opcodes.INVOKEINTERFACE;
- ins.set(ain, new MethodInsnNode(opcode, owner, name, desc, itf));
- }
- }
- }
- }
- private static void decryptStrings(InsnList ins) {
- for (int i = 0; i < ins.size(); i++) {
- AbstractInsnNode ain = ins.get(i);
- if (ain.getOpcode() == Opcodes.LDC && ain.getNext().getOpcode() == Opcodes.INVOKESTATIC) {
- LdcInsnNode ldc = (LdcInsnNode) ain;
- MethodInsnNode min = (MethodInsnNode) ain.getNext();
- if (min.desc.equals("(Ljava/lang/String;)Ljava/lang/String;")) {
- String decrypt = decrypt(ldc.cst.toString());
- ins.remove(ldc);
- ins.set(min, new LdcInsnNode(decrypt));
- }
- }
- }
- }
- public static String decrypt(String s) {
- final int length = s.length();
- int counter = length - 1;
- int i = length - 1;
- final char[] arrOut = new char[length];
- while (i >= 0) {
- final int counterCopy = counter;
- final char char1 = s.charAt(counterCopy);
- --counter;
- arrOut[counterCopy] = (char) (char1 ^ (3 << 3 ^ 0x2));
- if (counter < 0) {
- break;
- }
- final int counterM1 = counter--;
- arrOut[counterM1] = (char) (s.charAt(counterM1) ^ ((0x3 ^ 0x5) << 4 ^ 0x5));
- i = counter;
- }
- return new String(arrOut);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment