Ejemplo n.º 1
0
 public static void WriteFatSEHHeader(MethodBody mb, BinaryWriter bw)
 {
     int n = mb.ExceptionHandlingClauses.Count;
     int datasize = n * 24 + 4;
     datasize = datasize * 0x100 + 0x41;
     bw.Write(datasize);
 }
Ejemplo n.º 2
0
        private void CopyTryCatch(ILGenerator Gen, int i, MethodBody Body, List<int> ExceptionTrinkets)
        {
            // Quick check to see if we want to walk through the list
            if (!ExceptionTrinkets.Contains(i)) return;

            foreach (ExceptionHandlingClause Clause in Body.ExceptionHandlingClauses)
            {
                if (Clause.Flags != ExceptionHandlingClauseOptions.Clause &&
                   Clause.Flags != ExceptionHandlingClauseOptions.Finally)
                    continue;

                // Look for an ending of an exception block first!
                if (Clause.HandlerOffset + Clause.HandlerLength == i)
                    Gen.EndExceptionBlock();

                // If this marks the beginning of a try block, emit that
                if (Clause.TryOffset == i)
                    Gen.BeginExceptionBlock();

                // Also check for the beginning of a catch block
                if (Clause.HandlerOffset == i && Clause.Flags == ExceptionHandlingClauseOptions.Clause)
                    Gen.BeginCatchBlock(Clause.CatchType);

                // Lastly, check for a finally block
                if (Clause.HandlerOffset == i && Clause.Flags == ExceptionHandlingClauseOptions.Finally)
                    Gen.BeginFinallyBlock();
            }
        }
Ejemplo n.º 3
0
        public void MethodBodyTest()
        {
            MethodInfo        m   = typeof(GenericsUnitTest).GetMethod("MethodTest");
            MethodTableCursor cur = f[TableNames.Method].GetCursor() as MethodTableCursor;

            cur.Goto(m.MetadataToken & 0xFFFFFF);

            System.Reflection.MethodBody rb = m.GetMethodBody();
            CLIFileRW.MethodBody         cb = cur.MethodBody;
            Assert.AreEqual(rb.LocalSignatureMetadataToken & 0xFFFFFF, cb.LocalsSig);

            LocalsVarSig          locals = cb.LocalsSignature;
            IEnumerator <CLIType> lv     = locals.GetVariables().GetEnumerator();

            foreach (LocalVariableInfo v in rb.LocalVariables)
            {
                Assert.IsTrue(lv.MoveNext());
                // Fetch instantiation from local type since we are not driven by CLIFile reflection
                Assert.AreSame(v.LocalType, lv.Current.GetReflectionType(v.LocalType.GetGenericArguments()));
            }

            ILCursor ilc = cb.ILInstructions;

            while (ilc.Next())
            {
                ILInstruction instr = ilc.Instr;
                object        o     = instr.ResolveParameter(f);
            }
        }
		MethodBodyReader (MethodBase method)
		{
			this.method = method;

			this.body = method.GetMethodBody ();
			if (this.body == null)
				throw new ArgumentException ("Method has no body");

			var bytes = body.GetILAsByteArray ();
			if (bytes == null)
				throw new ArgumentException ("Can not get the body of the method");

			if (!(method is ConstructorInfo))
				method_arguments = method.GetGenericArguments ();

			if (method.DeclaringType != null)
				type_arguments = method.DeclaringType.GetGenericArguments ();

            if (!method.IsStatic)
                this_parameter = new ThisParameter(method.DeclaringType);


            this.parameters = method.GetParameters ();
			this.locals = body.LocalVariables;
			this.module = method.Module;
			this.il = new ByteBuffer (bytes);
			this.instructions = new List<Instruction> ((bytes.Length + 1) / 2);
		}
		public NaiveMethodNameExtractor(Delegate @delegate)
		{
			delegateMethod = @delegate.Method;
			body = delegateMethod.GetMethodBody();
			Debug.Assert(body != null);
			module = delegateMethod.Module;
			stream = new MemoryStream(body.GetILAsByteArray());
			Read();
		}
Ejemplo n.º 6
0
        public MethodBaseAdapter(MethodBase actual)
        {
            this.actual = actual;
            this.bodyOfActual = this.actual.GetMethodBody();
            if (bodyOfActual == null)
                throw new NotSupportedException("Method " + actual + " must have a body to adapted using this class.");

            this.Context = new MethodBaseModuleContext(actual);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Disassemble the bytecode of the specified method or constructor
 /// </summary>
 /// <param name="MethodBase">The method to disassemble</param>
 /// <param name="Resolver">A resolver class used while disassembling the code.
 /// Every token resolution and local variable resolution will be made with this resolver</param>
 /// <returns>The list of intruction contained in the method</returns>
 static public List <Instruction> ReadMethod(System.Reflection.MethodBase MethodBase, Resolver Resolver)
 {
     System.Reflection.MethodBody methodBody = MethodBase.GetMethodBody();
     if (methodBody == null)
     {
         return(new List <Instruction>());
     }
     return(ReadMethod(methodBody.GetILAsByteArray(), Resolver));
 }
Ejemplo n.º 8
0
 public MSIL_MethodResolver(System.Reflection.MethodBase Method) : base(Method.DeclaringType.Module)
 {
     System.Reflection.MethodBody body = Method.GetMethodBody();
     if (Method.GetMethodBody() != null)
     {
         foreach (System.Reflection.LocalVariableInfo localsBody in body.LocalVariables)
         {
             System.Reflection.LocalVariableInfo _WAR_local = localsBody;
             _locals.Add(_WAR_local.LocalIndex, _WAR_local);
         }
     }
 }
Ejemplo n.º 9
0
        // Build a cache of points where we need to look for exception trinkets
        // An exception trinket is an object denoting the offsets of try, catch and finally blocks
        private void MineExTrinkets(MethodBody Body, List<int> ExceptionTrinkets)
        {
            foreach (ExceptionHandlingClause Clause in Body.ExceptionHandlingClauses)
            {
                // Only handle catch and finally. TODO: fault and filter
                if (Clause.Flags != ExceptionHandlingClauseOptions.Clause &&
                   Clause.Flags != ExceptionHandlingClauseOptions.Finally)
                    continue;

                ExceptionTrinkets.Add(Clause.TryOffset);
                ExceptionTrinkets.Add(Clause.HandlerOffset);
                ExceptionTrinkets.Add(Clause.HandlerOffset + Clause.HandlerLength);
            }
        }
Ejemplo n.º 10
0
        public static Action <MethodDef> ApplyInject(this MethodBase inject, PatchConfiguration patch) => stub =>
        {
            CilBody            stubBody       = stub.Body;
            MethodBody         injectBody     = inject.GetMethodBody();
            List <Instruction> originalIL     = new List <Instruction>(stubBody.Instructions);
            List <Local>       originalLocals = new List <Local>(stubBody.Variables);
            stubBody.Variables.Clear();
            foreach (LocalVariableInfo local in injectBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex))
            {
                stubBody.Variables.Add(stub.Module.ToDNLib(local));
            }
            List <Instruction> mixinIL = new CilParser(inject.Module, stubBody.Variables, injectBody.GetILAsByteArray()).Parse();
            mixinIL.SimplifyMacros(stubBody.Variables, stub.Parameters);
            IList <Instruction> newIL = stubBody.Instructions;
            newIL.Clear();
            foreach (Instruction inst in mixinIL)
            {
                switch (inst.Operand)
                {
                case FieldInfo field:
                    inst.Operand = patch.ResolveOrImport(stub.Module, field);
                    break;

                case MethodBase method:
                    if (method.IsDefined(typeof(BaseDependencyAttribute)))
                    {
                        throw new InvalidOperationException("attempt to inject a body with a base dependency call");
                    }
                    inst.Operand = patch.ResolveOrImport(stub.Module, method);
                    break;

                case Type type:
                    inst.Operand = patch.ResolveOrImport(stub.Module, type);
                    break;

                case byte[] blob:
                    throw new NotImplementedException("how do you import this?");

                case MemberInfo member:
                    throw new NotImplementedException("how do you import this?");
                }
                newIL.Add(inst);
            }
            stubBody.ExceptionHandlers.Clear();
            foreach (ExceptionHandlingClause ehc in injectBody.ExceptionHandlingClauses)
            {
                stubBody.ExceptionHandlers.Add(ehc.ToDNLib(stub.Module, newIL));
            }
            stubBody.OptimizeMacros();
        };
