Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package pickandcraftSkin;
- import static org.objectweb.asm.Opcodes.ALOAD;
- import static org.objectweb.asm.Opcodes.ARETURN;
- import static org.objectweb.asm.Opcodes.INVOKESTATIC;
- import java.io.File;
- import java.io.InputStream;
- import java.util.Iterator;
- import java.util.zip.ZipEntry;
- import java.util.zip.ZipFile;
- import org.objectweb.asm.ClassReader;
- import org.objectweb.asm.ClassWriter;
- import org.objectweb.asm.tree.ClassNode;
- import org.objectweb.asm.tree.InsnList;
- import org.objectweb.asm.tree.InsnNode;
- import org.objectweb.asm.tree.MethodInsnNode;
- import org.objectweb.asm.tree.MethodNode;
- import org.objectweb.asm.tree.VarInsnNode;
- public class SkinClassTransformer implements net.minecraft.launchwrapper.IClassTransformer {
- @Override
- public byte[] transform(String arg0, String arg1, byte[] arg2) {
- //on cherche la classe qui nous interressent. On gere les deux cas: si elle est "obscurcie" ou pas
- if (arg0.equals("beu")) {
- System.out.println("********* INSIDE OBFUSCATED AbstractClientPlayer TRANSFORMER ABOUT TO PATCH: " + arg0);
- return patchClassASM(arg0, arg2, true);
- }
- if (arg0.equals("net.minecraft.client.entity.AbstractClientPlayer")) {
- System.out.println("********* INSIDE AbstractClientPlayer TRANSFORMER ABOUT TO PATCH: " + arg0);
- return patchClassASM(arg0, arg2, false);
- }
- //Check if the JVM is about to process the te.class or the EntityCreeper.class
- if (arg0.equals("bfn")
- || arg0.equals("net.minecraft.client.renderer.ImageBufferDownload")) {
- System.out
- .println("********* INSIDE ImageBufferDownload TRANSFORMER ABOUT TO PATCH: "
- + arg0);
- arg2 = patchClassInJar(arg0, arg2, arg0,
- SkinFMLLoadingPlugin.location);
- }
- return arg2;
- }
- //a small helper method that takes the class name we want to replace and our jar file.
- //It then uses the java zip library to open up the jar file and extract the classes.
- //Afterwards it serializes the class in bytes and pushes it on to the JVM.
- //with the original bytes that JVM was about to process ignored completly
- public byte[] patchClassInJar(String name, byte[] bytes, String ObfName,
- File location) {
- try {
- // open the jar as zip
- ZipFile zip = new ZipFile(location);
- // find the file inside the zip that is called te.class or
- // net.minecraft.entity.monster.EntityCreeper.class
- // replacing the . to / so it would look for
- // net/minecraft/entity/monster/EntityCreeper.class
- ZipEntry entry = zip.getEntry(name.replace('.', '/') + ".class");
- if (entry == null) {
- System.out
- .println(name + " not found in " + location.getName());
- } else {
- // serialize the class file into the bytes array
- InputStream zin = zip.getInputStream(entry);
- bytes = new byte[(int) entry.getSize()];
- zin.read(bytes);
- zin.close();
- System.out.println("[" + "SkinCustomHD" + "]: " + "Class "
- + name + " patched!");
- }
- zip.close();
- } catch (Exception e) {
- throw new RuntimeException("Error overriding " + name + " from "
- + location.getName(), e);
- }
- // return the new bytes
- return bytes;
- }
- public byte[] patchClassASM(String name, byte[] bytes, boolean obfuscated) {
- String targetMethod1Name = "", targetMethod2Name = "";
- boolean ok1 = false, ok2 = false;
- if(obfuscated == true) {
- targetMethod1Name ="d";
- targetMethod2Name = "e";
- }
- else {
- targetMethod1Name ="getSkinUrl";
- targetMethod2Name = "getCapeUrl";
- }
- //on prepare la manipulation
- ClassNode classNode = new ClassNode();
- ClassReader classReader = new ClassReader(bytes);
- classReader.accept(classNode, 0);
- //Maintenant, on boucle sur toutes les methodes declarees dans la classe jusqu'a trouver la/les methode(s) cible(s)
- Iterator<MethodNode> methods = classNode.methods.iterator();
- while(methods.hasNext())
- {
- MethodNode m = methods.next();
- System.out.println("********* Method Name: "+m.name + " Desc:" + m.desc);
- //On verifie si il s'agit de la methode cible et si elle a la meme signature (plus de detail ici: http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html)
- if ((m.name.equals(targetMethod1Name) && m.desc.equals("(Ljava/lang/String;)Ljava/lang/String;")))
- {
- System.out.println("********* Inside target method1!");
- //on creer une liste d'instruction pour invoquer une methode statique
- InsnList toInject = new InsnList();
- toInject.add(new VarInsnNode(ALOAD, 0));
- //new MethodInsnNode(on declare le type de la methode, "le chemin de la classe", "le nom de la methode", "sa signature")
- toInject.add(new MethodInsnNode(INVOKESTATIC, "pickandcraftSkin/PlayerCustom", "getURLSkinCustom", "(Ljava/lang/String;)Ljava/lang/String;"));
- toInject.add(new InsnNode(ARETURN));
- // on remplace les instructions deja presente dans la methode par notre liste d'instruction
- m.instructions = toInject;
- ok1 = true;
- System.out.println("Patching Method1 Complete!");
- }
- else if ((m.name.equals(targetMethod2Name) && m.desc.equals("(Ljava/lang/String;)Ljava/lang/String;")))
- {
- System.out.println("********* Inside target2 method!");
- InsnList toInject = new InsnList();
- toInject.add(new VarInsnNode(ALOAD, 0));
- toInject.add(new MethodInsnNode(INVOKESTATIC, "pickandcraftSkin/PlayerCustom", "getURLCapeCustom", "(Ljava/lang/String;)Ljava/lang/String;"));
- toInject.add(new InsnNode(ARETURN));
- // on remplace les instructions deja presente dans la methode par notre liste d'instruction
- m.instructions = toInject;
- ok2 = true;
- System.out.println("Patching Method2 Complete!");
- }
- if(ok1 && ok2)
- break;
- }
- //on finit la manipulation
- ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
- classNode.accept(writer);
- return writer.toByteArray();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement