From b4c7fe1d0e1f244ed8687d942e42a6623bf51f4e Mon Sep 17 00:00:00 2001 From: Christian Date: Sun, 27 Jan 2013 15:55:37 -0500 Subject: [PATCH] First draft runtime deobf --- .../mods/fml/common/asm/ASMTransformer.java | 4 +- .../asm/transformers/AccessTransformer.java | 5 +- .../DeobfuscationTransformer.java | 44 +++++++++++++++ .../FMLDeobfuscatingRemapper.java | 33 ++++++++++++ .../asm/transformers/MarkerTransformer.java | 4 +- .../asm/transformers/SideTransformer.java | 4 +- .../mods/fml/relauncher/FMLCorePlugin.java | 6 ++- .../fml/relauncher/IClassNameTransformer.java | 7 +++ .../fml/relauncher/IClassTransformer.java | 2 +- .../fml/relauncher/RelaunchClassLoader.java | 54 +++++++++++++++---- 10 files changed, 141 insertions(+), 22 deletions(-) create mode 100644 fml/common/cpw/mods/fml/common/asm/transformers/DeobfuscationTransformer.java create mode 100644 fml/common/cpw/mods/fml/common/asm/transformers/FMLDeobfuscatingRemapper.java create mode 100644 fml/common/cpw/mods/fml/relauncher/IClassNameTransformer.java diff --git a/fml/common/cpw/mods/fml/common/asm/ASMTransformer.java b/fml/common/cpw/mods/fml/common/asm/ASMTransformer.java index a4b106e73..8c7c512c2 100644 --- a/fml/common/cpw/mods/fml/common/asm/ASMTransformer.java +++ b/fml/common/cpw/mods/fml/common/asm/ASMTransformer.java @@ -12,7 +12,7 @@ import cpw.mods.fml.relauncher.IClassTransformer; public class ASMTransformer implements IClassTransformer { @Override - public byte[] transform(String name, byte[] bytes) + public byte[] transform(String name,String transformedName, byte[] bytes) { if ("net.minecraft.src.Block".equals(name)) { @@ -24,7 +24,7 @@ public class ASMTransformer implements IClassTransformer cn.accept(cw); return cw.toByteArray(); } - + return bytes; } diff --git a/fml/common/cpw/mods/fml/common/asm/transformers/AccessTransformer.java b/fml/common/cpw/mods/fml/common/asm/transformers/AccessTransformer.java index bc1a376ef..062d34381 100644 --- a/fml/common/cpw/mods/fml/common/asm/transformers/AccessTransformer.java +++ b/fml/common/cpw/mods/fml/common/asm/transformers/AccessTransformer.java @@ -143,8 +143,9 @@ public class AccessTransformer implements IClassTransformer @SuppressWarnings("unchecked") @Override - public byte[] transform(String name, byte[] bytes) + public byte[] transform(String name, String transformedName, byte[] bytes) { + System.out.printf("AT transforming %s : %s\n",name,transformedName); if (bytes == null) { return null; } if (!modifiers.containsKey(name)) { return bytes; } @@ -375,7 +376,7 @@ public class AccessTransformer implements IClassTransformer for (AccessTransformer trans : transformers) { - entryData = trans.transform(name, entryData); + entryData = trans.transform(name, name, entryData); } } diff --git a/fml/common/cpw/mods/fml/common/asm/transformers/DeobfuscationTransformer.java b/fml/common/cpw/mods/fml/common/asm/transformers/DeobfuscationTransformer.java new file mode 100644 index 000000000..5d361c6e1 --- /dev/null +++ b/fml/common/cpw/mods/fml/common/asm/transformers/DeobfuscationTransformer.java @@ -0,0 +1,44 @@ +package cpw.mods.fml.common.asm.transformers; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.commons.RemappingClassAdapter; +import org.objectweb.asm.tree.ClassNode; + +import cpw.mods.fml.relauncher.IClassNameTransformer; +import cpw.mods.fml.relauncher.IClassTransformer; + +public class DeobfuscationTransformer implements IClassTransformer, IClassNameTransformer { + + @Override + public byte[] transform(String name, String transformedName, byte[] bytes) + { + System.out.println("***" + name + ":"+transformedName); + ClassReader classReader = new ClassReader(bytes); + ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); + RemappingClassAdapter remapAdapter = new RemappingClassAdapter(classWriter, FMLDeobfuscatingRemapper.INSTANCE); + classReader.accept(remapAdapter, ClassReader.EXPAND_FRAMES); + return classWriter.toByteArray(); + } + + @Override + public String remapClassName(String name) + { + return FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.','/')).replace('/', '.'); + } + + @Override + public String unmapClassName(String name) + { + if (name.startsWith("hello.world.")) + { + return name.replace("hello.world.","").replace("LexManos", ""); + } + else + { + return name; + } + } + +} diff --git a/fml/common/cpw/mods/fml/common/asm/transformers/FMLDeobfuscatingRemapper.java b/fml/common/cpw/mods/fml/common/asm/transformers/FMLDeobfuscatingRemapper.java new file mode 100644 index 000000000..70bea79c4 --- /dev/null +++ b/fml/common/cpw/mods/fml/common/asm/transformers/FMLDeobfuscatingRemapper.java @@ -0,0 +1,33 @@ +package cpw.mods.fml.common.asm.transformers; + +import org.objectweb.asm.commons.Remapper; + +public class FMLDeobfuscatingRemapper extends Remapper { + public static final FMLDeobfuscatingRemapper INSTANCE = new FMLDeobfuscatingRemapper(); + + @Override + public String mapFieldName(String owner, String name, String desc) + { + System.out.println("+++" + owner + "."+name+"."+desc); + if (owner.indexOf('/')<0) + { + return "lexManosWasHere"+name; + } + else + { + return name; + } + } + @Override + public String map(String typeName) + { + if (typeName.indexOf('/') < 0) + { + return "hello/world/"+typeName+"LexManos"; + } + else + { + return typeName; + } + } +} diff --git a/fml/common/cpw/mods/fml/common/asm/transformers/MarkerTransformer.java b/fml/common/cpw/mods/fml/common/asm/transformers/MarkerTransformer.java index f9a2985a7..1c9b03707 100644 --- a/fml/common/cpw/mods/fml/common/asm/transformers/MarkerTransformer.java +++ b/fml/common/cpw/mods/fml/common/asm/transformers/MarkerTransformer.java @@ -87,7 +87,7 @@ public class MarkerTransformer implements IClassTransformer @SuppressWarnings("unchecked") @Override - public byte[] transform(String name, byte[] bytes) + public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null) { return null; } if (!markers.containsKey(name)) { return bytes; } @@ -240,7 +240,7 @@ public class MarkerTransformer implements IClassTransformer for (MarkerTransformer trans : transformers) { - entryData = trans.transform(name, entryData); + entryData = trans.transform(name, name, entryData); } } diff --git a/fml/common/cpw/mods/fml/common/asm/transformers/SideTransformer.java b/fml/common/cpw/mods/fml/common/asm/transformers/SideTransformer.java index f4c63ffd0..1b0d7afc5 100644 --- a/fml/common/cpw/mods/fml/common/asm/transformers/SideTransformer.java +++ b/fml/common/cpw/mods/fml/common/asm/transformers/SideTransformer.java @@ -21,7 +21,7 @@ public class SideTransformer implements IClassTransformer private static final boolean DEBUG = false; @SuppressWarnings("unchecked") @Override - public byte[] transform(String name, byte[] bytes) + public byte[] transform(String name, String transformedName, byte[] bytes) { if (bytes == null) { return null; } @@ -69,7 +69,7 @@ public class SideTransformer implements IClassTransformer classNode.accept(writer); return writer.toByteArray(); } - + private boolean remove(List anns, String side) { if (anns == null) diff --git a/fml/common/cpw/mods/fml/relauncher/FMLCorePlugin.java b/fml/common/cpw/mods/fml/relauncher/FMLCorePlugin.java index 093ca092f..b188e993d 100644 --- a/fml/common/cpw/mods/fml/relauncher/FMLCorePlugin.java +++ b/fml/common/cpw/mods/fml/relauncher/FMLCorePlugin.java @@ -13,9 +13,11 @@ public class FMLCorePlugin implements IFMLLoadingPlugin @Override public String[] getASMTransformerClass() { - return new String[] {"cpw.mods.fml.common.asm.transformers.AccessTransformer", + return new String[] { + "cpw.mods.fml.common.asm.transformers.AccessTransformer", "cpw.mods.fml.common.asm.transformers.MarkerTransformer", - "cpw.mods.fml.common.asm.transformers.SideTransformer" + "cpw.mods.fml.common.asm.transformers.SideTransformer", + "cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer", }; } diff --git a/fml/common/cpw/mods/fml/relauncher/IClassNameTransformer.java b/fml/common/cpw/mods/fml/relauncher/IClassNameTransformer.java new file mode 100644 index 000000000..3853e14a6 --- /dev/null +++ b/fml/common/cpw/mods/fml/relauncher/IClassNameTransformer.java @@ -0,0 +1,7 @@ +package cpw.mods.fml.relauncher; + +public interface IClassNameTransformer { + public String remapClassName(String name); + + public String unmapClassName(String name); +} diff --git a/fml/common/cpw/mods/fml/relauncher/IClassTransformer.java b/fml/common/cpw/mods/fml/relauncher/IClassTransformer.java index dd9045b55..d0a8e0fbc 100644 --- a/fml/common/cpw/mods/fml/relauncher/IClassTransformer.java +++ b/fml/common/cpw/mods/fml/relauncher/IClassTransformer.java @@ -2,5 +2,5 @@ package cpw.mods.fml.relauncher; public interface IClassTransformer { - public byte[] transform(String name, byte[] bytes); + public byte[] transform(String name, String transformedName, byte[] bytes); } diff --git a/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java b/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java index f2b48bd64..7b535e1e8 100644 --- a/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java +++ b/fml/common/cpw/mods/fml/relauncher/RelaunchClassLoader.java @@ -39,6 +39,7 @@ public class RelaunchClassLoader extends URLClassLoader private Set classLoaderExceptions = new HashSet(); private Set transformerExceptions = new HashSet(); private Map packageManifests = new HashMap(); + private IClassNameTransformer renameTransformer; private static Manifest EMPTY = new Manifest(); @@ -74,7 +75,12 @@ public class RelaunchClassLoader extends URLClassLoader { try { - transformers.add((IClassTransformer) loadClass(transformerClassName).newInstance()); + IClassTransformer transformer = (IClassTransformer) loadClass(transformerClassName).newInstance(); + transformers.add(transformer); + if (transformer instanceof IClassNameTransformer && renameTransformer == null) + { + renameTransformer = (IClassNameTransformer) transformer; + } } catch (Exception e) { @@ -122,9 +128,11 @@ public class RelaunchClassLoader extends URLClassLoader try { CodeSigner[] signers = null; - int lastDot = name.lastIndexOf('.'); - String pkgname = lastDot == -1 ? "" : name.substring(0, lastDot); - String fName = name.replace('.', '/').concat(".class"); + String transformedName = transformName(name); + String untransformedName = untransformName(name); + int lastDot = untransformedName.lastIndexOf('.'); + String pkgname = lastDot == -1 ? "" : untransformedName.substring(0, lastDot); + String fName = untransformedName.replace('.', '/').concat(".class"); String pkgPath = pkgname.replace('.', '/'); URLConnection urlConnection = findCodeSourceConnectionFor(fName); if (urlConnection instanceof JarURLConnection && lastDot > -1) @@ -136,7 +144,7 @@ public class RelaunchClassLoader extends URLClassLoader Manifest mf = jf.getManifest(); JarEntry ent = jf.getJarEntry(fName); Package pkg = getPackage(pkgname); - getClassBytes(name); + getClassBytes(untransformedName); signers = ent.getCodeSigners(); if (pkg == null) { @@ -169,10 +177,10 @@ public class RelaunchClassLoader extends URLClassLoader FMLLog.severe("The URL %s is defining elements for sealed path %s", urlConnection.getURL(), pkgname); } } - byte[] basicClass = getClassBytes(name); - byte[] transformedClass = runTransformers(name, basicClass); - Class cl = defineClass(name, transformedClass, 0, transformedClass.length, new CodeSource(urlConnection.getURL(), signers)); - cachedClasses.put(name, cl); + byte[] basicClass = getClassBytes(untransformedName); + byte[] transformedClass = runTransformers(untransformedName, transformedName, basicClass); + Class cl = defineClass(transformedName, transformedClass, 0, transformedClass.length, new CodeSource(urlConnection.getURL(), signers)); + cachedClasses.put(transformedName, cl); return cl; } catch (Throwable e) @@ -186,6 +194,30 @@ public class RelaunchClassLoader extends URLClassLoader } } + private String untransformName(String name) + { + if (renameTransformer != null) + { + return renameTransformer.unmapClassName(name); + } + else + { + return name; + } + } + + private String transformName(String name) + { + if (renameTransformer != null) + { + return renameTransformer.remapClassName(name); + } + else + { + return name; + } + } + private boolean isSealed(String path, Manifest man) { Attributes attr = man.getAttributes(path); @@ -221,11 +253,11 @@ public class RelaunchClassLoader extends URLClassLoader } } - private byte[] runTransformers(String name, byte[] basicClass) + private byte[] runTransformers(String name, String transformedName, byte[] basicClass) { for (IClassTransformer transformer : transformers) { - basicClass = transformer.transform(name, basicClass); + basicClass = transformer.transform(name, transformedName, basicClass); } return basicClass; }