Ejemplo n.º 11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ILCode"/> class.
        /// </summary>
        /// <param name="method">The method to read the IL code from.</param>
        public ILCode(MethodBase method)
        {
            this.Method = method;
            this.body = this.Method.GetMethodBody();

            if (this.body == null)
            {
                this.ilbytes = new byte[0];
            }
            else
            {
                this.ilbytes = this.body.GetILAsByteArray();
            }

            this.reader = new BinaryReader(new MemoryStream(this.ilbytes, false));
        }
Ejemplo n.º 12
0
        private MethodBodyReader(MethodBase method)
        {
            _method = method;
            _body = method.GetMethodBody();
            if (_body == null)
                throw new ArgumentException("Method has no body");

            var iLAsByteArray = _body.GetILAsByteArray();
            if (iLAsByteArray == null)
                throw new ArgumentException("Can not get the body of the method");

            if (!(method is ConstructorInfo))
                _methodArguments = method.GetGenericArguments();

            if (method.DeclaringType != null)
                _typeArguments = method.DeclaringType.GetGenericArguments();

            _parameters = method.GetParameters();
            _locals = _body.LocalVariables;
            _module = method.Module;
            _il = new ByteBuffer(iLAsByteArray);
        }
Ejemplo n.º 13
0
        public MethodDebugInfo(MethodBody body, ISymbolMethod pdb)
        {
            Body = body;

            // todo. support multiple locals sharing the same local slot 
            // (but having different Start::End offsets, of course)
            // so far we just silently ignore them taking into account only the first one
            var locals = pdb.RootScope.Flatten(ss => ss.GetChildren()).SelectMany(ss => ss.GetLocals());
            LocalNames = locals.Select(lv => new {Index = lv.AddressField1, Name = lv.Name})
                .Distinct().ToDictionary(lv => lv.Index, lv => lv.Name).ToReadOnly();

            var count = pdb.SequencePointCount;
            var offsets = new int[count];
            var documents = new ISymbolDocument[count];
            var lines = new int[count];
            var columns = new int[count];
            var endLines = new int[count];
            var endColumns = new int[count];
            pdb.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns);

            SequencePoints = 0.UpTo(count - 1).Select(i => 
                new SequencePoint(offsets[i], documents[i], lines[i], columns[i], endLines[i], endColumns[i])
            ).ToReadOnly();
        }
        private void _CopyMethodToDefinition()
        {
            MethodBase method     = OriginalMethod;
            Module     moduleFrom = method.Module;

            System.Reflection.MethodBody bodyFrom = method.GetMethodBody();
            byte[] data = bodyFrom?.GetILAsByteArray();
            if (data == null)
            {
                throw new NotSupportedException("Body-less method");
            }

            MethodDefinition def      = Definition;
            ModuleDefinition moduleTo = def.Module;

            Mono.Cecil.Cil.MethodBody bodyTo = def.Body;
            ILProcessor processor            = bodyTo.GetILProcessor();

            Type[] typeArguments = null;
            if (method.DeclaringType.IsGenericType)
            {
                typeArguments = method.DeclaringType.GetGenericArguments();
            }

            Type[] methodArguments = null;
            if (method.IsGenericMethod)
            {
                methodArguments = method.GetGenericArguments();
            }

            foreach (LocalVariableInfo info in bodyFrom.LocalVariables)
            {
                TypeReference type = moduleTo.ImportReference(info.LocalType);
                if (info.IsPinned)
                {
                    type = new PinnedType(type);
                }
                bodyTo.Variables.Add(new VariableDefinition(type));
            }

            using (BinaryReader reader = new BinaryReader(new MemoryStream(data))) {
                for (Instruction instr = null, prev = null; reader.BaseStream.Position < reader.BaseStream.Length; prev = instr)
                {
                    int offset = (int)reader.BaseStream.Position;
                    instr = Instruction.Create(OpCodes.Nop);
                    byte op = reader.ReadByte();
                    instr.OpCode = op != 0xfe ? _CecilOpCodes1X[op] : _CecilOpCodes2X[reader.ReadByte()];
                    instr.Offset = offset;
                    if (prev != null)
                    {
                        prev.Next = instr;
                    }
                    instr.Previous = prev;
                    ReadOperand(reader, instr);
                    bodyTo.Instructions.Add(instr);
                }
            }

            foreach (Instruction instr in bodyTo.Instructions)
            {
                switch (instr.OpCode.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    instr.Operand = GetInstruction((int)instr.Operand);
                    break;

                case OperandType.InlineSwitch:
                    int[]         offsets = (int[])instr.Operand;
                    Instruction[] targets = new Instruction[offsets.Length];
                    for (int i = 0; i < offsets.Length; i++)
                    {
                        targets[i] = GetInstruction(offsets[i]);
                    }
                    instr.Operand = targets;
                    break;
                }
            }

            foreach (ExceptionHandlingClause clause in bodyFrom.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler((ExceptionHandlerType)clause.Flags);
                bodyTo.ExceptionHandlers.Add(handler);

                handler.TryStart = GetInstruction(clause.TryOffset);
                handler.TryEnd   = GetInstruction(clause.TryOffset + clause.TryLength);

                handler.FilterStart  = handler.HandlerType != ExceptionHandlerType.Filter ? null : GetInstruction(clause.FilterOffset);
                handler.HandlerStart = GetInstruction(clause.HandlerOffset);
                handler.HandlerEnd   = GetInstruction(clause.HandlerOffset + clause.HandlerLength);

                handler.CatchType = handler.HandlerType != ExceptionHandlerType.Catch ? null : clause.CatchType == null ? null : moduleTo.ImportReference(clause.CatchType);
            }

            void ReadOperand(BinaryReader reader, Instruction instr)
            {
                int index, offs, length;

                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    instr.Operand = null;
                    break;

                case OperandType.InlineSwitch:
                    length = reader.ReadInt32();
                    offs   = (int)reader.BaseStream.Position + (4 * length);
                    int[] targets = new int[length];
                    for (int i = 0; i < length; i++)
                    {
                        targets[i] = reader.ReadInt32() + offs;
                    }
                    instr.Operand = targets;
                    break;

                case OperandType.ShortInlineBrTarget:
                    offs          = reader.ReadSByte();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.InlineBrTarget:
                    offs          = reader.ReadInt32();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.ShortInlineI:
                    instr.Operand = instr.OpCode == OpCodes.Ldc_I4_S ? reader.ReadSByte() : (object)reader.ReadByte();
                    break;

                case OperandType.InlineI:
                    instr.Operand = reader.ReadInt32();
                    break;

                case OperandType.ShortInlineR:
                    instr.Operand = reader.ReadSingle();
                    break;

                case OperandType.InlineR:
                    instr.Operand = reader.ReadDouble();
                    break;

                case OperandType.InlineI8:
                    instr.Operand = reader.ReadInt64();
                    break;

                case OperandType.InlineSig:
                    instr.Operand = moduleTo.ImportCallSite(moduleFrom, moduleFrom.ResolveSignature(reader.ReadInt32()));
                    break;

                case OperandType.InlineString:
                    instr.Operand = moduleFrom.ResolveString(reader.ReadInt32());
                    break;

                case OperandType.InlineTok:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Any);
                    break;

                case OperandType.InlineType:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Type);
                    break;

                case OperandType.InlineMethod:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Method);
                    break;

                case OperandType.InlineField:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Field);
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineVar ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = bodyTo.Variables[index];
                    break;

                case OperandType.InlineArg:
                case OperandType.ShortInlineArg:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineArg ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = def.Parameters[index];
                    break;

                case OperandType.InlinePhi:     // No opcode seems to use this
                default:
                    throw new NotSupportedException($"Unsupported opcode ${instr.OpCode.Name}");
                }
            }

            MemberReference ResolveTokenAs(int token, TokenResolutionMode resolveMode)
            {
                try {
                    switch (resolveMode)
                    {
                    case TokenResolutionMode.Type:
                        return(moduleTo.ImportReference(moduleFrom.ResolveType(token, typeArguments, methodArguments)));

                    case TokenResolutionMode.Method:
                        return(moduleTo.ImportReference(moduleFrom.ResolveMethod(token, typeArguments, methodArguments)));

                    case TokenResolutionMode.Field:
                        return(moduleTo.ImportReference(moduleFrom.ResolveField(token, typeArguments, methodArguments)));

                    case TokenResolutionMode.Any:
                        switch (moduleFrom.ResolveMember(token, typeArguments, methodArguments))
                        {
                        case Type i:
                            return(moduleTo.ImportReference(i));

                        case MethodBase i:
                            return(moduleTo.ImportReference(i));

                        case FieldInfo i:
                            return(moduleTo.ImportReference(i));

                        case var resolved:
                            throw new NotSupportedException($"Invalid resolved member type {resolved.GetType()}");
                        }

                    default:
                        throw new NotSupportedException($"Invalid TokenResolutionMode {resolveMode}");
                    }
                } catch (MissingMemberException) {
                    // we could not resolve the method normally, so lets read the import table
                    // but we can only do that if the module was loaded from disk
                    // this can still throw if the assembly is a dynamic one, but if that's broken, you have bigger issues
                    string filePath = moduleFrom.Assembly.Location;
                    if (!File.Exists(filePath))
                    {
                        // in this case, the fallback cannot be followed, and so throwing the original error gives the user information
                        throw;
                    }

                    // TODO: make this cached somehow so its not read and re-opened a bunch
                    using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(filePath, new ReaderParameters {
                        ReadingMode = ReadingMode.Deferred
                    })) {
                        ModuleDefinition module = assembly.Modules.First(m => m.Name == moduleFrom.Name);
                        // this should only fail if the token itself is somehow wrong
                        MemberReference reference = (MemberReference)module.LookupToken(token);
                        // the explicit casts here are to throw if they are incorrect
                        // normally the references would need to be imported, but moduleTo isn't written to anywhere
                        switch (resolveMode)
                        {
                        case TokenResolutionMode.Type:
                            return((TypeReference)reference);

                        case TokenResolutionMode.Method:
                            return((MethodReference)reference);

                        case TokenResolutionMode.Field:
                            return((FieldReference)reference);

                        case TokenResolutionMode.Any:
                            return(reference);

                        default:
                            throw new NotSupportedException($"Invalid TokenResolutionMode {resolveMode}");
                        }
                    }
                }
            }

            Instruction GetInstruction(int offset)
            {
                int last = bodyTo.Instructions.Count - 1;

                if (offset < 0 || offset > bodyTo.Instructions[last].Offset)
                {
                    return(null);
                }

                int min = 0;
                int max = last;

                while (min <= max)
                {
                    int         mid   = min + ((max - min) / 2);
                    Instruction instr = bodyTo.Instructions[mid];

                    if (offset == instr.Offset)
                    {
                        return(instr);
                    }

                    if (offset < instr.Offset)
                    {
                        max = mid - 1;
                    }
                    else
                    {
                        min = mid + 1;
                    }
                }

                return(null);
            }
        }
        public static int PushedValuesCount(this Instruction instruction, MethodInfo analyzedMethod, MethodBody methodBody)
        {
            int pushedCount = instruction.PushedValuesCountByOpCode();

            if (methodBody.ExceptionHandlingClauses.Any(x => x.BeginsOn(instruction) && x.IsCatch()))
            {
                pushedCount++;
            }

            return pushedCount;
        }
        MethodBodyReader(MethodBase method)
        {
            this.method = method;

            this.body = method.GetMethodBody();
            if (this.body == null)
                throw new ArgumentNullException();

            var bytes = body.GetILAsByteArray();
            if (bytes == null)
                throw new ArgumentNullException();

            if (!(method is ConstructorInfo))
                method_arguments = method.GetGenericArguments();

            if (method.DeclaringType != null)
                type_arguments = method.DeclaringType.GetGenericArguments();

            this.parameters = method.GetParameters();
            this.locals = body.LocalVariables;
            this.module = method.Module;
            this.il = new ByteBuffer(bytes);
        }
        private void _CopyMethodToDefinition()
        {
            MethodBase method     = OriginalMethod;
            Module     moduleFrom = method.Module;

            System.Reflection.MethodBody bodyFrom = method.GetMethodBody();
            byte[] data = bodyFrom?.GetILAsByteArray();
            if (data == null)
            {
                throw new NotSupportedException("Body-less method");
            }

            MethodDefinition def      = Definition;
            ModuleDefinition moduleTo = def.Module;

            Mono.Cecil.Cil.MethodBody bodyTo = def.Body;
            ILProcessor processor            = bodyTo.GetILProcessor();

            Type[] typeArguments = null;
            if (method.DeclaringType.IsGenericType)
            {
                typeArguments = method.DeclaringType.GetGenericArguments();
            }

            Type[] methodArguments = null;
            if (method.IsGenericMethod)
            {
                methodArguments = method.GetGenericArguments();
            }

            foreach (LocalVariableInfo info in bodyFrom.LocalVariables)
            {
                TypeReference type = moduleTo.ImportReference(info.LocalType);
                if (info.IsPinned)
                {
                    type = new PinnedType(type);
                }
                bodyTo.Variables.Add(new VariableDefinition(type));
            }

            using (BinaryReader reader = new BinaryReader(new MemoryStream(data))) {
                while (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    int         offset = (int)reader.BaseStream.Position;
                    Instruction instr  = Instruction.Create(OpCodes.Nop);
                    byte        op     = reader.ReadByte();
                    instr.OpCode = op != 0xfe ? _CecilOpCodes1X[op] : _CecilOpCodes2X[reader.ReadByte()];
                    instr.Offset = offset;
                    ReadOperand(reader, instr);
                    bodyTo.Instructions.Add(instr);
                }
            }

            foreach (Instruction instr in bodyTo.Instructions)
            {
                switch (instr.OpCode.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    instr.Operand = GetInstruction((int)instr.Operand);
                    break;

                case OperandType.InlineSwitch:
                    int[]         offsets = (int[])instr.Operand;
                    Instruction[] targets = new Instruction[offsets.Length];
                    for (int i = 0; i < offsets.Length; i++)
                    {
                        targets[i] = GetInstruction(offsets[i]);
                    }
                    instr.Operand = targets;
                    break;
                }
            }

            foreach (ExceptionHandlingClause clause in bodyFrom.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler((ExceptionHandlerType)clause.Flags);
                bodyTo.ExceptionHandlers.Add(handler);

                handler.TryStart = GetInstruction(clause.TryOffset);
                handler.TryEnd   = GetInstruction(clause.TryOffset + clause.TryLength);

                handler.FilterStart  = handler.HandlerType != ExceptionHandlerType.Filter ? null : GetInstruction(clause.FilterOffset);
                handler.HandlerStart = GetInstruction(clause.HandlerOffset);
                handler.HandlerEnd   = GetInstruction(clause.HandlerOffset + clause.HandlerLength);

                handler.CatchType = handler.HandlerType != ExceptionHandlerType.Catch ? null : clause.CatchType == null ? null : moduleTo.ImportReference(clause.CatchType);
            }

            void ReadOperand(BinaryReader reader, Instruction instr)
            {
                int index, offs, length;

                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    instr.Operand = null;
                    break;

                case OperandType.InlineSwitch:
                    length = reader.ReadInt32();
                    offs   = (int)reader.BaseStream.Position + (4 * length);
                    int[] targets = new int[length];
                    for (int i = 0; i < length; i++)
                    {
                        targets[i] = reader.ReadInt32() + offs;
                    }
                    instr.Operand = targets;
                    break;

                case OperandType.ShortInlineBrTarget:
                    offs          = reader.ReadSByte();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.InlineBrTarget:
                    offs          = reader.ReadInt32();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.ShortInlineI:
                    instr.Operand = instr.OpCode == OpCodes.Ldc_I4_S ? reader.ReadSByte() : (object)reader.ReadByte();
                    break;

                case OperandType.InlineI:
                    instr.Operand = reader.ReadInt32();
                    break;

                case OperandType.ShortInlineR:
                    instr.Operand = reader.ReadSingle();
                    break;

                case OperandType.InlineR:
                    instr.Operand = reader.ReadDouble();
                    break;

                case OperandType.InlineI8:
                    instr.Operand = reader.ReadInt64();
                    break;

                case OperandType.InlineSig:
                    throw new NotSupportedException("Parsing CallSites at runtime currently not supported");

                case OperandType.InlineString:
                    instr.Operand = moduleFrom.ResolveString(reader.ReadInt32());
                    break;

                case OperandType.InlineTok:
                    switch (moduleFrom.ResolveMember(reader.ReadInt32(), typeArguments, methodArguments))
                    {
                    case Type i:
                        instr.Operand = moduleTo.ImportReference(i);
                        break;

                    case FieldInfo i:
                        instr.Operand = moduleTo.ImportReference(i);
                        break;

                    case MethodBase i:
                        instr.Operand = moduleTo.ImportReference(i);
                        break;
                    }
                    break;

                case OperandType.InlineType:
                    instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveType(reader.ReadInt32(), typeArguments, methodArguments));
                    break;

                case OperandType.InlineMethod:
                    instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveMethod(reader.ReadInt32(), typeArguments, methodArguments));
                    break;

                case OperandType.InlineField:
                    instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveField(reader.ReadInt32(), typeArguments, methodArguments));
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineVar ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = bodyTo.Variables[index];
                    break;

                case OperandType.InlineArg:
                case OperandType.ShortInlineArg:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineArg ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = def.Parameters[index];
                    break;

                case OperandType.InlinePhi:     // No opcode seems to use this
                default:
                    throw new NotSupportedException($"Unsupported opcode ${instr.OpCode.Name}");
                }
            }

            Instruction GetInstruction(int offset)
            {
                int last = bodyTo.Instructions.Count - 1;

                if (offset < 0 || offset > bodyTo.Instructions[last].Offset)
                {
                    return(null);
                }

                int min = 0;
                int max = last;

                while (min <= max)
                {
                    int         mid   = min + ((max - min) / 2);
                    Instruction instr = bodyTo.Instructions[mid];

                    if (offset == instr.Offset)
                    {
                        return(instr);
                    }

                    if (offset < instr.Offset)
                    {
                        max = mid - 1;
                    }
                    else
                    {
                        min = mid + 1;
                    }
                }

                return(null);
            }
        }
