Search in sources :

Example 1 with SiPush

use of net.runelite.asm.attributes.code.instructions.SiPush in project runelite by runelite.

the class ExprArgOrderTest method test2.

@Test
public void test2() {
    ClassGroup group = ClassGroupFactory.generateGroup();
    Code code = group.findClass("test").findMethod("func").getCode();
    Instructions ins = code.getInstructions();
    code.setMaxStack(2);
    // vars[0] = 3
    Instruction[] prepareVariables = { new LDC(ins, 3), new IStore(ins, 0) };
    for (Instruction i : prepareVariables) {
        ins.addInstruction(i);
    }
    Instruction[] body = { // 2
    new ILoad(ins, 0), new LDC(ins, 3), new IAdd(ins), new Pop(ins), // 6
    new LDC(ins, 3), new ILoad(ins, 0), new IAdd(ins), new SiPush(ins, (short) 512), new IAdd(ins), new Pop(ins), new VReturn(ins) };
    for (Instruction i : body) {
        ins.addInstruction(i);
    }
    ExprArgOrder exprArgOrder = new ExprArgOrder();
    exprArgOrder.run(group);
    List<Instruction> instructions = ins.getInstructions();
    // ensure this stays the same
    assertEquals(ILOAD, instructions.get(2).getType());
    assertEquals(LDC, instructions.get(3).getType());
    assertEquals(IADD, instructions.get(4).getType());
    // 
    assertEquals(ILOAD, instructions.get(6).getType());
    assertEquals(SIPUSH, instructions.get(7).getType());
    assertEquals(IADD, instructions.get(8).getType());
    assertEquals(LDC, instructions.get(9).getType());
    assertEquals(IADD, instructions.get(10).getType());
}
Also used : SiPush(net.runelite.asm.attributes.code.instructions.SiPush) IStore(net.runelite.asm.attributes.code.instructions.IStore) ILoad(net.runelite.asm.attributes.code.instructions.ILoad) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.InstructionType.LDC) LDC(net.runelite.asm.attributes.code.instructions.LDC) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) VReturn(net.runelite.asm.attributes.code.instructions.VReturn) Pop(net.runelite.asm.attributes.code.instructions.Pop) ClassGroup(net.runelite.asm.ClassGroup) IAdd(net.runelite.asm.attributes.code.instructions.IAdd) Test(org.junit.Test)

Example 2 with SiPush

use of net.runelite.asm.attributes.code.instructions.SiPush in project runelite by runelite.

the class ExprArgOrderTest method test4.

@Test
public void test4() {
    ClassGroup group = ClassGroupFactory.generateGroup();
    Code code = group.findClass("test").findMethod("func").getCode();
    Instructions ins = code.getInstructions();
    code.setMaxStack(2);
    // vars[0] = 3
    Instruction[] prepareVariables = { new LDC(ins, 3), new IStore(ins, 0) };
    for (Instruction i : prepareVariables) {
        ins.addInstruction(i);
    }
    Instruction[] body = { new SiPush(ins, (short) 600), new ILoad(ins, 0), new LDC(ins, 3), new IMul(ins), new IAdd(ins), new Pop(ins), new ILoad(ins, 0), new LDC(ins, 3), new IMul(ins), new SiPush(ins, (short) 600), new IAdd(ins), new Pop(ins), new VReturn(ins) };
    for (Instruction i : body) {
        ins.addInstruction(i);
    }
    ExprArgOrder exprArgOrder = new ExprArgOrder();
    exprArgOrder.run(group);
    List<Instruction> instructions = ins.getInstructions();
    for (int i = 2; i <= 7; ++i) {
        assertEquals(instructions.get(i).getType(), instructions.get(i + 6).getType());
    }
}
Also used : SiPush(net.runelite.asm.attributes.code.instructions.SiPush) IStore(net.runelite.asm.attributes.code.instructions.IStore) ILoad(net.runelite.asm.attributes.code.instructions.ILoad) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.InstructionType.LDC) LDC(net.runelite.asm.attributes.code.instructions.LDC) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) VReturn(net.runelite.asm.attributes.code.instructions.VReturn) Pop(net.runelite.asm.attributes.code.instructions.Pop) ClassGroup(net.runelite.asm.ClassGroup) IMul(net.runelite.asm.attributes.code.instructions.IMul) IAdd(net.runelite.asm.attributes.code.instructions.IAdd) Test(org.junit.Test)

