예제 #1
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);
        }
예제 #2
0
        public bool deobfuscate(List <Block> allBlocks)
        {
            if (!init(allBlocks))
            {
                return(false);
            }

            bool changed = false;

            var indexesToRemove = new List <int>();

            foreach (var block in allBlocks)
            {
                indexesToRemove.Clear();
                var instrs = block.Instructions;
                for (int i = 0; i < instrs.Count - 1; i++)
                {
                    var instr = instrs[i];
                    if (instr.OpCode.Code == Code.Ldloca || instr.OpCode.Code == Code.Ldloca_S)
                    {
                        var local = instr.Operand as VariableDefinition;
                        if (local == null)
                        {
                            continue;
                        }
                        localInfos[local].invalid();
                    }
                    else if (instr.isLdloc())
                    {
                        var local = DotNetUtils.getLocalVar(blocks.Locals, instr.Instruction);
                        if (local == null)
                        {
                            continue;
                        }
                        var localInfo = localInfos[local];
                        var cast      = instrs[i + 1];
                        if (localInfo.CastType == null)
                        {
                            continue;
                        }
                        if (!isCast(cast))
                        {
                            throw new ApplicationException("Not a cast instr");
                        }

                        indexesToRemove.Add(i + 1);
                    }
                }
                if (indexesToRemove.Count > 0)
                {
                    block.remove(indexesToRemove);
                    changed = true;
                }
            }

            foreach (var info in localInfos.Values)
            {
                if (info.CastType == null)
                {
                    continue;
                }
                info.local.VariableType = info.CastType;
            }

            if (changed)
            {
                foreach (var block in allBlocks)
                {
                    var instrs = block.Instructions;
                    for (int i = 0; i < instrs.Count - 1; i++)
                    {
                        var instr     = instrs[i];
                        int castIndex = i + 1;
                        if (instr.OpCode.Code == Code.Dup)
                        {
                            if (i == 0)
                            {
                                continue;
                            }
                            castIndex = i;
                            instr     = instrs[i - 1];
                        }

                        if (instr.isLdarg())
                        {
                            addCast(block, castIndex, i + 1, DotNetUtils.getArgType(blocks.Method, instr.Instruction));
                        }
                        else if (instr.OpCode.Code == Code.Ldfld || instr.OpCode.Code == Code.Ldsfld)
                        {
                            var field = instr.Operand as FieldReference;
                            if (field == null)
                            {
                                continue;
                            }
                            addCast(block, castIndex, i + 1, field.FieldType);
                        }
                        else if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt)
                        {
                            var calledMethod = instr.Operand as MethodReference;
                            if (calledMethod == null || !DotNetUtils.hasReturnValue(calledMethod))
                            {
                                continue;
                            }
                            addCast(block, castIndex, i + 1, calledMethod.MethodReturnType.ReturnType);
                        }
                    }
                }
            }

            return(changed);
        }