Пример #1
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];
                    TypeSig             fieldType = null;
                    TypeInfo <FieldDef> info      = null;
                    IField              field;
                    switch (instr.OpCode.Code)
                    {
                    case Code.Stfld:
                    case Code.Stsfld:
                        field = instr.Operand as IField;
                        if (field == null)
                        {
                            continue;
                        }
                        if (!fieldWrites.TryGetValue(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 IMethod;
                        if (calledMethod == null)
                        {
                            continue;
                        }
                        var calledMethodDefOrRef = calledMethod as IMethodDefOrRef;
                        var calledMethodSpec     = calledMethod as MethodSpec;
                        if (calledMethodSpec != null)
                        {
                            calledMethodDefOrRef = calledMethodSpec.Method;
                        }
                        if (calledMethodDefOrRef == null)
                        {
                            continue;
                        }

                        IList <TypeSig> calledMethodArgs = DotNetUtils.GetArgs(calledMethodDefOrRef);
                        calledMethodArgs = DotNetUtils.ReplaceGenericParameters(calledMethodDefOrRef.DeclaringType.TryGetGenericInstSig(), calledMethodSpec, 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 IField;
                            if (field == null)
                            {
                                continue;
                            }
                            if (!fieldWrites.TryGetValue(field, out info))
                            {
                                continue;
                            }
                            fieldType = calledMethodArgs[calledMethodArgs.Count - 1 - j];
                            if (!IsValidType(info.arg.DeclaringType, fieldType))
                            {
                                continue;
                            }
                            info.Add(fieldType);
                        }
                        break;

                    default:
                        continue;
                    }
                }
            }

            bool modified    = false;
            var  removeThese = new List <FieldDef>();

            foreach (var info in fieldWrites.Values)
            {
                if (info.UpdateNewType(module))
                {
                    removeThese.Add(info.arg);
                    GetUpdatedField(info.arg).newFieldType = info.newType;
                    info.arg.FieldSig.Type = info.newType;
                    modified = true;
                }
            }
            foreach (var field in removeThese)
            {
                fieldWrites.Remove(field);
            }
            return(modified);
        }
Пример #2
0
        public static TypeSig GetLoadedType(MethodDef method, IList <Instruction> instructions, int instrIndex, int argIndexFromEnd, out bool wasNewobj)
        {
            wasNewobj = false;
            var pushedArgs = MethodStack.GetPushedArgInstructions(instructions, instrIndex);
            var pushInstr  = pushedArgs.GetEnd(argIndexFromEnd);

            if (pushInstr == null)
            {
                return(null);
            }

            TypeSig type;
            Local   local;
            var     corLibTypes = method.DeclaringType.Module.CorLibTypes;

            switch (pushInstr.OpCode.Code)
            {
            case Code.Ldstr:
                type = corLibTypes.String;
                break;

            case Code.Conv_I:
            case Code.Conv_Ovf_I:
            case Code.Conv_Ovf_I_Un:
                type = corLibTypes.IntPtr;
                break;

            case Code.Conv_U:
            case Code.Conv_Ovf_U:
            case Code.Conv_Ovf_U_Un:
                type = corLibTypes.UIntPtr;
                break;

            case Code.Conv_I8:
            case Code.Conv_Ovf_I8:
            case Code.Conv_Ovf_I8_Un:
                type = corLibTypes.Int64;
                break;

            case Code.Conv_U8:
            case Code.Conv_Ovf_U8:
            case Code.Conv_Ovf_U8_Un:
                type = corLibTypes.UInt64;
                break;

            case Code.Conv_R8:
            case Code.Ldc_R8:
            case Code.Ldelem_R8:
            case Code.Ldind_R8:
                type = corLibTypes.Double;
                break;

            case Code.Call:
            case Code.Calli:
            case Code.Callvirt:
                var calledMethod = pushInstr.Operand as IMethod;
                if (calledMethod == null)
                {
                    return(null);
                }
                type = calledMethod.MethodSig.GetRetType();
                break;

            case Code.Newarr:
                var type2 = pushInstr.Operand as ITypeDefOrRef;
                if (type2 == null)
                {
                    return(null);
                }
                type      = new SZArraySig(type2.ToTypeSig());
                wasNewobj = true;
                break;

            case Code.Newobj:
                var ctor = pushInstr.Operand as IMethod;
                if (ctor == null)
                {
                    return(null);
                }
                type      = ctor.DeclaringType.ToTypeSig();
                wasNewobj = true;
                break;

            case Code.Castclass:
            case Code.Isinst:
            case Code.Unbox_Any:
            case Code.Ldelem:
            case Code.Ldobj:
                type = (pushInstr.Operand as ITypeDefOrRef).ToTypeSig();
                break;

            case Code.Ldarg:
            case Code.Ldarg_S:
            case Code.Ldarg_0:
            case Code.Ldarg_1:
            case Code.Ldarg_2:
            case Code.Ldarg_3:
                type = pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType);
                break;

            case Code.Ldloc:
            case Code.Ldloc_S:
            case Code.Ldloc_0:
            case Code.Ldloc_1:
            case Code.Ldloc_2:
            case Code.Ldloc_3:
                local = pushInstr.GetLocal(method.Body.Variables);
                if (local == null)
                {
                    return(null);
                }
                type = local.Type.RemovePinned();
                break;

            case Code.Ldloca:
            case Code.Ldloca_S:
                local = pushInstr.Operand as Local;
                if (local == null)
                {
                    return(null);
                }
                type = CreateByRefType(local.Type.RemovePinned());
                break;

            case Code.Ldarga:
            case Code.Ldarga_S:
                type = CreateByRefType(pushInstr.GetArgumentType(method.MethodSig, method.DeclaringType));
                break;

            case Code.Ldfld:
            case Code.Ldsfld:
                var field = pushInstr.Operand as IField;
                if (field == null || field.FieldSig == null)
                {
                    return(null);
                }
                type = field.FieldSig.GetFieldType();
                break;

            case Code.Ldflda:
            case Code.Ldsflda:
                var field2 = pushInstr.Operand as IField;
                if (field2 == null || field2.FieldSig == null)
                {
                    return(null);
                }
                type = CreateByRefType(field2.FieldSig.GetFieldType());
                break;

            case Code.Ldelema:
            case Code.Unbox:
                type = CreateByRefType(pushInstr.Operand as ITypeDefOrRef);
                break;

            default:
                return(null);
            }

            return(type);
        }
Пример #3
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;
                }
            }
        }