Ejemplo n.º 18
0
        public void MethodBodyAllTest()
        {
            Assembly          mscorlib = typeof(object).Assembly;
            CLIFile           f        = CLIFile.Open(mscorlib.Location);
            MethodTableCursor cur      = f[TableNames.Method].GetCursor() as MethodTableCursor;
            int instrcnt = 0;
            int methods  = 0;
            int implmeth = 0;
            int brcnt    = 0;

            while (cur.Next())
            {
                // The token 0x0600449a is not resolved by ResolveMethod, it is likely a bug in reflection.
                // With .NET 3.5 SP1 the method has moved into token 0x44df.
                if (cur.Position == 0x44df)
                {
                    continue;
                }
                MethodBase mb = mscorlib.ManifestModule.ResolveMethod(cur.MetadataToken);

                System.Reflection.MethodBody rb = mb.GetMethodBody();
                methods++;
                if (rb == null)
                {
                    Assert.IsTrue(rb == null && cur.RVA == 0);
                    continue;
                }
                implmeth++;

                CLIFileRW.MethodBody cb = cur.MethodBody;
                Assert.AreEqual(rb.LocalSignatureMetadataToken & 0xFFFFFF, cb.LocalsSig);
                if (rb.LocalSignatureMetadataToken != 0)
                {
                    LocalsVarSig locals = cb.LocalsSignature;

                    IEnumerator <CLIType> lv = locals.GetVariables().GetEnumerator();
                    foreach (LocalVariableInfo v in rb.LocalVariables)
                    {
                        Assert.IsTrue(lv.MoveNext());
                        // Fetch instantiation from local type since we are not driven by CLIFile reflection
                        Assert.AreSame(v.LocalType, lv.Current.GetReflectionType(mb.DeclaringType.ContainsGenericParameters ? mb.DeclaringType.GetGenericArguments() : null, mb.ContainsGenericParameters ? mb.GetGenericArguments() : null));
                    }
                }

                ILCursor ilc = cb.ILInstructions;
                while (ilc.Next())
                {
                    ILInstruction instr = ilc.Instr;
                    object        o     = instr.ResolveParameter(f);
                    instrcnt++;
                    if (instr.op == System.Reflection.Emit.OpCodes.Br || instr.op == System.Reflection.Emit.OpCodes.Br_S)
                    {
                        brcnt++;
                    }
                }
            }

            System.Diagnostics.Debug.WriteLine(string.Format("Total methods: {0}", methods));
            System.Diagnostics.Debug.WriteLine(string.Format("Impl methods: {0}", implmeth));
            System.Diagnostics.Debug.WriteLine(string.Format("Total instructions: {0}", instrcnt));
            System.Diagnostics.Debug.WriteLine(string.Format("Total unconditional branch: {0}", brcnt));
            System.Diagnostics.Debug.WriteLine(string.Format("Average method len: {0}", (instrcnt / (double)methods)));
        }
