Question

Background: I'm injecting the Minecraft Launcher to obtain the applet (which I've done), but now I wish to load minecraft's file through my class loader. I found the method which GameUpdater.java (Minecraft's gameupdater, also dispatcher for the client's applet), and under which has a method called "createApplet".

GameUpdater.java:

public Applet createApplet() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class localClass = classLoader.loadClass("net.minecraft.client.MinecraftApplet");
return (Applet)localClass.newInstance();
}   

Okay, well simple enough, replace classLoader.loadClass with your own static load method. So, I tried, in my classloader, here is my transformation code:

for(Method method : generator.getMethods()) {
                    if(method.getName().equals("createApplet")) {
                        ConstantPoolGen cpg = generator.getConstantPool();
                        MethodGen methodGen = new MethodGen(method, generator.getClassName(), cpg);
                        Instruction instruction = null;
                        InstructionList instructionList = methodGen.getInstructionList();
                        InstructionHandle[] instructionHandles = instructionList.getInstructionHandles();
                        for(int i = 0; i < instructionHandles.length; i++) {
                            //System.out.println(instructionHandles[i].getInstruction());  //debug
                            if(instructionHandles[i].getInstruction() instanceof LDC) {
                                instruction = instructionHandles[i].getInstruction();
                                InstructionFactory instructionFactory = new InstructionFactory(generator, cpg);
                                InvokeInstruction classLoaderCall =
                                        instructionFactory.createInvoke(
                                        "MinecraftLauncher", "loadClass", Type.CLASS, new Type[]{Type.STRING},Constants.INVOKESTATIC);
                                instructionList.insert(instruction, classLoaderCall);
                                methodGen.setInstructionList(instructionList);
                                instructionList.setPositions();
                                methodGen.setMaxStack();
                                methodGen.setMaxLocals();
                                methodGen.removeLineNumbers();
                                generator.replaceMethod(method, methodGen.getMethod());
                                generator.getJavaClass().dump("gameupdater.class");
                            }
                        }
                    }

Yet, I fell on my face. Here is the updated gameupdater.class (as you see above, I dump it)

public Applet createApplet() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class localClass = MinecraftLauncher.loadClass(classLoader).loadClass("net.minecraft.client.MinecraftApplet");
return (Applet)localClass.newInstance();
}

Here is a picture of the bytecode for the method createApplet in GameUpdater bytecode info

Now, I have no other idea how else to do this. If someone could point me into the right direction, that would be awesome! In the mean time, I'm going to keep trying, and reading the bcel doc.

If you have any questions regarding more code, etc, please tell me.

Was it helpful?

Solution

Solved. The trick is to delete the InvokerVirtual (delete the OPCODE from the instruction list) after adding your new one(your static method replacing the load function).

Example

instructionList.insert(instruction, classLoaderCall);
instructionList.delete(instruction);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top