Пример #1
0
        protected bool checkSameMethods(MethodReference method, MethodDefinition methodToInline, int ignoreLastMethodToInlineArgs)
        {
            var methodToInlineArgs = DotNetUtils.getArgs(methodToInline);
            var methodArgs         = DotNetUtils.getArgs(method);

            if (methodToInlineArgs.Count - ignoreLastMethodToInlineArgs != methodArgs.Count)
            {
                return(false);
            }
            for (int i = 0; i < methodArgs.Count; i++)
            {
                var methodArg         = methodArgs[i];
                var methodToInlineArg = methodToInlineArgs[i];
                if (!isCompatibleType(i, methodArg, methodToInlineArg))
                {
                    if (i != 0 || !method.HasImplicitThis)
                    {
                        return(false);
                    }
                    if (!isCompatibleValueThisPtr(methodArg, methodToInlineArg))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        protected bool checkSameMethods(IMethod method, MethodDef methodToInline, int ignoreLastMethodToInlineArgs)
        {
            var  methodToInlineArgs = methodToInline.Parameters;
            var  methodArgs         = DotNetUtils.getArgs(method);
            bool hasImplicitThis    = method.MethodSig.ImplicitThis;

            if (methodToInlineArgs.Count - ignoreLastMethodToInlineArgs != methodArgs.Count)
            {
                return(false);
            }
            for (int i = 0; i < methodArgs.Count; i++)
            {
                var methodArg         = methodArgs[i];
                var methodToInlineArg = getArgType(methodToInline, methodToInlineArgs[i].Type);
                if (!isCompatibleType(i, methodArg, methodToInlineArg))
                {
                    if (i != 0 || !hasImplicitThis)
                    {
                        return(false);
                    }
                    if (!isCompatibleValueThisPtr(methodArg, methodToInlineArg))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Пример #3
0
        bool findArgs(CallResult callResult)
        {
            var block      = callResult.block;
            var method     = callResult.getMethodRef();
            var methodArgs = DotNetUtils.getArgs(method);
            int numArgs    = methodArgs.Count;
            var args       = new object[numArgs];

            int instrIndex = callResult.callEndIndex - 1;

            for (int i = numArgs - 1; i >= 0; i--)
            {
                object arg = null;
                if (!getArg(method, block, ref arg, ref instrIndex))
                {
                    return(false);
                }
                if (arg is int)
                {
                    arg = fixIntArg(methodArgs[i], (int)arg);
                }
                else if (arg is long)
                {
                    arg = fixIntArg(methodArgs[i], (long)arg);
                }
                args[i] = arg;
            }

            callResult.args           = args;
            callResult.callStartIndex = instrIndex + 1;
            return(true);
        }
Пример #4
0
        bool deobfuscateFields()
        {
            foreach (var info in fieldWrites.Values)
            {
                info.clear();
            }

            foreach (var method in allMethods)
            {
                if (method.Body == null)
                {
                    continue;
                }
                var instructions = method.Body.Instructions;
                for (int i = 0; i < instructions.Count; i++)
                {
                    var           instr             = instructions[i];
                    TypeReference fieldType         = null;
                    TypeInfo <FieldDefinition> info = null;
                    FieldReference             field;
                    switch (instr.OpCode.Code)
                    {
                    case Code.Stfld:
                    case Code.Stsfld:
                        field = instr.Operand as FieldReference;
                        if (field == null)
                        {
                            continue;
                        }
                        if (!fieldWrites.TryGetValue(new FieldReferenceAndDeclaringTypeKey(field), out info))
                        {
                            continue;
                        }
                        bool wasNewobj;
                        fieldType = getLoadedType(info.arg.DeclaringType, method, instructions, i, out wasNewobj);
                        if (fieldType == null)
                        {
                            continue;
                        }
                        info.add(fieldType, wasNewobj);
                        break;

                    case Code.Call:
                    case Code.Calli:
                    case Code.Callvirt:
                    case Code.Newobj:
                        var pushedArgs   = MethodStack.getPushedArgInstructions(instructions, i);
                        var calledMethod = instr.Operand as MethodReference;
                        if (calledMethod == null)
                        {
                            continue;
                        }
                        IList <TypeReference> calledMethodArgs = DotNetUtils.getArgs(calledMethod);
                        calledMethodArgs = DotNetUtils.replaceGenericParameters(calledMethod.DeclaringType as GenericInstanceType, calledMethod as GenericInstanceMethod, calledMethodArgs);
                        for (int j = 0; j < pushedArgs.NumValidArgs; j++)
                        {
                            var pushInstr = pushedArgs.getEnd(j);
                            if (pushInstr.OpCode.Code != Code.Ldfld && pushInstr.OpCode.Code != Code.Ldsfld)
                            {
                                continue;
                            }

                            field = pushInstr.Operand as FieldReference;
                            if (field == null)
                            {
                                continue;
                            }
                            if (!fieldWrites.TryGetValue(new FieldReferenceAndDeclaringTypeKey(field), out info))
                            {
                                continue;
                            }
                            fieldType = calledMethodArgs[calledMethodArgs.Count - 1 - j];
                            if (!isValidType(info.arg.DeclaringType, fieldType))
                            {
                                continue;
                            }
                            info.add(fieldType);
                        }
                        break;

                    default:
                        continue;
                    }
                }
            }

            bool changed     = false;
            var  removeThese = new List <FieldDefinition>();

            foreach (var info in fieldWrites.Values)
            {
                if (info.updateNewType(module))
                {
                    removeThese.Add(info.arg);
                    getUpdatedField(info.arg).newFieldType = info.newType;
                    info.arg.FieldType = info.newType;
                    changed            = true;
                }
            }
            foreach (var field in removeThese)
            {
                fieldWrites.Remove(new FieldReferenceAndDeclaringTypeKey(field));
            }
            return(changed);
        }
Пример #5
0
        protected InstructionPatcher tryInlineOtherMethod(int patchIndex, MethodDefinition methodToInline, Instruction instr, int instrIndex, int popLastArgs)
        {
            int  loadIndex       = 0;
            int  methodArgsCount = DotNetUtils.getArgsCount(methodToInline);
            bool foundLdarga     = false;

            while (instr != null && loadIndex < methodArgsCount)
            {
                bool isLdarg = true;
                switch (instr.OpCode.Code)
                {
                case Code.Ldarg:
                case Code.Ldarg_S:
                case Code.Ldarg_0:
                case Code.Ldarg_1:
                case Code.Ldarg_2:
                case Code.Ldarg_3:
                    break;

                case Code.Ldarga:
                case Code.Ldarga_S:
                    foundLdarga = true;
                    break;

                default:
                    isLdarg = false;
                    break;
                }
                if (!isLdarg)
                {
                    break;
                }

                if (DotNetUtils.getArgIndex(instr) != loadIndex)
                {
                    return(null);
                }
                loadIndex++;
                instr = DotNetUtils.getInstruction(methodToInline.Body.Instructions, ref instrIndex);
            }
            if (instr == null || loadIndex != methodArgsCount - popLastArgs)
            {
                return(null);
            }

            if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt)
            {
                if (foundLdarga)
                {
                    return(null);
                }
                var callInstr    = instr;
                var calledMethod = callInstr.Operand as MethodReference;
                if (calledMethod == null)
                {
                    return(null);
                }

                if (!isCompatibleType(-1, calledMethod.MethodReturnType.ReturnType, methodToInline.MethodReturnType.ReturnType))
                {
                    return(null);
                }

                if (!checkSameMethods(calledMethod, methodToInline, popLastArgs))
                {
                    return(null);
                }

                return(new InstructionPatcher(patchIndex, instrIndex, callInstr));
            }
            else if (instr.OpCode.Code == Code.Newobj)
            {
                if (foundLdarga)
                {
                    return(null);
                }
                var newobjInstr = instr;
                var ctor        = newobjInstr.Operand as MethodReference;
                if (ctor == null)
                {
                    return(null);
                }

                if (!isCompatibleType(-1, ctor.DeclaringType, methodToInline.MethodReturnType.ReturnType))
                {
                    return(null);
                }

                var methodArgs       = DotNetUtils.getArgs(methodToInline);
                var calledMethodArgs = DotNetUtils.getArgs(ctor);
                if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count)
                {
                    return(null);
                }
                for (int i = 1; i < calledMethodArgs.Count; i++)
                {
                    if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1]))
                    {
                        return(null);
                    }
                }

                return(new InstructionPatcher(patchIndex, instrIndex, newobjInstr));
            }
            else if (instr.OpCode.Code == Code.Ldfld || instr.OpCode.Code == Code.Ldflda ||
                     instr.OpCode.Code == Code.Ldftn || instr.OpCode.Code == Code.Ldvirtftn)
            {
                var ldInstr = instr;
                if (methodArgsCount != 1)
                {
                    return(null);
                }

                return(new InstructionPatcher(patchIndex, instrIndex, ldInstr));
            }

            return(null);
        }
Пример #6
0
        void deobfuscateMethod(MethodDef method)
        {
            if (!method.IsStatic || method.Body == null)
            {
                return;
            }

            bool fixReturnType = isUnknownType(method.MethodSig.GetRetType());

            argInfos.Clear();
            foreach (var arg in method.Parameters)
            {
                if (arg.IsHiddenThisParameter)
                {
                    continue;
                }
                if (!isUnknownType(arg))
                {
                    continue;
                }
                argInfos[arg] = new TypeInfo <Parameter>(arg);
            }
            if (argInfos.Count == 0 && !fixReturnType)
            {
                return;
            }

            var        methodParams = method.Parameters;
            PushedArgs pushedArgs;
            var        instructions = method.Body.Instructions;

            for (int i = 0; i < instructions.Count; i++)
            {
                var instr = instructions[i];
                switch (instr.OpCode.Code)
                {
                case Code.Ret:
                    if (!fixReturnType)
                    {
                        break;
                    }
                    bool wasNewobj;
                    var  type = getLoadedType(method, method, instructions, i, out wasNewobj);
                    if (type == null)
                    {
                        break;
                    }
                    methodReturnInfo.add(type);
                    break;

                case Code.Call:
                case Code.Calli:
                case Code.Callvirt:
                case Code.Newobj:
                    pushedArgs = MethodStack.getPushedArgInstructions(instructions, i);
                    var calledMethod = instr.Operand as IMethod;
                    if (calledMethod == null)
                    {
                        break;
                    }
                    var calledMethodParams = DotNetUtils.getArgs(calledMethod);
                    for (int j = 0; j < pushedArgs.NumValidArgs; j++)
                    {
                        int calledMethodParamIndex = calledMethodParams.Count - j - 1;
                        var ldInstr = pushedArgs.getEnd(j);
                        switch (ldInstr.OpCode.Code)
                        {
                        case Code.Ldarg:
                        case Code.Ldarg_S:
                        case Code.Ldarg_0:
                        case Code.Ldarg_1:
                        case Code.Ldarg_2:
                        case Code.Ldarg_3:
                            addMethodArgType(method, getParameter(methodParams, ldInstr), DotNetUtils.getArg(calledMethodParams, calledMethodParamIndex));
                            break;

                        default:
                            break;
                        }
                    }
                    break;

                case Code.Castclass:
                    pushedArgs = MethodStack.getPushedArgInstructions(instructions, i);
                    if (pushedArgs.NumValidArgs < 1)
                    {
                        break;
                    }
                    addMethodArgType(method, getParameter(methodParams, pushedArgs.getEnd(0)), instr.Operand as ITypeDefOrRef);
                    break;

                case Code.Stloc:
                case Code.Stloc_S:
                case Code.Stloc_0:
                case Code.Stloc_1:
                case Code.Stloc_2:
                case Code.Stloc_3:
                    pushedArgs = MethodStack.getPushedArgInstructions(instructions, i);
                    if (pushedArgs.NumValidArgs < 1)
                    {
                        break;
                    }
                    addMethodArgType(method, getParameter(methodParams, pushedArgs.getEnd(0)), instr.GetLocal(method.Body.Variables));
                    break;

                case Code.Stsfld:
                    pushedArgs = MethodStack.getPushedArgInstructions(instructions, i);
                    if (pushedArgs.NumValidArgs < 1)
                    {
                        break;
                    }
                    addMethodArgType(method, getParameter(methodParams, pushedArgs.getEnd(0)), instr.Operand as IField);
                    break;

                case Code.Stfld:
                    pushedArgs = MethodStack.getPushedArgInstructions(instructions, i);
                    if (pushedArgs.NumValidArgs >= 1)
                    {
                        var field = instr.Operand as IField;
                        addMethodArgType(method, getParameter(methodParams, pushedArgs.getEnd(0)), field);
                        if (pushedArgs.NumValidArgs >= 2 && field != null)
                        {
                            addMethodArgType(method, getParameter(methodParams, pushedArgs.getEnd(1)), field.DeclaringType);
                        }
                    }
                    break;

                case Code.Ldfld:
                case Code.Ldflda:
                    pushedArgs = MethodStack.getPushedArgInstructions(instructions, i);
                    if (pushedArgs.NumValidArgs < 1)
                    {
                        break;
                    }
                    addMethodArgType(method, getParameter(methodParams, pushedArgs.getEnd(0)), instr.Operand as IField);
                    break;

                //TODO: For better results, these should be checked:
                case Code.Starg:
                case Code.Starg_S:

                case Code.Ldelema:
                case Code.Ldelem:
                case Code.Ldelem_I:
                case Code.Ldelem_I1:
                case Code.Ldelem_I2:
                case Code.Ldelem_I4:
                case Code.Ldelem_I8:
                case Code.Ldelem_R4:
                case Code.Ldelem_R8:
                case Code.Ldelem_Ref:
                case Code.Ldelem_U1:
                case Code.Ldelem_U2:
                case Code.Ldelem_U4:

                case Code.Ldind_I:
                case Code.Ldind_I1:
                case Code.Ldind_I2:
                case Code.Ldind_I4:
                case Code.Ldind_I8:
                case Code.Ldind_R4:
                case Code.Ldind_R8:
                case Code.Ldind_Ref:
                case Code.Ldind_U1:
                case Code.Ldind_U2:
                case Code.Ldind_U4:

                case Code.Ldobj:

                case Code.Stelem:
                case Code.Stelem_I:
                case Code.Stelem_I1:
                case Code.Stelem_I2:
                case Code.Stelem_I4:
                case Code.Stelem_I8:
                case Code.Stelem_R4:
                case Code.Stelem_R8:
                case Code.Stelem_Ref:

                case Code.Stind_I:
                case Code.Stind_I1:
                case Code.Stind_I2:
                case Code.Stind_I4:
                case Code.Stind_I8:
                case Code.Stind_R4:
                case Code.Stind_R8:
                case Code.Stind_Ref:

                case Code.Stobj:
                default:
                    break;
                }
            }
        }