Ejemplo n.º 19
0
        private MethodBodyReader(MethodBase method)
        {
            this.method = method;

            this.body = method.GetMethodBody();
            if (this.body == null)
            {
                throw new ArgumentException("Method has no body");
            }

            byte[] bytes = this.body.GetILAsByteArray();
            if (bytes == null)
            {
                throw new ArgumentException("Can not get the body of the method");
            }

            if (!(method is ConstructorInfo))
            {
                method.GetGenericArguments();
            }

            if (method.DeclaringType != null)
            {
                method.DeclaringType.GetGenericArguments();
            }

            this.parameters = method.GetParameters();
            this.locals = this.body.LocalVariables;
            this.module = method.Module;
            this.il = new ByteBuffer(bytes);
        }
Ejemplo n.º 20
0
        public static Action <MethodDef> ApplyMixin(this MethodBase mixin, PatchConfiguration patch) => original =>
        {
            CilBody            originalBody   = original.Body;
            MethodBody         mixinBody      = mixin.GetMethodBody();
            List <Instruction> originalIL     = new List <Instruction>(originalBody.Instructions);
            List <Local>       originalLocals = new List <Local>(originalBody.Variables);
            originalBody.Variables.Clear();
            foreach (LocalVariableInfo local in mixinBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex))
            {
                originalBody.Variables.Add(original.Module.ToDNLib(local));
            }
            List <Instruction> mixinIL = new CilParser(mixin.Module, originalBody.Variables, mixinBody.GetILAsByteArray()).Parse();
            mixinIL.SimplifyMacros(originalBody.Variables, original.Parameters);
            IList <Instruction> newIL = originalBody.Instructions;
            newIL.Clear();
            int ilStart = 0;
            if (mixin.IsConstructor)
            {
                foreach (Instruction inst in mixin.IsDefined(typeof(RewriteBaseAttribute)) ? mixinIL : originalIL)
                {
                    ilStart++;
                    newIL.Add(inst);
                    if (inst.OpCode.FlowControl == FlowControl.Call)
                    {
                        break;
                    }
                }
                RemoveCall(originalIL);
                RemoveCall(mixinIL);
            }
            MethodDef baseCopy = new MethodDefUser(original.DeclaringType.FindUnusedMethodName(original.Name + "<Base>$"), original.MethodSig, original.ImplAttributes, original.Attributes & CopyMask | CopyAttr);
            bool      useBase  = false;
            foreach (Instruction inst in mixinIL)
            {
                switch (inst.Operand)
                {
                case FieldInfo field:
                    inst.Operand = patch.ResolveOrImport(original.Module, field);
                    break;

                case MethodBase method:
                    if (method.IsDefined(typeof(BaseDependencyAttribute)))
                    {
                        useBase      = true;
                        inst.Operand = baseCopy;
                        break;
                    }
                    inst.Operand = patch.ResolveOrImport(original.Module, method);
                    break;

                case Type type:
                    inst.Operand = patch.ResolveOrImport(original.Module, type);
                    break;

                case byte[] blob:
                    throw new NotImplementedException("how do you import this?");

                case MemberInfo member:
                    throw new NotImplementedException("how do you import this?");
                }
                newIL.Add(inst);
            }
            if (useBase)
            {
                baseCopy.Body = new CilBody(originalBody.InitLocals, originalIL, new List <ExceptionHandler>(originalBody.ExceptionHandlers), originalBody.Variables);
                original.DeclaringType.Methods.Add(baseCopy);
            }
            originalBody.ExceptionHandlers.Clear();
            foreach (ExceptionHandlingClause ehc in mixinBody.ExceptionHandlingClauses)
            {
                originalBody.ExceptionHandlers.Add(ehc.ToDNLib(original.Module, newIL));
            }
            originalBody.OptimizeMacros();

            void RemoveCall(List <Instruction> il)
            {
                for (int index = 0; index < il.Count; index++)
                {
                    if (il[index].OpCode.FlowControl != FlowControl.Call)
                    {
                        continue;
                    }
                    il.RemoveRange(0, index + 1);
                    break;
                }
            }
        };
