Ejemplo n.º 1
0
        TypeReference getLoadedType(IGenericParameterProvider gpp, MethodDefinition method, IList <Instruction> instructions, int instrIndex, out bool wasNewobj)
        {
            var fieldType = MethodStack.getLoadedType(method, instructions, instrIndex, out wasNewobj);

            if (fieldType == null || !isValidType(gpp, fieldType))
            {
                return(null);
            }
            return(fieldType);
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        void deobfuscateMethod(MethodDefinition method)
        {
            if (!method.IsStatic || method.Body == null)
            {
                return;
            }

            bool fixReturnType = isUnknownType(method.MethodReturnType);

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

            var        methodParams = DotNetUtils.getParameters(method);
            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 MethodReference;
                    if (calledMethod == null)
                    {
                        break;
                    }
                    var calledMethodParams = DotNetUtils.getParameters(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.getParameter(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 TypeReference);
                    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)), DotNetUtils.getLocalVar(method.Body.Variables, instr));
                    break;

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

                case Code.Stfld:
                    pushedArgs = MethodStack.getPushedArgInstructions(instructions, i);
                    if (pushedArgs.NumValidArgs >= 1)
                    {
                        var field = instr.Operand as FieldReference;
                        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 FieldReference);
                    break;

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

                case Code.Ldelema:
                case Code.Ldelem_Any:
                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_Any:
                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;
                }
            }
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        public static TypeReference getLoadedType(MethodDefinition 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);
            }

            TypeReference      type;
            VariableDefinition local;

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

            case Code.Conv_I:
            case Code.Conv_Ovf_I:
            case Code.Conv_Ovf_I_Un:
                type = method.Module.TypeSystem.IntPtr;
                break;

            case Code.Conv_U:
            case Code.Conv_Ovf_U:
            case Code.Conv_Ovf_U_Un:
                type = method.Module.TypeSystem.UIntPtr;
                break;

            case Code.Conv_I8:
            case Code.Conv_Ovf_I8:
            case Code.Conv_Ovf_I8_Un:
                type = method.Module.TypeSystem.Int64;
                break;

            case Code.Conv_U8:
            case Code.Conv_Ovf_U8:
            case Code.Conv_Ovf_U8_Un:
                type = method.Module.TypeSystem.UInt64;
                break;

            case Code.Conv_R8:
            case Code.Ldc_R8:
            case Code.Ldelem_R8:
            case Code.Ldind_R8:
                type = method.Module.TypeSystem.Double;
                break;

            case Code.Call:
            case Code.Calli:
            case Code.Callvirt:
                var calledMethod = pushInstr.Operand as MethodReference;
                if (calledMethod == null)
                {
                    return(null);
                }
                type = calledMethod.MethodReturnType.ReturnType;
                break;

            case Code.Newarr:
                type = pushInstr.Operand as TypeReference;
                if (type == null)
                {
                    return(null);
                }
                type      = new ArrayType(type);
                wasNewobj = true;
                break;

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

            case Code.Castclass:
            case Code.Isinst:
            case Code.Unbox_Any:
            case Code.Ldelem_Any:
            case Code.Ldobj:
                type = pushInstr.Operand as TypeReference;
                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 = DotNetUtils.getArgType(method, pushInstr);
                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 = DotNetUtils.getLocalVar(method.Body.Variables, pushInstr);
                if (local == null)
                {
                    return(null);
                }
                type = local.VariableType;
                break;

            case Code.Ldloca:
            case Code.Ldloca_S:
                local = pushInstr.Operand as VariableDefinition;
                if (local == null)
                {
                    return(null);
                }
                type = createByReferenceType(local.VariableType);
                break;

            case Code.Ldarga:
            case Code.Ldarga_S:
                type = createByReferenceType(DotNetUtils.getArgType(method, pushInstr));
                break;

            case Code.Ldfld:
            case Code.Ldsfld:
                var field = pushInstr.Operand as FieldReference;
                if (field == null)
                {
                    return(null);
                }
                type = field.FieldType;
                break;

            case Code.Ldflda:
            case Code.Ldsflda:
                var field2 = pushInstr.Operand as FieldReference;
                if (field2 == null)
                {
                    return(null);
                }
                type = createByReferenceType(field2.FieldType);
                break;

            case Code.Ldelema:
            case Code.Unbox:
                type = createByReferenceType(pushInstr.Operand as TypeReference);
                break;

            default:
                return(null);
            }

            return(type);
        }
Ejemplo n.º 6
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);
        }