Example 3 with SiPush

use of net.runelite.asm.attributes.code.instructions.SiPush in project runelite by runelite.

the class MultiplicationDeobfuscatorTest method test13.

// sipush                512
// ldc                   -688421113
// imul
// ldc                   -585812297
// imul
// putstatic             class134/field2009 I
@Test
public void test13() {
    ClassGroup group = ClassGroupFactory.generateGroup();
    Code code = group.findClass("test").findMethod("func").getCode();
    Instructions ins = code.getInstructions();
    code.setMaxStack(2);
    LDC constant1 = new LDC(ins, -688421113);
    LDC constant2 = new LDC(ins, -585812297);
    Instruction[] body = { new SiPush(ins, (short) 512), constant1, new IMul(ins), constant2, new IMul(ins), new VReturn(ins) };
    for (Instruction i : body) {
        ins.addInstruction(i);
    }
    Execution e = new Execution(group);
    e.populateInitialMethods();
    e.run();
    assert constant1.getConstantAsInt() * constant2.getConstantAsInt() == 1;
    Deobfuscator d = new MultiplicationDeobfuscator();
    d.run(group);
    Assert.assertEquals(1, constant1.getConstantAsInt());
    Assert.assertEquals(1, constant2.getConstantAsInt());
}
Also used : SiPush(net.runelite.asm.attributes.code.instructions.SiPush) Execution(net.runelite.asm.execution.Execution) ClassGroup(net.runelite.asm.ClassGroup) IMul(net.runelite.asm.attributes.code.instructions.IMul) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.instructions.LDC) Instruction(net.runelite.asm.attributes.code.Instruction) Code(net.runelite.asm.attributes.Code) VReturn(net.runelite.asm.attributes.code.instructions.VReturn) Deobfuscator(net.runelite.deob.Deobfuscator) Test(org.junit.Test)

Example 4 with SiPush

use of net.runelite.asm.attributes.code.instructions.SiPush in project runelite by runelite.

the class MultiplicationDeobfuscator method parseExpression.