Ejemplo n.º 21
0
        private void Write(BinaryWriter bw, Module module, MethodBody mb)
        {
            var locals = mb.LocalVariables;
            bw.Write(locals.Count);
            for (int i=0;i< locals.Count;i++)
            {
                bw.Write(locals[i].LocalType.FullName);
                bw.Write(locals[i].IsPinned);
            }

            var il = mb.GetILAsByteArray();
            for(int i = 0; i < il.Length;)
            {
                EArgumentType argType = EArgumentType.None;
                var opcode = (EOpCode)il[i];
                bw.Write(il[i]);
                i++;

                if(opcode == EOpCode.Extended)
                {
                    bw.Write(il[i]);
                    argType = ((EExtendedOpCode)il[i]).ArgFor();
                    i++;
                }
                else
                    argType = opcode.ArgFor();

                switch (argType)
                {
                    case EArgumentType.Field:
                        var fi = module.ResolveField(BitConverter.ToInt32(il, i));
                        i += 4;
                        bw.Write(Names.Field(fi));
                        break;
                    case EArgumentType.Float32:
                        bw.Write(BitConverter.ToSingle(il, i));
                        i += 4;
                        break;
                    case EArgumentType.Float64:
                        bw.Write(BitConverter.ToDouble(il, i));
                        i += 8;
                        break;
                    case EArgumentType.Token:
                    case EArgumentType.Int32:
                        bw.Write(BitConverter.ToInt32(il, i));
                        i += 4;
                        break;
                    case EArgumentType.Int64:
                        bw.Write(BitConverter.ToInt64(il, i));
                        i += 8;
                        break;
                    case EArgumentType.Int8:
                        bw.Write((sbyte)il[i]);
                        i++;
                        break;
                    case EArgumentType.ListOfInt:
                        uint count = BitConverter.ToUInt32(il, i);
                        bw.Write(count);
                        i += 4;
                        while(count > 0)
                        {
                            bw.Write(BitConverter.ToInt32(il, i));
                            i += 4;
                        }
                        break;
                    case EArgumentType.Method:
                        var mi = module.ResolveMethod(BitConverter.ToInt32(il, i));
                        i += 4;
                        bw.Write(Names.Method(mi));
                        break;
                    case EArgumentType.String:
                        var str = module.ResolveString(BitConverter.ToInt32(il, i));
                        i += 4;
                        bw.Write(str);
                        break;
                    case EArgumentType.Type:
                        var t = module.ResolveType(BitConverter.ToInt32(il, i));
                        i += 4;
                        bw.Write(t.FullName);
                        break;
                    case EArgumentType.Uint16:
                        bw.Write(BitConverter.ToUInt16(il, i));
                        i += 2;
                        break;
                    case EArgumentType.Uint32:
                        bw.Write(BitConverter.ToUInt32(il, i));
                        i += 4;
                        break;
                    case EArgumentType.Uint8:
                        bw.Write(il[i]);
                        i++;
                        break;
                }
            }

            bw.Write((byte)EOpCode.Terminator);
            /*

            var handlers = mb.ExceptionHandlingClauses;
            m_bw.Write(handlers.Count);
            foreach(var h in handlers)
            {
                m_bw.Write(h.TryOffset);
                m_bw.Write(h.TryLength);
                m_bw.Write(h.FilterOffset);
                m_bw.Write(h.HandlerOffset);
                m_bw.Write(h.HandlerLength);
                m_bw.Write((uint)h.Flags);

                //m_bw.Write(h.)
            }*/
        }
Ejemplo n.º 22
0
 // Initialise the variables. TODO: Obey InitLocals
 void CopyLocals(ILGenerator Gen, MethodBody Body)
 {
     foreach(LocalVariableInfo Info in Body.LocalVariables)
         Gen.DeclareLocal(GrabType(Info.LocalType), Info.IsPinned);
 }
Ejemplo n.º 23
0
 public EmitFuncObj(Module module, Function function, MethodBody cilMethod, InstructionBuilder instructionBuilder, object argument, Stack<Value> stack, Value[] locals, Value[] parameters)
 {
     Module = module;
     Function = function;
     CilMethod = cilMethod;
     Builder = instructionBuilder;
     Argument = argument;
     Stack = stack;
     Locals = locals;
     Parameters = parameters;
 }
Ejemplo n.º 24
0
 public static void WriteSEH(MethodBody mb, BinaryWriter bw)
 {
     if (mb.ExceptionHandlingClauses.Count == 0)
         return;
     bool bTiny = IsSEHTiny(mb);
     if (bTiny)
         WriteTinySEHHeader(mb, bw);
     else
         WriteFatSEHHeader(mb, bw);
     foreach (ExceptionHandlingClause ehc in mb.ExceptionHandlingClauses)
     {
         if (bTiny)
             WriteSeHTinyRow(ehc, bw);
         else
             WriteSeHFatRow(ehc, bw);
     }
 }
		MethodBodyReader (MethodBase method)
		{
            //wicky.patch.start: check DynamicMethod
            byte[] bytes;
            if (DynamicMethodHelper.IsDynamicOrRTDynamicMethod(method))
            {
                DynamicMethod dynamicMethod = DynamicMethodHelper.GetDynamicMethod(method);
                this.method = dynamicMethod;
                bytes = DynamicMethodHelper.GetILAsByteArray(dynamicMethod);
                if (bytes == null) 
                    bytes = new byte[0];                
                if (dynamicMethod.DeclaringType != null)
                    type_arguments = dynamicMethod.DeclaringType.GetGenericArguments();
                this.parameters = dynamicMethod.GetParameters();                
                this.module = dynamicMethod.Module;
                //this.locals = ??
                this.il = new ByteBuffer(bytes);
                this.tokenResolver = new DynamicScopeTokenResolver(dynamicMethod);
            }
            else
            {
                this.method = method;
                this.body = method.GetMethodBody();
                if (this.body == null)
                    bytes = new byte[0];
                else
                    bytes = body.GetILAsByteArray();
                if (bytes == null)
                    bytes = new byte[0];

                bytes = body.GetILAsByteArray();

                if (!(method is ConstructorInfo))
                    method_arguments = method.GetGenericArguments();

                if (method.DeclaringType != null)
                    type_arguments = method.DeclaringType.GetGenericArguments();

                this.parameters = method.GetParameters();
                this.locals = body.LocalVariables;
                this.module = method.Module;
                this.il = new ByteBuffer(bytes);
                this.tokenResolver = new ModuleScopeTokenResolver(method);
            }

            /*
            this.method = method;

			this.body = method.GetMethodBody ();
			if (this.body == null)
				throw new ArgumentException ("Method has no body");

			var bytes = body.GetILAsByteArray ();
			if (bytes == null)
				throw new ArgumentException ("Can not get the body of the method");

			if (!(method is ConstructorInfo))
				method_arguments = method.GetGenericArguments ();

			if (method.DeclaringType != null)
				type_arguments = method.DeclaringType.GetGenericArguments ();

			this.parameters = method.GetParameters ();
			this.locals = body.LocalVariables;
			this.module = method.Module;
			this.il = new ByteBuffer (bytes);
            */

            //wicky.patch.end
        }
