First draft runtime deobf

This commit is contained in:
Christian 2013-01-27 15:55:37 -05:00
parent 5c99e3488a
commit b4c7fe1d0e
10 changed files with 141 additions and 22 deletions

View file

@ -12,7 +12,7 @@ import cpw.mods.fml.relauncher.IClassTransformer;
public class ASMTransformer implements IClassTransformer public class ASMTransformer implements IClassTransformer
{ {
@Override @Override
public byte[] transform(String name, byte[] bytes) public byte[] transform(String name,String transformedName, byte[] bytes)
{ {
if ("net.minecraft.src.Block".equals(name)) if ("net.minecraft.src.Block".equals(name))
{ {
@ -24,7 +24,7 @@ public class ASMTransformer implements IClassTransformer
cn.accept(cw); cn.accept(cw);
return cw.toByteArray(); return cw.toByteArray();
} }
return bytes; return bytes;
} }

View file

@ -143,8 +143,9 @@ public class AccessTransformer implements IClassTransformer
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @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 (bytes == null) { return null; }
if (!modifiers.containsKey(name)) { return bytes; } if (!modifiers.containsKey(name)) { return bytes; }
@ -375,7 +376,7 @@ public class AccessTransformer implements IClassTransformer
for (AccessTransformer trans : transformers) for (AccessTransformer trans : transformers)
{ {
entryData = trans.transform(name, entryData); entryData = trans.transform(name, name, entryData);
} }
} }

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -87,7 +87,7 @@ public class MarkerTransformer implements IClassTransformer
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public byte[] transform(String name, byte[] bytes) public byte[] transform(String name, String transformedName, byte[] bytes)
{ {
if (bytes == null) { return null; } if (bytes == null) { return null; }
if (!markers.containsKey(name)) { return bytes; } if (!markers.containsKey(name)) { return bytes; }
@ -240,7 +240,7 @@ public class MarkerTransformer implements IClassTransformer
for (MarkerTransformer trans : transformers) for (MarkerTransformer trans : transformers)
{ {
entryData = trans.transform(name, entryData); entryData = trans.transform(name, name, entryData);
} }
} }

View file

@ -21,7 +21,7 @@ public class SideTransformer implements IClassTransformer
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public byte[] transform(String name, byte[] bytes) public byte[] transform(String name, String transformedName, byte[] bytes)
{ {
if (bytes == null) { return null; } if (bytes == null) { return null; }
@ -69,7 +69,7 @@ public class SideTransformer implements IClassTransformer
classNode.accept(writer); classNode.accept(writer);
return writer.toByteArray(); return writer.toByteArray();
} }
private boolean remove(List<AnnotationNode> anns, String side) private boolean remove(List<AnnotationNode> anns, String side)
{ {
if (anns == null) if (anns == null)

View file

@ -13,9 +13,11 @@ public class FMLCorePlugin implements IFMLLoadingPlugin
@Override @Override
public String[] getASMTransformerClass() 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.MarkerTransformer",
"cpw.mods.fml.common.asm.transformers.SideTransformer" "cpw.mods.fml.common.asm.transformers.SideTransformer",
"cpw.mods.fml.common.asm.transformers.DeobfuscationTransformer",
}; };
} }

View file

@ -0,0 +1,7 @@
package cpw.mods.fml.relauncher;
public interface IClassNameTransformer {
public String remapClassName(String name);
public String unmapClassName(String name);
}

View file

@ -2,5 +2,5 @@ package cpw.mods.fml.relauncher;
public interface IClassTransformer public interface IClassTransformer
{ {
public byte[] transform(String name, byte[] bytes); public byte[] transform(String name, String transformedName, byte[] bytes);
} }

View file

@ -39,6 +39,7 @@ public class RelaunchClassLoader extends URLClassLoader
private Set<String> classLoaderExceptions = new HashSet<String>(); private Set<String> classLoaderExceptions = new HashSet<String>();
private Set<String> transformerExceptions = new HashSet<String>(); private Set<String> transformerExceptions = new HashSet<String>();
private Map<Package,Manifest> packageManifests = new HashMap<Package,Manifest>(); private Map<Package,Manifest> packageManifests = new HashMap<Package,Manifest>();
private IClassNameTransformer renameTransformer;
private static Manifest EMPTY = new Manifest(); private static Manifest EMPTY = new Manifest();
@ -74,7 +75,12 @@ public class RelaunchClassLoader extends URLClassLoader
{ {
try 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) catch (Exception e)
{ {
@ -122,9 +128,11 @@ public class RelaunchClassLoader extends URLClassLoader
try try
{ {
CodeSigner[] signers = null; CodeSigner[] signers = null;
int lastDot = name.lastIndexOf('.'); String transformedName = transformName(name);
String pkgname = lastDot == -1 ? "" : name.substring(0, lastDot); String untransformedName = untransformName(name);
String fName = name.replace('.', '/').concat(".class"); int lastDot = untransformedName.lastIndexOf('.');
String pkgname = lastDot == -1 ? "" : untransformedName.substring(0, lastDot);
String fName = untransformedName.replace('.', '/').concat(".class");
String pkgPath = pkgname.replace('.', '/'); String pkgPath = pkgname.replace('.', '/');
URLConnection urlConnection = findCodeSourceConnectionFor(fName); URLConnection urlConnection = findCodeSourceConnectionFor(fName);
if (urlConnection instanceof JarURLConnection && lastDot > -1) if (urlConnection instanceof JarURLConnection && lastDot > -1)
@ -136,7 +144,7 @@ public class RelaunchClassLoader extends URLClassLoader
Manifest mf = jf.getManifest(); Manifest mf = jf.getManifest();
JarEntry ent = jf.getJarEntry(fName); JarEntry ent = jf.getJarEntry(fName);
Package pkg = getPackage(pkgname); Package pkg = getPackage(pkgname);
getClassBytes(name); getClassBytes(untransformedName);
signers = ent.getCodeSigners(); signers = ent.getCodeSigners();
if (pkg == null) 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); FMLLog.severe("The URL %s is defining elements for sealed path %s", urlConnection.getURL(), pkgname);
} }
} }
byte[] basicClass = getClassBytes(name); byte[] basicClass = getClassBytes(untransformedName);
byte[] transformedClass = runTransformers(name, basicClass); byte[] transformedClass = runTransformers(untransformedName, transformedName, basicClass);
Class<?> cl = defineClass(name, transformedClass, 0, transformedClass.length, new CodeSource(urlConnection.getURL(), signers)); Class<?> cl = defineClass(transformedName, transformedClass, 0, transformedClass.length, new CodeSource(urlConnection.getURL(), signers));
cachedClasses.put(name, cl); cachedClasses.put(transformedName, cl);
return cl; return cl;
} }
catch (Throwable e) 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) private boolean isSealed(String path, Manifest man)
{ {
Attributes attr = man.getAttributes(path); 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) for (IClassTransformer transformer : transformers)
{ {
basicClass = transformer.transform(name, basicClass); basicClass = transformer.transform(name, transformedName, basicClass);
} }
return basicClass; return basicClass;
} }