public static MultiplicationExpression parseExpression(InstructionContext ctx, Class want) {
    MultiplicationExpression me = new MultiplicationExpression();
    if (ctx.getInstruction() instanceof LVTInstruction) {
        LVTInstruction lvt = (LVTInstruction) ctx.getInstruction();
        // loading a variable
        if (!lvt.store()) {
            // var index
            int idx = lvt.getVariableIndex();
            // variables at time of execution
            Variables vars = ctx.getVariables();
            // get the variable
            VariableContext vctx = vars.get(idx);
            if (// ?
            vctx.getRead().size() == 1) {
                // this is an istore
                InstructionContext storeCtx = vctx.getInstructionWhichStored();
                if (storeCtx.getInstruction() instanceof LVTInstruction) {
                    // invoking funcs can put stuff in lvt
                    LVTInstruction storelvt = (LVTInstruction) storeCtx.getInstruction();
                    if (storelvt instanceof IInc)
                        throw new IllegalStateException();
                    assert storelvt.store();
                    InstructionContext pushed = storeCtx.getPops().get(0).getPushed();
                    return parseExpression(pushed, want);
                }
            }
        }
    }
    if (ctx.getInstruction() instanceof PushConstantInstruction) {
        if (ctx.getInstruction() instanceof BiPush || ctx.getInstruction() instanceof SiPush) {
            throw new IllegalStateException();
        }
        me.instructions.add(ctx);
        return me;
    }
    for (StackContext sctx : ctx.getPops()) {
        if (ctx.getInstruction().getClass() == want) {
            if (!isOnlyPath(ctx, sctx))
                continue;
        }
        InstructionContext i = sctx.getPushed();
        // if this instruction is imul, look at pops
        if (ctx.getInstruction().getClass() == want) {
            if (i.getInstruction() instanceof Swap) {
                logger.debug("Resolving swap");
                Swap swap = (Swap) i.getInstruction();
                sctx = swap.getOriginal(sctx);
                i = sctx.getPushed();
            }
            if (i.getInstruction() instanceof PushConstantInstruction) {
                // bipush/sipush are always not obfuscated
                if (i.getInstruction() instanceof BiPush || i.getInstruction() instanceof SiPush)
                    continue;
                // a constant of imul
                me.instructions.add(i);
            } else if (i.getInstruction().getClass() == want) {
                // chained imul, append to me
                try {
                    MultiplicationExpression other = parseExpression(i, want);
                    if (other.dupmagic != null) {
                        assert me.dupmagic == null;
                        me.dupmagic = other.dupmagic;
                    }
                    me.instructions.addAll(other.instructions);
                    me.dupedInstructions.addAll(other.dupedInstructions);
                    me.subexpressions.addAll(other.subexpressions);
                } catch (IllegalStateException ex) {
                // this is ok? just don't include it?
                }
            } else if (i.getInstruction() instanceof IAdd || i.getInstruction() instanceof ISub || i.getInstruction() instanceof LAdd || i.getInstruction() instanceof LSub) {
                // imul using result of iadd or isub. evaluate expression
                try {
                    MultiplicationExpression other = parseExpression(i, want);
                    assert other.dupmagic == null;
                    // subexpr
                    me.subexpressions.add(other);
                } catch (IllegalStateException ex) {
                    assert me.subexpressions.isEmpty();
                // subexpression is too complex. we can still simplify the top level though
                }
            } else if (i.getInstruction() instanceof DupInstruction) {
                DupInstruction dup = (DupInstruction) i.getInstruction();
                // find other branch of the dup instruction
                // sctx = what dup pushed, find other
                // other side of dup
                StackContext otherCtx = dup.getOtherBranch(sctx);
                // what popped other side of dup. is this right?
                InstructionContext otherCtxI = otherCtx.getPopped().get(0);
                if (otherCtxI.getInstruction().getClass() == want) {
                    // assert otherCtxI.getInstruction() instanceof IMul;
                    // other side of that imul
                    InstructionContext pushConstant = otherCtxI.getPops().get(0).getPushed();
                    assert pushConstant.getInstruction() instanceof LDC;
                    me.dupmagic = pushConstant;
                    // original
                    StackContext orig = dup.getOriginal(sctx);
                    try {
                        MultiplicationExpression other = parseExpression(orig.getPushed(), want);
                        // done to it affect that, too. so multiply it by existing values?
                        if (orig.getPushed().getInstruction() instanceof IAdd || orig.getPushed().getInstruction() instanceof ISub || orig.getPushed().getInstruction() instanceof LAdd || orig.getPushed().getInstruction() instanceof LSub) {
                            me.subexpressions.add(other);
                        } else {
                            assert other.dupmagic == null;
                            me.instructions.addAll(other.instructions);
                            me.dupedInstructions.addAll(other.instructions);
                            me.subexpressions.addAll(other.subexpressions);
                        }
                    } catch (IllegalStateException ex) {
                        assert me.subexpressions.isEmpty();
                    }
                }
            } else if (i.getInstruction() instanceof GetFieldInstruction) {
                me.fieldInstructions.add(i);
            // non constant, ignore
            } else {
            // System.out.println("imul pops something I don't know " + i.getInstruction());
            }
        } else // this is an iadd/sub
        if (ctx.getInstruction() instanceof IAdd || ctx.getInstruction() instanceof ISub || ctx.getInstruction() instanceof LAdd || ctx.getInstruction() instanceof LSub) {
            // parse this side of the add/sub
            MultiplicationExpression other = parseExpression(i, want);
            me.subexpressions.add(other);
        } else {
        // System.out.println(ctx.getInstruction() + " pops something I dont know " + i.getInstruction());
        }
    }
    if (me.instructions.isEmpty() && me.subexpressions.isEmpty())
        throw new IllegalStateException();
    return me;
}
Also used : SiPush(net.runelite.asm.attributes.code.instructions.SiPush) InstructionContext(net.runelite.asm.execution.InstructionContext) PushConstantInstruction(net.runelite.asm.attributes.code.instruction.types.PushConstantInstruction) DupInstruction(net.runelite.asm.attributes.code.instruction.types.DupInstruction) LDC(net.runelite.asm.attributes.code.instructions.LDC) LVTInstruction(net.runelite.asm.attributes.code.instruction.types.LVTInstruction) VariableContext(net.runelite.asm.execution.VariableContext) BiPush(net.runelite.asm.attributes.code.instructions.BiPush) Variables(net.runelite.asm.execution.Variables) Swap(net.runelite.asm.attributes.code.instructions.Swap) ISub(net.runelite.asm.attributes.code.instructions.ISub) StackContext(net.runelite.asm.execution.StackContext) LAdd(net.runelite.asm.attributes.code.instructions.LAdd) IInc(net.runelite.asm.attributes.code.instructions.IInc) LSub(net.runelite.asm.attributes.code.instructions.LSub) IAdd(net.runelite.asm.attributes.code.instructions.IAdd) GetFieldInstruction(net.runelite.asm.attributes.code.instruction.types.GetFieldInstruction)