Ejemplo n.º 26
0
        public ControlFlowGraph(NetMethodBody body, Module module, Type[] genericTypeArguments, Type[] genericMethodArguments)
        {
            // Convert the byte code into instruction objects
            ushort ip = 0;

            byte[] il = body.GetILAsByteArray();

            List <IInstruction> instructions = new List <IInstruction>();

            while (ip < il.Length)
            {
                instructions.Add(OpCodeTable.GetInstruction(il, ref ip, module, genericTypeArguments, genericMethodArguments));
            }

            // Iterate the instructions building a list of call graph nodes
            SortedList <ushort, CallGraphNode> nodes = new SortedList <ushort, CallGraphNode>();
            CallGraphNode node = new CallGraphNode(0);

            nodes.Add(0, node);

            int          index       = 0;
            IInstruction instruction = instructions[index];

            do
            {
                Console.Write(instruction);

                // Create the nodes that this instruction branches to
                switch (instruction.OpCode.FlowControl)
                {
                case FlowControl.Branch:
                {
                    if ((instruction.OpCode != OpCodes.Leave) &&
                        (instruction.OpCode != OpCodes.Leave_S))
                    {
                        // Direct branch to a new instruction that is not a leave instruction from a try-catch block.
                        // Create a call graph node for the target of the branch.
                        MakeNode((ushort)instruction.Argument, nodes);

                        Console.Write(" <-- Branch {0:x4}", instruction.Argument);
                    }

                    break;
                }

                case FlowControl.Cond_Branch:
                {
                    if (instruction.OpCode.Value == OpCodes.Switch.Value)
                    {
                        // Conditional branch to n-blocks
                        foreach (ushort switchTargetIp in (ushort[])instruction.Argument)
                        {
                            MakeNode(switchTargetIp, nodes);
                        }
                    }
                    else
                    {
                        // Conditional branch to two blocks
                        MakeNode((ushort)instruction.Argument, nodes);

                        Console.WriteLine("Making " + instruction.Argument);
                    }

                    // Set the next instruction of a branch to also be a target
                    MakeNode(instructions[index + 1].IP, nodes);
                    Console.Write(" <-- If Node {0:x4}", instruction.Argument);
                    break;
                }

                case FlowControl.Return:
                    // Set the next instruction of a branch to also be a target
                    Console.Write(" <-- Exit Node");
                    break;

                case FlowControl.Throw:
                    // End of graph
                    Console.Write(" <-- Throw Node");
                    break;

                case FlowControl.Break:
                case FlowControl.Call:
                case FlowControl.Meta:
                case FlowControl.Next:
#pragma warning disable 612,618
                case FlowControl.Phi:
#pragma warning restore 612,618
                    // Add the continuation link
                    //node.NodeType = NodeType.FallThrough;
                    //MakeNode(ip, node, nodes);
                    break;
                }

                Console.WriteLine();

                // Get the next instruction
                index++;
                if (index < instructions.Count)
                {
                    instruction = instructions[index];

                    // Find the node to add the next instruction to
                    CallGraphNode nextNode;
                    if (nodes.TryGetValue(instruction.IP, out nextNode))
                    {
                        /*if (node.NodeType == NodeType.FallThrough)
                         * {
                         *      Console.Write("added fall through link ");
                         *      node.OutEdges.Add(nextNode);
                         *      nextNode.InEdges.Add(node);
                         * }*/



                        node = nextNode;

                        Console.Write("New Node --> ");
                    }
                }
            } while (index < instructions.Count);

            Console.WriteLine();

            // Iterate the instructions a second time adding them to the correct nodes
            //CallGraphNode node;
            node = nodes[0];
            for (index = 0; index < instructions.Count; index++)
            {
                instruction = instructions[index];

                if (index > 0)
                {
                    CallGraphNode nextNode;
                    if (nodes.TryGetValue(instruction.IP, out nextNode))
                    {
                        if (node.OutEdges.Count == 0)
                        {
                            Console.WriteLine("ff");
                            node.NodeType = NodeType.FallThrough;
                            LinkNode(node, nextNode);
                        }
                        Console.Write("--" + node.OutEdges.Count + "--");
                        node = nextNode;
                        Console.Write("new node ");
                    }
                }

                Console.WriteLine(instruction);
                node.Instructions.Add(instruction);

                // Create the nodes that this instruction branches to
                switch (instruction.OpCode.FlowControl)
                {
                case FlowControl.Branch:
                {
                    if ((instruction.OpCode != OpCodes.Leave) &&
                        (instruction.OpCode != OpCodes.Leave_S))
                    {
                        // Direct branch to a new instruction that is not a leave instruction from a try-catch block.
                        // Create a call graph node for the target of the branch.
                        node.NodeType = NodeType.OneBranch;
                        LinkNode(node, nodes[(ushort)instruction.Argument]);

                        Console.Write(" <-- Branch {0:x4}", instruction.Argument);
                    }

                    break;
                }

                case FlowControl.Cond_Branch:
                {
                    if (instruction.OpCode.Value == OpCodes.Switch.Value)
                    {
                        // Conditional branch to n-blocks
                        node.NodeType = NodeType.MultiBranch;
                        foreach (ushort switchTargetIp in (ushort[])instruction.Argument)
                        {
                            LinkNode(node, nodes[switchTargetIp]);
                        }
                    }
                    else
                    {
                        // Conditional branch to two blocks
                        node.NodeType = NodeType.TwoBranch;
                        LinkNode(node, nodes[(ushort)instruction.Argument]);
                        Console.Write("Linking " + instruction.Argument);
                    }

                    // Set the next instruction of a branch to also be a target
                    LinkNode(node, nodes[instructions[index + 1].IP]);
                    Console.Write(" <-- If Node {0:x4}", instruction.Argument);
                    break;
                }

                case FlowControl.Return:
                    // Set the next instruction of a branch to also be a target
                    node.NodeType = NodeType.Exit;
                    Console.Write(" <-- Exit Node");
                    break;

                case FlowControl.Throw:
                    // End of graph
                    node.NodeType = NodeType.Throw;
                    Console.Write(" <-- Throw Node");
                    break;
                }
            }



            // Copy the nodes to a simple list
            _nodes.AddRange(nodes.Values);

            Console.WriteLine();
            Console.WriteLine(_nodes.Count);
            foreach (CallGraphNode n in _nodes)
            {
                Console.WriteLine(n.StartIP + " " + n.NodeType + " " + n.OutEdges.Count);
            }

            CheckGraph();

            // Add the exception information - build a sorted tree of clauses
            SortedList <int, TryHandler> clauses = new SortedList <int, TryHandler>();
            foreach (ExceptionHandlingClause clause in body.ExceptionHandlingClauses)
            {
                Add(new TryHandler(clause), clauses);
            }

            foreach (TryHandler clause in clauses.Values)
            {
                TraverseExceptionTree(clause);
            }

            // Find the root node -- This fails when there are multiple try statements on the first instruction
            for (int i = 0; i < _nodes.Count; i++)
            {
                if (_nodes[i].StartIP == 0)
                {
                    _rootNode = _nodes[i];
                    break;
                }
            }

            if (_rootNode == null)
            {
                throw new ApplicationException("Unable to find a root node");
            }

            CheckGraph();

            // Remove redundancies and add in-edge information
            Optimize();

            CheckGraph();

            // Visit the graph in depth first order and label the nodes
            _depthFirstSearchLast = new CallGraphNode[_nodes.Count];
            int last = _nodes.Count - 1;
            DepthFirstTraverse(_rootNode, ref last);

            // Find the immediate dominators of each node
            FindImmediateDominators();

            // Check the graph for reducibility
            FindDerivedSequence();

            // Work out the graphs back edges
            DetermineBackEdges();

            ResetTraversal();
            StructureCases();
            StructureLoops();
            StructureIfs();
            ResetTraversal();
        }
