1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
package gtPlusPlus.preloader.asm;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import java.util.Iterator;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;
import gtPlusPlus.core.util.Utils;
import net.minecraft.launchwrapper.IClassTransformer;
public class Preloader_ClassTransformer implements IClassTransformer {
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
/*if (name.equals("abq")) {
Utils.LOG_ASM("[ASM] INSIDE OBFUSCATED EXPLOSION TRANSFORMER ABOUT TO PATCH: " + name);
return patchClassASM(name, basicClass, true);
}
else if (name.equals("net.minecraftforge.oredict.OreDictionary")) {
Utils.LOG_ASM("[ASM] INSIDE OREDICT TRANSFORMER ABOUT TO PATCH: " + name);
return patchClassASM(name, basicClass, false);
}*/
return basicClass;
}
public byte[] patchClassASM(String name, byte[] bytes, boolean obfuscated) {
String targetMethodName = "";
if(obfuscated == true)
targetMethodName ="a";
else
targetMethodName ="registerOreImpl";
//set up ASM class manipulation stuff. Consult the ASM docs for details
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
//Now we loop over all of the methods declared inside the Explosion class until we get to the targetMethodName "doExplosionB"
// find method to inject into
Iterator<MethodNode> methods = classNode.methods.iterator();
while(methods.hasNext())
{
MethodNode m = methods.next();
Utils.LOG_ASM("[ASM] Method Name: "+m.name + " Desc:" + m.desc);
//Check if this is doExplosionB and it's method signature is (Z)V which means that it accepts a boolean (Z) and returns a void (V)
if ((m.name.equals(targetMethodName) && m.desc.equals("(Ljava/lang/String;Lnet/minecraft/item/ItemStack;)V")))
{
Utils.LOG_ASM("[ASM] Inside target method!");
// find interesting instructions in method, there is a single FDIV instruction we use as target
// make new instruction list
InsnList toInject = new InsnList();
//toInject.add(new VarInsnNode(ALOAD, 0));
toInject.add(new VarInsnNode(ALOAD, 1));
toInject.add(new MethodInsnNode(INVOKESTATIC, "gtPlusPlus/preloader/Preloader_GT_OreDict", "removeCircuit", "(Lnet/minecraft/item/ItemStack;)Z, false"));
toInject.add(new VarInsnNode(Opcodes.IFEQ, 1));
toInject.add(new VarInsnNode(Opcodes.RETURN, 0));
//toInject.add(new VarInsnNode(org.objectweb.asm.Opcodes.LABEL END, 0));
// inject new instruction list into method instruction list
m.instructions.insert(toInject);
Utils.LOG_ASM("Patching Complete!");
break;
}
}
//ASM specific for cleaning up and returning the final bytes for JVM processing.
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
classNode.accept(writer);
return writer.toByteArray();
}
}
|