Example 5 with SiPush

use of net.runelite.asm.attributes.code.instructions.SiPush in project runelite by runelite.

the class InjectInvoker method injectInvoker.

private void injectInvoker(ClassFile clazz, java.lang.reflect.Method method, Method deobfuscatedMethod, Method invokeMethod, String garbage) {
    if (clazz.findMethod(method.getName(), deobfuscatedMethod.getDescriptor()) != null) {
        logger.warn("Not injecting method {} because it already exists!", method);
        // this can happen from exporting a field and method with the same name
        return;
    }
    assert invokeMethod.isStatic() == deobfuscatedMethod.isStatic();
    assert invokeMethod.isStatic() || invokeMethod.getClassFile() == clazz;
    Type lastGarbageArgumentType = null;
    if (deobfuscatedMethod.getDescriptor().getArguments().size() != invokeMethod.getDescriptor().getArguments().size()) {
        // allow for obfuscated method to have a single bogus signature at the end
        assert deobfuscatedMethod.getDescriptor().size() + 1 == invokeMethod.getDescriptor().size();
        List<Type> arguments = invokeMethod.getDescriptor().getArguments();
        lastGarbageArgumentType = arguments.get(arguments.size() - 1);
    }
    // Injected method signature is always the same as the API
    Signature apiSignature = inject.javaMethodToSignature(method);
    Method invokerMethodSignature = new Method(clazz, method.getName(), apiSignature);
    invokerMethodSignature.setAccessFlags(ACC_PUBLIC);
    // create code attribute
    Code code = new Code(invokerMethodSignature);
    invokerMethodSignature.setCode(code);
    Instructions instructions = code.getInstructions();
    List<Instruction> ins = instructions.getInstructions();
    // this + arguments
    code.setMaxStack(1 + invokeMethod.getDescriptor().size());
    // load function arguments onto the stack.
    int index = 0;
    if (!invokeMethod.isStatic()) {
        // this
        ins.add(new ALoad(instructions, index++));
    } else {
        // this method is always non static
        ++index;
    }
    for (int i = 0; i < deobfuscatedMethod.getDescriptor().size(); ++i) {
        Type type = deobfuscatedMethod.getDescriptor().getTypeOfArg(i);
        Instruction loadInstruction = inject.createLoadForTypeIndex(instructions, type, index);
        ins.add(loadInstruction);
        Signature invokeDesc = invokeMethod.getDescriptor();
        Type obType = invokeDesc.getTypeOfArg(i);
        if (!type.equals(obType)) {
            CheckCast checkCast = new CheckCast(instructions);
            checkCast.setType(obType);
            ins.add(checkCast);
        }
        if (loadInstruction instanceof DLoad || loadInstruction instanceof LLoad) {
            index += 2;
        } else {
            index += 1;
        }
    }
    if (lastGarbageArgumentType != null) {
        // if garbage is null here it might just be an unused parameter, not part of the obfuscation
        if (garbage == null) {
            garbage = "0";
        }
        switch(lastGarbageArgumentType.toString()) {
            case "Z":
            case "B":
            case "C":
                ins.add(new BiPush(instructions, Byte.parseByte(garbage)));
                break;
            case "S":
                ins.add(new SiPush(instructions, Short.parseShort(garbage)));
                break;
            case "I":
                ins.add(new LDC(instructions, Integer.parseInt(garbage)));
                break;
            case "D":
                ins.add(new LDC(instructions, Double.parseDouble(garbage)));
                break;
            case "F":
                ins.add(new LDC(instructions, Float.parseFloat(garbage)));
                break;
            case "J":
                ins.add(new LDC(instructions, Long.parseLong(garbage)));
                break;
            default:
                throw new RuntimeException("Unknown type");
        }
    }
    if (invokeMethod.isStatic()) {
        ins.add(new InvokeStatic(instructions, invokeMethod.getPoolMethod()));
    } else {
        ins.add(new InvokeVirtual(instructions, invokeMethod.getPoolMethod()));
    }
    Type returnValue = invokeMethod.getDescriptor().getReturnValue();
    InstructionType returnType;
    if (returnValue.isPrimitive() && returnValue.getDimensions() == 0) {
        switch(returnValue.toString()) {
            case "Z":
            case "I":
                returnType = InstructionType.IRETURN;
                break;
            case "J":
                returnType = InstructionType.LRETURN;
                break;
            case "F":
                returnType = InstructionType.FRETURN;
                break;
            case "D":
                returnType = InstructionType.DRETURN;
                break;
            case "V":
                returnType = InstructionType.RETURN;
                break;
            default:
                assert false;
                return;
        }
    } else {
        returnType = InstructionType.ARETURN;
    }
    ins.add(new Return(instructions, returnType));
    clazz.addMethod(invokerMethodSignature);
}
Also used : SiPush(net.runelite.asm.attributes.code.instructions.SiPush) LLoad(net.runelite.asm.attributes.code.instructions.LLoad) Return(net.runelite.asm.attributes.code.instructions.Return) InstructionType(net.runelite.asm.attributes.code.InstructionType) DLoad(net.runelite.asm.attributes.code.instructions.DLoad) Instructions(net.runelite.asm.attributes.code.Instructions) LDC(net.runelite.asm.attributes.code.instructions.LDC) Method(net.runelite.asm.Method) CheckCast(net.runelite.asm.attributes.code.instructions.CheckCast) Instruction(net.runelite.asm.attributes.code.Instruction) BiPush(net.runelite.asm.attributes.code.instructions.BiPush) Code(net.runelite.asm.attributes.Code) InstructionType(net.runelite.asm.attributes.code.InstructionType) Type(net.runelite.asm.Type) InvokeVirtual(net.runelite.asm.attributes.code.instructions.InvokeVirtual) Signature(net.runelite.asm.signature.Signature) ALoad(net.runelite.asm.attributes.code.instructions.ALoad) InvokeStatic(net.runelite.asm.attributes.code.instructions.InvokeStatic)