Ejemplo n.º 27
0
        static void Main(string[] args)
        {
            module = ModuleDefMD.Load(args[0]);
            AssemblyName assemblyName = AssemblyName.GetAssemblyName(args[0]);
            Assembly     assembly     = Assembly.Load(assemblyName);
            Module       Module_L     = assembly.GetModules()[0];

            mod = Module_L;
            foreach (EmbeddedResource res in module.Resources)
            {
                if (res.Name == "Eddy^CZ_")
                {
                    using (new StreamReader(res.GetResourceStream()))
                    {
                        byte[] ar = new byte[res.GetResourceStream().Length];
                        res.GetResourceStream().Read(ar, 0, ar.Length);
                        byteArrayResource = ar;
                    }
                }
            }


            byte[] buffer = null;

            foreach (EmbeddedResource res in module.Resources)
            {
                if (res.Name == "Eddy^CZ")
                {
                    using (new StreamReader(res.GetResourceStream()))
                    {
                        byte[] arr = new byte[res.GetResourceStream().Length];
                        res.GetResourceStream().Read(arr, 0, arr.Length);
                        buffer = arr;
                    }
                }
            }

            binr                  = new BinaryReader(new MemoryStream(buffer));
            All.val               = new ValueStack();
            All.val.parameters    = new object[1];
            All.val.parameters[0] = byteArrayResource;
            All.val.locals        = new object[10];
            All.run(binr);



            bool   flag = IntPtr.Size == 4;
            IntPtr ptr  = default(IntPtr);

            if (flag)
            {
                ExtractEmbeddedDlls("NativePRo.dll", File.ReadAllBytes(Directory.GetCurrentDirectory() + "\\X86"));

                IntPtr intptr = LoadDll("NativePRo.dll");
                ptr = Inisialize.e(intptr, "_a@16");
            }
            else
            {
                ExtractEmbeddedDlls("NativePRo.dll", File.ReadAllBytes("X64"));

                IntPtr intptr = LoadDll("NativePRo.dll");
                ptr = Inisialize.e(intptr, "a");
            }
            Inisialize.bc     = (Inisialize.a)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Inisialize.a));
            byteArrayResource = (byte[])All.val.locals[1];



            OpCode[] array  = new OpCode[256];
            OpCode[] array2 = new OpCode[256];
            oneByteOpCodes = array;
            twoByteOpCodes = array2;
            Type typeFromHandle  = typeof(OpCode);
            Type typeFromHandle2 = typeof(OpCodes);

            foreach (FieldInfo fieldInfo in typeFromHandle2.GetFields())
            {
                bool flag2 = fieldInfo.FieldType == typeFromHandle;
                if (flag2)
                {
                    OpCode opCode = (OpCode)fieldInfo.GetValue(null);
                    ushort num    = (ushort)opCode.Value;
                    bool   flag3  = opCode.Size == 1;
                    if (flag3)
                    {
                        byte b = (byte)num;
                        oneByteOpCodes[(int)b] = opCode;
                        // Console.WriteLine(opCode.Name);
                    }
                    else
                    {
                        byte b2 = (byte)(num | 65024);
                        twoByteOpCodes[(int)b2] = opCode;
                        //Console.WriteLine(opCode.Name);
                    }
                }
            }



            foreach (var type in module.Types)
            {
                try
                {
                    foreach (var method in type.Methods)
                    {
                        try
                        {
                            if (is_virualized(method))
                            {
                                List <dnlib.DotNet.Emit.Instruction> real = new List <dnlib.DotNet.Emit.Instruction>();
                                for (int i = 0; i < method.Body.Instructions.Count; i++)
                                {
                                    try
                                    {
                                        if (method.Body.Instructions[i].OpCode == dnlib.DotNet.Emit.OpCodes.Call)
                                        {
                                            if (method.Body.Instructions[i].Operand.ToString().Contains("Runner"))
                                            {
                                                #region Resolve Method
                                                int        md                       = (int)((MethodDef)method).MDToken.Raw;
                                                MethodBase callingMethod            = Module_L.ResolveMethod(md);
                                                dnlib.DotNet.Emit.Instruction instr = new dnlib.DotNet.Emit.Instruction();
                                                #endregion

                                                #region Параметры
                                                int position = method.Body.Instructions[i - 4].GetLdcI4Value();
                                                int size     = method.Body.Instructions[i - 3].GetLdcI4Value();
                                                int ID       = method.Body.Instructions[i - 2].GetLdcI4Value();
                                                Console.WriteLine("Recovering Method - " + method.FullName + "_Keys --_--" + position.ToString() + "--_--" + size.ToString() + "--_--" + ID.ToString());
                                                #endregion

                                                #region  асшифровка Опкодов
                                                byte[] array4        = byteArrayGrabber(byteArrayResource, position, size);
                                                byte[] key           = MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(method.Name));
                                                byte[] ilasByteArray = callingMethod.GetMethodBody().GetILAsByteArray();
                                                Inisialize.bc(array4, array4.Length, ilasByteArray, ilasByteArray.Length);
                                                byte[] bytes = Decrypt(key, array4);
                                                #endregion

                                                #region Получение Опкодов из Ресурсов
                                                System.Reflection.MethodBody methodBody = callingMethod.GetMethodBody();
                                                BinaryReader        binaryReader        = new BinaryReader(new MemoryStream(bytes));
                                                ParameterInfo[]     parameters2         = callingMethod.GetParameters();
                                                List <LocalBuilder> list = new List <LocalBuilder>();
                                                int    num      = 0;
                                                bool   isStatic = callingMethod.IsStatic;
                                                Type[] array5;
                                                if (isStatic)
                                                {
                                                    array5 = new Type[parameters2.Length];
                                                }
                                                else
                                                {
                                                    array5    = new Type[parameters2.Length + 1];
                                                    array5[0] = callingMethod.DeclaringType;
                                                    num       = 1;
                                                }
                                                for (int z = 0; z < parameters2.Length; z++)
                                                {
                                                    ParameterInfo parameterInfo = parameters2[z];
                                                    array5[num + z] = parameterInfo.ParameterType;
                                                }

                                                DynamicMethod             dynamicMethod  = new DynamicMethod("", (callingMethod.MemberType == MemberTypes.Constructor) ? null : ((MethodInfo)callingMethod).ReturnParameter.ParameterType, array5, Module_L, true);
                                                ILGenerator               ilgenerator    = dynamicMethod.GetILGenerator();
                                                IList <LocalVariableInfo> localVariables = methodBody.LocalVariables;
                                                foreach (LocalVariableInfo localVariableInfo in localVariables)
                                                {
                                                    list.Add(ilgenerator.DeclareLocal(localVariableInfo.LocalType));
                                                }
                                                int count = binaryReader.ReadInt32();

                                                int num2 = binaryReader.ReadInt32();
                                                Dictionary <int, Label> dictionary = new Dictionary <int, Label>();
                                                for (int j = 0; j < num2; j++)
                                                {
                                                    Label value = ilgenerator.DefineLabel();
                                                    dictionary.Add(j, value);
                                                }

                                                for (int k = 0; k < num2; k++)
                                                {
                                                    short  num3  = binaryReader.ReadInt16();
                                                    bool   flags = num3 >= 0 && (int)num3 < oneByteOpCodes.Length;
                                                    OpCode opcode;
                                                    if (flags)
                                                    {
                                                        opcode = oneByteOpCodes[(int)num3];
                                                    }
                                                    else
                                                    {
                                                        byte b = (byte)((int)num3 | 65024);
                                                        opcode = twoByteOpCodes[(int)b];
                                                    }
                                                    #endregion


                                                    byte   opType = binaryReader.ReadByte();
                                                    object a      = OperandInitialiser.Initialise(opType, binaryReader, assembly.GetModules()[0], dictionary, list);
                                                    try
                                                    {
                                                        real.Add(OpcodeConverter.converter(opcode, a, binaryReader, assembly.GetModules()[0]));
                                                    }
                                                    catch
                                                    {
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                    }
                                }
                                method.Body.Instructions.Clear();
                                foreach (var fes in real)
                                {
                                    method.Body.Instructions.Add(fes);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                        }
                    }
                }
                catch
                {
                }
            }



            module.Write("lsd.exe", new ModuleWriterOptions(module)
            {
                MetaDataOptions =
                {
                    Flags = MetaDataFlags.PreserveAll
                },
                Logger = DummyLogger.NoThrowInstance
            });


            Console.WriteLine("=================================");
            Console.ReadLine();
        }
Ejemplo n.º 28
0
        private static void AnalizeMore(MethodBody methodBody, byte[] il, Action<string[]> self)
        {
            Console.ReadLine();

            // 分岐ターゲットが正しく取得できたので、分岐フローを元に構造認識が可能になります
            // 構造認識では、制御フローに関するステートメントに着目したいため、制御フロー影響
            // の無い命令群をまとめてそれらと制御フローの関連付けができる単位が必要になります。
            var exceptionHandlingClauses = methodBody.ExceptionHandlingClauses.ToArray();
            GettingControlFlowElement(il, exceptionHandlingClauses);

            Console.ReadLine();

            // 制御構造の認識ができると、IL上でプログラムがどのように進行するかという動作パスを
            // 考える事ができるようになります。動作パスを意識する事で、IL命令がどの順に実行され
            // えるのかが分かります。
            var controlFlow = Msil.PopulateControlFlowPath(il, exceptionHandlingClauses);
            Console.WriteLine(controlFlow.Count + " path found");
            Console.WriteLine(controlFlow.First().Key);

            Console.ReadLine();

            // 動作パスが列挙されたので、その動作パスを使ってILの評価スタックをシミュレートする
            // と、どのIL命令がどのIL命令の出力を使うのかというデータ依存関係が得られます。
            // このデータ依存関係は、最終的にローカル変数やフィールドに書かれる物がどのように計算
            // されるのか、条件分岐命令の条件はいったい何なのかを表現します。
            var ilinsts = Msil.ILInstructions(il).ToArray();
            var runs = Msil.GetRuns(ilinsts,il.Length, exceptionHandlingClauses).ToArray();
            var dataFlowSource = new Dictionary<int, List<Tuple<int, int>>>();
            foreach (var flow in controlFlow)
            {
                Msil.SimulateEvalStack(runs, flow.Value, dataFlowSource, self.Method.Module);
            }
            DisassembleWithDataFlow(runs, dataFlowSource);

            Console.ReadLine();

            // 依存関係グラフを再帰的に追う事でプログラム内のデータ依存関係を式風に表示する事も
            // できます。
            var setlocalOpCodes = new[]
                {
                    OpCodes.Stloc.Value,
                    OpCodes.Stloc_0.Value,
                    OpCodes.Stloc_1.Value,
                    OpCodes.Stloc_2.Value,
                    OpCodes.Stloc_3.Value,
                    OpCodes.Stloc_S.Value
                };

            foreach (var run in runs)
            {
                Console.WriteLine("IL_{0:X4}:",run.StartIndex);

                foreach (var instruction in run.Instructions)
                {
                    var opCode = instruction.OpCode;
                    if (setlocalOpCodes.Contains(opCode.Value))
                    {
                        var localIndex = instruction.GetLocalIndex();
                        var startIndex = instruction.StartIndex;
                        List<Tuple<int, int>> source;

                        string sourceDesc;
                        if (!dataFlowSource.TryGetValue(startIndex, out source))
                        {
                            sourceDesc = "/* unknown */"; // 例外による動作フローを追わない為、例外系での処理が認識されません
                        }
                        else
                        {
                            var popCnts = source.Select(t => t.Item1).Distinct().OrderBy(n => n);

                            var sources =
                                popCnts.Select(
                                    popCnt => string.Join(" or ",
                                        source.Where(t => t.Item1 == popCnt)
                                            .Distinct()
                                            .Select(t => "(" + Describe(t.Item2, ilinsts, dataFlowSource,self.Method.Module) + ")"))).ToList();
                            sourceDesc = string.Join(",", sources);
                        }
                        Console.WriteLine("  local_{0} = {1}", localIndex, sourceDesc);
                    }

                    if (opCode.Value == OpCodes.Call.Value || opCode.Value == OpCodes.Calli.Value ||
                        opCode.Value == OpCodes.Callvirt.Value)
                    {
                        // 結果がどこにも使われない call は表示
                        if (dataFlowSource.Values.SelectMany(_ => _).All(t => t.Item2 != instruction.StartIndex))
                        {
                            Console.WriteLine("  {0}",
                                              Describe(instruction.StartIndex, ilinsts, dataFlowSource,
                                                       self.Method.Module));
                        }
                    }

                    if (opCode.FlowControl == FlowControl.Cond_Branch )
                    {
                        if (opCode.Value != OpCodes.Switch.Value)
                        {
                            Console.WriteLine("  {0} goto IL_{1:X4}",
                                              Describe(instruction.StartIndex, ilinsts, dataFlowSource,
                                                       self.Method.Module),
                                              instruction.GetBranchLocation());
                        }
                        else
                        {
                            Console.WriteLine("  {0} {1}",
                                              Describe(instruction.StartIndex, ilinsts, dataFlowSource,
                                                       self.Method.Module),
                                             string.Join(", ",instruction.GetBranchLocations().Select(n=> string.Format("IL_{0:X4}",n)))
                                );
                        }
                    }
                    if (opCode.FlowControl == FlowControl.Branch)
                    {
                        Console.WriteLine("  goto IL_{0:X4}", instruction.GetBranchLocation());
                    }
                }
            }
            Console.ReadLine();
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Validates an actual method body (the cloned version) against an expected method body (its source).
        /// </summary>
        /// <param name="actualMethodBody">Method body to validate.</param>
        /// <param name="expectedMethodBody">Method body with expeted info.</param>
        private static void ValidateMethodBody(MethodBody actualMethodBody, MethodBody expectedMethodBody)
        {
            Assert.That(actualMethodBody == null, Is.EqualTo(expectedMethodBody == null));
            if (actualMethodBody == null) { return; }

            Assert.That(actualMethodBody.InitLocals, Is.EqualTo(expectedMethodBody.InitLocals));
            Assert.That(actualMethodBody.MaxStackSize, Is.EqualTo(expectedMethodBody.MaxStackSize));

            Assert.That(actualMethodBody.ExceptionHandlingClauses.Count, Is.EqualTo(expectedMethodBody.ExceptionHandlingClauses.Count));
            for (int i = 0; i < actualMethodBody.ExceptionHandlingClauses.Count; i++)
            {
                ValidateExceptionHandlingClause(actualMethodBody.ExceptionHandlingClauses[i], expectedMethodBody.ExceptionHandlingClauses[i]);
            }

            Assert.That(actualMethodBody.LocalVariables.Count, Is.EqualTo(expectedMethodBody.LocalVariables.Count));
            for (int i = 0; i < actualMethodBody.LocalVariables.Count; i++)
            {
                ValidateLocalVariable(actualMethodBody.LocalVariables[i], expectedMethodBody.LocalVariables[i]);
            }
        }
Ejemplo n.º 30
0
        public static void WriteILCode(MethodBody mb, BinaryWriter writer)
        {
            int codesize = mb.GetILAsByteArray().Length;
            writer.Write(mb.GetILAsByteArray());

            // 对齐 4 bytes
            int ig = codesize & 3;
            if (ig == 0)
                return;
            if (mb.ExceptionHandlingClauses.Count == 0)
                return;//无SEH;
            ig = 4 - ig;
            for(int i=0; i<ig;i++)
            {
                writer.Write((byte)0);
            }
        }
Ejemplo n.º 31
0
        public ILReader(MethodBase InputMethod, FieldInfo[] FieldsInModule, MethodBase[] MethodsInModule, Assembly currentAssm)
        {
            workingAssm = currentAssm;
            MethodOpcodes = new ArrayList();
            InputMeth = InputMethod;
            ExceptionHandlers = new ArrayList();

            if (InputMethod == null)
            {
                Console.WriteLine("Error, input method is not specified, can not continue");
                return;
            }
            methodBody = InputMethod.GetMethodBody();
            curModule = InputMethod.DeclaringType.Module;

            pos = 0;
            pos1 = 0;

            IL = methodBody.GetILAsByteArray();

            IList<ExceptionHandlingClause>  ehClauses = methodBody.ExceptionHandlingClauses;
            foreach( ExceptionHandlingClause ehclause in ehClauses )
            {
                ExceptionHandlers.Add(new ExceptionInstruction(ehclause.TryOffset,ExceptionHandler.Try,null));
                switch (ehclause.Flags)
                {
                    //case 0:
                    case ExceptionHandlingClauseOptions.Clause:
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.Catch,ehclause.CatchType));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null));
                    break;
                    //case 1:
                case ExceptionHandlingClauseOptions.Filter:
                    ExceptionHandlers.Add(new ExceptionInstruction(ehclause.FilterOffset,ExceptionHandler.Filter,null));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.EndFilter,null));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null));
                        break;
                    //case 2:
                    case ExceptionHandlingClauseOptions.Finally:
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.Finally,null));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null));
                        break;
                    //case 4:
                    case ExceptionHandlingClauseOptions.Fault:
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.Fault,null));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null));
                        break;
                }
            }
            // populate opcode
            Opcode Op = GetOpcode();
            while (Op.Name != "")												// This cycles through all the Opcodes
            {
                if (Op.Name != "stfld")
                    MethodOpcodes.Add(Op);
                Op = GetOpcode();
            }
            // sort the stfld opcodes and output
            // this will make the opcode invalid for run.
            // but out purpose is simply compare the assemblies.
            StfldList.Sort(new StringCompare());
            foreach (object i in StfldList)
            {
                Opcode temp = new Opcode("stfld", i);
                MakeLabel(temp, false);
                MethodOpcodes.Add(temp);
            }
        }
