Click here to Skip to main content
15,886,724 members
Articles / Programming Languages / MSIL

Assembly Manipulation and C# / VB.NET Code Injection

Rate me:
Please Sign up or sign in to vote.
4.95/5 (200 votes)
26 Apr 2013MIT5 min read 922K   25K   486  
Reflexil is an assembly editor and runs as a plug-in for Reflector or JustDecompile. Reflexil is able to manipulate IL code and save the modified assemblies to disk. Reflexil also supports "on-the-fly" C#/VB.NET code injection.
/*
    Reflexil .NET assembly editor.
    Copyright (C) 2007 Sebastien LEBRETON

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#region " Imports "
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using Mono.Cecil;
using Reflector.CodeModel;
using Reflexil.Utils;
using Reflexil.Wrappers;
#endregion

namespace Reflexil.Forms
{
	partial class GenericMemberReferenceForm<T> : IComparer, IReflectionVisitor where T : MemberReference
	{
		
		#region " Constants "
		const string EXPANDER_NODE_KEY = "|-expander-|";
		#endregion
		
		#region " Fields "
        private AssemblyDefinition m_restrictadef;
		private T m_selected;
		private Dictionary<object, TreeNode> m_nodes = new Dictionary<object, TreeNode>();
		private Dictionary<IReflectionVisitable, IReflectionVisitable> m_visiteditems = new Dictionary<IReflectionVisitable, IReflectionVisitable>();
		private Dictionary<Type, int> m_orders = new Dictionary<Type, int>();
		#endregion
		
		#region " Properties "
        public AssemblyDefinition AssemblyRestriction
        {
            get
            {
                return m_restrictadef;
            }
            set
            {
                m_restrictadef = value;
            }
        }

		public MemberReference SelectedItem
		{
			get
			{
				return m_selected;
			}
		}
		#endregion
		
		#region " Events "
		private void TreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e)
		{
			LoadNodeOnDemand(e.Node);
		}
		
		private void TreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			if (e.Node.Tag != null)
			{
				if (typeof(T).IsAssignableFrom(e.Node.Tag.GetType()))
				{
					m_selected = (T) e.Node.Tag;
					ButOk.Enabled = true;
				}
				else
				{
					ButOk.Enabled = false;
				}
			}
			else
			{
				ButOk.Enabled = false;
			}
		}
		
		private void MemberReferenceForm_Load(Object sender, EventArgs e)
		{
			TreeView.Focus();
		}
		#endregion
		
		#region " Methods "
		public GenericMemberReferenceForm(T selected) : base()
		{
			InitializeComponent();

            string keyword = (typeof(T).Name.Contains("Reference")) ? "Reference" : "Definition";
            Text = Text + typeof(T).Name.Replace(keyword, string.Empty).ToLower();
			ImageList.Images.AddStrip(DataManager.GetInstance().GetAllImages());
			
			foreach (IAssembly asm in DataManager.GetInstance().GetReflectorAssemblies())
			{
				AppendRootNode(asm);
			}
			
			m_orders.Add(typeof(AssemblyDefinition), 0);
			m_orders.Add(typeof(TypeDefinition), 1);
			m_orders.Add(typeof(MethodDefinition), 2);
			m_orders.Add(typeof(PropertyDefinition), 3);
			m_orders.Add(typeof(EventDefinition), 3);
			m_orders.Add(typeof(FieldDefinition), 5);
			
			TreeView.TreeViewNodeSorter = this;
			
			ButOk.Enabled = selected != null && SelectItem(selected);
		}
		
		#region " Selection "
		public AssemblyDefinition GetAssemblyDefinitionByNodeName(string name)
		{
			foreach (TreeNode subNode in TreeView.Nodes)
			{
				if (subNode.Text == name)
				{
					if ((subNode.Tag) is IAssembly)
					{
						LoadNodeOnDemand(subNode);
					}
					return ((AssemblyDefinition) subNode.Tag);
				}
			}
			return null;
		}
		
		public string StripGenerics(TypeReference item, string str)
		{
			if ((item) is GenericInstanceType)
			{
				foreach (TypeReference arg in ((GenericInstanceType) item).GenericArguments)
				{
					str = str.Replace(string.Format("<{0}>", arg.FullName), string.Empty);
				}
			}
			return str;
		}
		
		public TypeDefinition GetTypeDefinition(TypeReference item)
		{
			ModuleDefinition moddef = null;
			
			if ((item.Scope) is ModuleDefinition)
			{
				moddef = (ModuleDefinition) item.Scope;
				GetAssemblyDefinitionByNodeName(moddef.Assembly.Name.Name);
			}
			else if ((item.Scope) is AssemblyNameReference)
			{
				AssemblyNameReference anr = (AssemblyNameReference) item.Scope;
				AssemblyDefinition asmdef = GetAssemblyDefinitionByNodeName(anr.Name);
				if (asmdef != null)
				{
					moddef = asmdef.MainModule;
				}
			}
			
			if (moddef != null)
			{
				TypeDefinition typedef = moddef.Types[StripGenerics(item, item.FullName)];
				
				if (typedef != null)
				{
					if (typedef.DeclaringType != null)
					{
						GetTypeDefinition(typedef.DeclaringType);
					}
					LoadNodeOnDemand(m_nodes[moddef]);
					LoadNodeOnDemand(m_nodes[typedef]);
					return typedef;
				}
			}
			
			return null;
		}
		
		public MethodDefinition GetMethodDefinition(MethodReference item)
		{
			TypeDefinition typedef = GetTypeDefinition(item.DeclaringType);
			if (typedef != null)
			{
				ArrayList methods = new ArrayList();
				methods.AddRange(typedef.Constructors);
				methods.AddRange(typedef.Methods);
				foreach (MethodDefinition method in methods)
				{
					if (StripGenerics(typedef, method.ToString()) == StripGenerics(item.DeclaringType, item.ToString()))
					{
						return method;
					}
				}
			}
			return null;
		}
		
		public FieldDefinition GetFieldDefinition(FieldReference item)
		{
			TypeDefinition typedef = GetTypeDefinition(item.DeclaringType);
			if (typedef != null)
			{
				foreach (FieldDefinition field in typedef.Fields)
				{
					if (StripGenerics(typedef, field.ToString()) == StripGenerics(item.DeclaringType, item.ToString()))
					{
						return field;
					}
				}
			}
			return null;
		}
		
		public bool SelectItem(MemberReference item)
		{
			object itemtag = null;
			
			if ((item) is TypeReference)
			{
				itemtag = GetTypeDefinition((TypeReference) item);
			}
			else if ((item) is MethodReference)
			{
				itemtag = GetMethodDefinition((MethodReference) item);
			}
			else if ((item) is FieldReference)
			{
				itemtag = GetFieldDefinition((FieldReference) item);
			}
			
			if (itemtag != null&& m_nodes.ContainsKey(itemtag))
			{
				TreeView.SelectedNode = m_nodes[itemtag];
				m_selected = (T) item;
				return true;
			}
			
			return false;
		}
		#endregion
		
		#region " Cosmetic "
		public int Compare(object x, object y)
		{
			TreeNode xn = (TreeNode) x;
			TreeNode yn = (TreeNode) y;
			
			int result = 0;
			if (xn.Tag != null&& yn.Tag != null)
			{
				if (m_orders.ContainsKey(xn.Tag.GetType()))
				{
					result = m_orders[xn.Tag.GetType()].CompareTo(m_orders[yn.Tag.GetType()]);
				}
			}
			if (result == 0)
			{
				result = xn.Text.CompareTo(yn.Text);
			}
			return result;
		}
		
		private int ScopeOffset(int attributes, int mask, int publicValue, int friendValue, int protectedFriendValue, int protectedValue, int privateValue)
		{
			int[] scopes = new int[] { publicValue, friendValue, protectedFriendValue, protectedValue, privateValue };
			attributes = attributes & mask;
			
			for (int i = 0; i <= scopes.Length - 1; i++)
			{
				if (attributes == scopes[i])
				{
					return i;
				}
			}
			
			return 0;
		}
		
		private EReflectorImages ImageIndex(object obj)
		{
			EReflectorImages offset = EReflectorImages.Empty;
			
			if ((obj) is TypeDefinition)
			{
				TypeDefinition typedef = (TypeDefinition) obj;
				if (typedef.IsEnum)
				{
					offset = EReflectorImages.PublicEnum;
				}
				else if (typedef.IsInterface)
				{
					offset = EReflectorImages.PublicInterface;
				}
				else if (typedef.IsValueType)
				{
					offset = EReflectorImages.PublicStructure;
				}
				else
				{
					offset = EReflectorImages.PublicClass;
				}
				if ((typedef.Attributes & TypeAttributes.VisibilityMask) < TypeAttributes.Public)
				{
                    offset = (EReflectorImages)((int)offset + EReflectorImages.FriendClass - EReflectorImages.PublicClass);
				}
				else
				{
					offset = offset + ScopeOffset(Convert.ToInt32(typedef.Attributes), (int)TypeAttributes.VisibilityMask, (int)TypeAttributes.NestedPublic, (int)TypeAttributes.NestedAssembly, (int)TypeAttributes.NestedFamORAssem, (int)TypeAttributes.NestedFamily, (int)TypeAttributes.NestedPrivate);
				}
			}
			else if ((obj) is PropertyDefinition)
			{
				PropertyDefinition propdef = (PropertyDefinition) obj;
				if (propdef.GetMethod == null)
				{
					if (propdef.SetMethod.IsStatic)
					{
						offset = EReflectorImages.PublicSharedWriteOnlyProperty;
					}
					else
					{
						offset = EReflectorImages.PublicWriteOnlyProperty;
					}
				}
				else if (propdef.SetMethod == null)
				{
					if (propdef.GetMethod.IsStatic)
					{
						offset = EReflectorImages.PublicSharedReadOnlyProperty;
					}
					else
					{
						offset = EReflectorImages.PublicReadOnlyProperty;
					}
				}
				else
				{
					if (propdef.GetMethod.IsStatic)
					{
						offset = EReflectorImages.PublicSharedProperty;
					}
					else
					{
						offset = EReflectorImages.PublicProperty;
					}
				}
			}
			else if ((obj) is MethodDefinition)
			{
				MethodDefinition metdef = (MethodDefinition) obj;
				if (metdef.IsConstructor)
				{
					if (metdef.IsStatic)
					{
						offset = EReflectorImages.PublicSharedConstructor;
					}
					else
					{
						offset = EReflectorImages.PublicConstructor;
					}
				}
				else
				{
					if (metdef.IsVirtual)
					{
						if (metdef.IsStatic)
						{
							offset = EReflectorImages.PublicSharedOverrideMethod;
						}
						else
						{
							offset = EReflectorImages.PublicOverrideMethod;
						}
					}
					else
					{
						if (metdef.IsStatic)
						{
							offset = EReflectorImages.PublicSharedMethod;
						}
						else
						{
							offset = EReflectorImages.PublicMethod;
						}
					}
				}
				offset = offset + ScopeOffset((int)metdef.Attributes, (int)MethodAttributes.MemberAccessMask, (int)MethodAttributes.Public, (int)MethodAttributes.Assem, (int)MethodAttributes.FamORAssem, (int)MethodAttributes.Family, (int)MethodAttributes.Private);
			}
			else if ((obj) is FieldDefinition)
			{
				FieldDefinition field = (FieldDefinition) obj;
				if (field.IsLiteral && field.IsStatic)
				{
					offset = EReflectorImages.PublicEnumValue;
				}
				else
				{
					if (field.IsStatic)
					{
						offset = EReflectorImages.PublicSharedField;
					}
					else
					{
						offset = EReflectorImages.PublicField;
					}
				}
                offset = offset + ScopeOffset((int)field.Attributes, (int)FieldAttributes.FieldAccessMask, (int)FieldAttributes.Public, (int)FieldAttributes.Assembly, (int)FieldAttributes.FamORAssem, (int)FieldAttributes.Family, (int)FieldAttributes.Private);
			}
			else if ((obj) is ModuleDefinition)
			{
				offset = EReflectorImages.Module;
			}
			else if ((obj) is EventDefinition)
			{
				EventDefinition evtdef = (EventDefinition) obj;
				if (evtdef.AddMethod.IsStatic)
				{
					offset = EReflectorImages.PublicSharedEvent;
				}
				else
				{
					offset = EReflectorImages.PublicEvent;
				}
			}
			else if ((obj) is AssemblyDefinition || (obj) is IAssembly)
			{
				offset = EReflectorImages.Assembly;
			}
			else if ((obj) is NamespaceWrapper)
			{
				offset = EReflectorImages.PublicNamespace;
			}
			
			return offset;
		}
		
		public string DisplayString(object obj)
		{
			if ((obj) is MethodDefinition)
			{
				MethodDefinition metdef = (MethodDefinition) obj;
				return metdef.ToString().Substring(metdef.ToString().IndexOf("::") + 2) + " : " + metdef.ReturnType.ReturnType.ToString();
			}
			else if ((obj) is PropertyDefinition)
			{
				PropertyDefinition propdef = (PropertyDefinition) obj;
				return propdef.ToString().Substring(propdef.ToString().IndexOf("::") + 2) + " : " + propdef.PropertyType.ToString();
			}
			else if ((obj) is FieldDefinition)
			{
				FieldDefinition flddef = (FieldDefinition) obj;
				return flddef.ToString().Substring(flddef.ToString().IndexOf("::") + 2) + " : " + flddef.FieldType.ToString();
			}
			else if ((obj) is ModuleDefinition)
			{
				ModuleDefinition moddef = (ModuleDefinition) obj;
				return moddef.Name;
			}
			else if ((obj) is TypeDefinition)
			{
				TypeDefinition typedef = (TypeDefinition) obj;
				return typedef.Name;
			}
			else if ((obj) is AssemblyDefinition)
			{
				AssemblyDefinition asmdef = (AssemblyDefinition) obj;
				return asmdef.Name.Name;
			}
			else if ((obj) is IAssembly)
			{
				IAssembly iasm = (IAssembly) obj;
				return iasm.Name;
			}
			else if ((obj) is EventDefinition)
			{
				EventDefinition evtdef = (EventDefinition) obj;
				return evtdef.Name;
			}
			else
			{
				return obj.ToString();
			}
		}
		#endregion
		
		#region " Node management "
        private void LoadNodeOnDemand(TreeNode node)
        {
            if (node.Nodes.ContainsKey(EXPANDER_NODE_KEY))
            {
                node.Nodes.RemoveAt(node.Nodes.IndexOfKey(EXPANDER_NODE_KEY));
            }
            if ((node.Tag) is IReflectionVisitable)
            {
                IReflectionVisitable visitable = (IReflectionVisitable)node.Tag;
                if (!m_visiteditems.ContainsKey(visitable))
                {
                    visitable.Accept(this);
                    m_visiteditems.Add(visitable, visitable);
                }
            }
            else if ((node.Tag) is IAssembly)
            {
                IAssembly iasm = (IAssembly)node.Tag;

                AssemblyContext context = DataManager.GetInstance().GetAssemblyContext(iasm.Location);
                if (context != null)
                {
                    AssemblyDefinition asmdef = context.AssemblyDefinition;

                    if ((AssemblyRestriction == null) || (asmdef == AssemblyRestriction))
                    {
                        m_nodes.Remove(node.Tag);
                        m_nodes.Add(asmdef, node);
                        node.Tag = asmdef;

                        foreach (ModuleDefinition moddef in asmdef.Modules)
                        {
                            AppendNode(asmdef, moddef, moddef.Types.Count > 0);
                        }
                    }
                    else
                    {
                        node.Tag = "restricted";
                        node.Text += String.Format(" (You can't use this assembly for selection -> restricted to {0})", AssemblyRestriction.Name.Name);
                    }
                }
            }
        }
		
		private void AppendRootNode(IAssembly root)
		{
            // Prevent dumb users from using regular EXE files loaded in reflector
            if (root.Type != AssemblyType.None)
            {
                TreeNode rootnode = new TreeNode(DisplayString(root));
                rootnode.ImageIndex = (int)ImageIndex(root);
                rootnode.SelectedImageIndex = rootnode.ImageIndex;
                rootnode.Tag = root;
                rootnode.Nodes.Add(EXPANDER_NODE_KEY, EXPANDER_NODE_KEY);
                TreeView.Nodes.Add(rootnode);
                m_nodes.Add(root, rootnode);
            }
		}
		
		private void AppendNode(TreeNode ownernode, object child, bool createExpander)
		{
			if (! m_nodes.ContainsKey(child))
			{
				TreeNode childnode = new TreeNode(DisplayString(child));
				childnode.ImageIndex = (int)ImageIndex(child);
				childnode.SelectedImageIndex = childnode.ImageIndex;
				childnode.Tag = child;
				if (createExpander)
				{
					childnode.Nodes.Add(EXPANDER_NODE_KEY, EXPANDER_NODE_KEY);
				}
				ownernode.Nodes.Add(childnode);
				m_nodes.Add(child, childnode);
			}
		}
		
		private void AppendNode(object owner, object child, bool createExpander)
		{
			TreeNode ownernode = m_nodes[owner];
			AppendNode(ownernode, child, createExpander);
		}
		#endregion
		
		#region " Visitor implementation "
		public void VisitConstructorCollection(ConstructorCollection ctors)
		{
			foreach (MethodDefinition constructor in ctors)
			{
				AppendNode(constructor.DeclaringType, constructor, false);
			}
		}
		
		public void VisitEventDefinitionCollection(EventDefinitionCollection events)
		{
			foreach (EventDefinition evt in events)
			{
				AppendNode(evt.DeclaringType, evt, true);
				if (evt.AddMethod != null)
				{
					AppendNode(evt, evt.AddMethod, false);
				}
				if (evt.RemoveMethod != null)
				{
					AppendNode(evt, evt.RemoveMethod, false);
				}
			}
		}
		
		public void VisitFieldDefinitionCollection(FieldDefinitionCollection fields)
		{
			foreach (FieldDefinition field in fields)
			{
				AppendNode(field.DeclaringType, field, false);
			}
		}
		
		public void VisitMethodDefinitionCollection(MethodDefinitionCollection methods)
		{
			foreach (MethodDefinition method in methods)
			{
				if (! method.IsSpecialName || method.IsConstructor)
				{
					AppendNode(method.DeclaringType, method, false);
				}
			}
		}
		
		public void VisitNestedTypeCollection(NestedTypeCollection nestedTypes)
		{
			foreach (TypeDefinition nestedType in nestedTypes)
			{
				AppendNode(nestedType.DeclaringType, nestedType, true);
			}
		}
		
		public void VisitPropertyDefinitionCollection(PropertyDefinitionCollection properties)
		{
			foreach (PropertyDefinition @property in properties)
			{
				AppendNode(@property.DeclaringType, @property, true);
				if (@property.GetMethod != null)
				{
					AppendNode(@property, @property.GetMethod, false);
				}
				if (@property.SetMethod != null)
				{
					AppendNode(@property, @property.SetMethod, false);
				}
			}
		}
		
		public void VisitTypeDefinitionCollection(TypeDefinitionCollection types)
		{
			foreach (TypeDefinition typedef in types)
			{
                if ((typedef.Attributes & TypeAttributes.VisibilityMask) <= TypeAttributes.Public)
				{
                    NamespaceWrapper wrapper = new NamespaceWrapper(typedef.Module, typedef.Namespace);
                    AppendNode(typedef.Module, wrapper, true);
                    AppendNode(wrapper, typedef, true);
				}
			}
		}
		#endregion
		
		#region " Unimplemented vistor "
		public void VisitEventDefinition(EventDefinition evt)
		{
		}
		
		public void VisitFieldDefinition(FieldDefinition field)
		{
		}
		
		public void VisitModuleDefinition(ModuleDefinition @module)
		{
		}
		
		public void VisitNestedType(TypeDefinition nestedType)
		{
		}
		
		public void VisitPropertyDefinition(PropertyDefinition @property)
		{
		}
		
		public void VisitTypeDefinition(TypeDefinition type)
		{
		}
		
		public void VisitConstructor(MethodDefinition ctor)
		{
		}
		
		public void VisitMethodDefinition(MethodDefinition method)
		{
		}
		
		public void TerminateModuleDefinition(ModuleDefinition @module)
		{
		}
		
		public void VisitExternType(TypeReference externType)
		{
		}
		
		public void VisitExternTypeCollection(ExternTypeCollection externs)
		{
		}
		
		public void VisitInterface(TypeReference interf)
		{
		}
		
		public void VisitInterfaceCollection(InterfaceCollection interfaces)
		{
		}
		
		public void VisitMemberReference(MemberReference member)
		{
		}
		
		public void VisitMemberReferenceCollection(MemberReferenceCollection members)
		{
		}
		
		public void VisitCustomAttribute(CustomAttribute customAttr)
		{
		}
		
		public void VisitCustomAttributeCollection(CustomAttributeCollection customAttrs)
		{
		}
		
		public void VisitGenericParameter(GenericParameter genparam)
		{
		}
		
		public void VisitGenericParameterCollection(GenericParameterCollection genparams)
		{
		}
		
		public void VisitMarshalSpec(MarshalSpec marshalSpec)
		{
		}
		
		public void VisitSecurityDeclaration(SecurityDeclaration secDecl)
		{
		}
		
		public void VisitSecurityDeclarationCollection(SecurityDeclarationCollection secDecls)
		{
		}
		
		public void VisitTypeReference(TypeReference type)
		{
		}
		
		public void VisitTypeReferenceCollection(TypeReferenceCollection refs)
		{
		}
		
		public void VisitOverride(MethodReference ov)
		{
		}
		
		public void VisitOverrideCollection(OverrideCollection meth)
		{
		}
		
		public void VisitParameterDefinition(ParameterDefinition parameter)
		{
		}
		
		public void VisitParameterDefinitionCollection(ParameterDefinitionCollection parameters)
		{
		}
		
		public void VisitPInvokeInfo(PInvokeInfo pinvk)
		{
		}
		#endregion
		
		#endregion
		
	}
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer (Senior) Microsoft
United States United States
Sebastien Lebreton is a Software Engineer at Microsoft.

He is particularly interested in optimization, reverse engineering and distributed objects technologies.

Comments and Discussions