Aggregations

LDC (net.runelite.asm.attributes.code.instructions.LDC)7 SiPush (net.runelite.asm.attributes.code.instructions.SiPush)7 Code (net.runelite.asm.attributes.Code)6 Instruction (net.runelite.asm.attributes.code.Instruction)6 Instructions (net.runelite.asm.attributes.code.Instructions)6 ClassGroup (net.runelite.asm.ClassGroup)5 VReturn (net.runelite.asm.attributes.code.instructions.VReturn)5 Test (org.junit.Test)5 ILoad (net.runelite.asm.attributes.code.instructions.ILoad)4 IMul (net.runelite.asm.attributes.code.instructions.IMul)4 IStore (net.runelite.asm.attributes.code.instructions.IStore)4 IAdd (net.runelite.asm.attributes.code.instructions.IAdd)3 Execution (net.runelite.asm.execution.Execution)3 LDC (net.runelite.asm.attributes.code.InstructionType.LDC)2 Label (net.runelite.asm.attributes.code.Label)2 BiPush (net.runelite.asm.attributes.code.instructions.BiPush)2 IfEq (net.runelite.asm.attributes.code.instructions.IfEq)2 Pop (net.runelite.asm.attributes.code.instructions.Pop)2 Deobfuscator (net.runelite.deob.Deobfuscator)2 Method (net.runelite.asm.Method)1