Ejemplo n.º 32
0
 public static void WriteTinySEHHeader(MethodBody mb, BinaryWriter bw)
 {
     int n = mb.ExceptionHandlingClauses.Count;
     int datasize = n * 12 + 4;
     bw.Write((byte)1);
     bw.Write((byte)datasize);
     bw.Write((byte)0);
     bw.Write((byte)0);
 }
Ejemplo n.º 33
0
 private void ExamineLocalVariables(MethodBody body, MethodInfo method = null)
 {
     Console.WriteLine("\n\t\t-- Local variables");
     body.LocalVariables.ToList().ForEach(x => Console.WriteLine("\t\t| " + x));
     Console.WriteLine("\t\t-- End of local variables\n");
 }
Ejemplo n.º 34
0
 public MethodBody(System.Reflection.MethodBody body)
     : this(body, false)
 {
 }
Ejemplo n.º 35
0
 public MethodBody(System.Reflection.MethodBody body, bool loadDebugInfo)
     : this(body.AssertNotNull().Get("m_methodBase").AssertCast <MethodBase>(), loadDebugInfo)
 {
 }
Ejemplo n.º 36
0
        private MethodBodyReader(MethodBase method, MethodBody mb)
        {
            this.method = method;

            body = mb;
            if (body == null)
                throw new ArgumentException();

            var bytes = body.GetILAsByteArray();
            if (bytes == null)
                throw new ArgumentException();

            if (!(method is ConstructorInfo))
                method_arguments = method.GetGenericArguments();

            if (method.DeclaringType != null)
                generic_type_arguments = method.DeclaringType.GetGenericArguments();

            parameters = method.GetParameters();
            locals = body.LocalVariables;
            module = method.Module;
            il = new ByteBuffer(bytes);
        }
Ejemplo n.º 37
0
 internal IMethodBody GetBody(MethodBody methodBody) {
   throw new NotImplementedException();
 }