First draft runtime deobf
This commit is contained in:
parent
5c99e3488a
commit
b4c7fe1d0e
10 changed files with 141 additions and 22 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package cpw.mods.fml.relauncher;
|
||||||
|
|
||||||
|
public interface IClassNameTransformer {
|
||||||
|
public String remapClassName(String name);
|
||||||
|
|
||||||
|
public String unmapClassName(String name);
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue