Click here to Skip to main content
15,886,199 members
Articles / Desktop Programming / MFC

A .NET assembly viewer

Rate me:
Please Sign up or sign in to vote.
4.88/5 (55 votes)
28 Nov 20028 min read 303.5K   15.8K   166  
An application to examine .NET assemblies both directly and with reflection
/***
 * 
 *  ASMEX by RiskCare Ltd.
 * 
 * This source is copyright (C) 2002 RiskCare Ltd. All rights reserved.
 * 
 * Disclaimer:
 * This code is provided 'as is', with absolutely no warranty expressed or
 * implied.  Any use of this code is at your own risk.
 *   
 * You are hereby granted the right to redistribute this source unmodified
 * in its original archive. 
 * You are hereby granted the right to use this code, or code based on it,
 * provided that you acknowledge RiskCare Ltd somewhere in the documentation
 * of your application. 
 * You are hereby granted the right to distribute changes to this source, 
 * provided that:
 * 
 * 1 -- This copyright notice is retained unchanged 
 * 2 -- Your changes are clearly marked 
 * 
 * Enjoy!
 * 
 * --------------------------------------------------------------------
 * 
 * If you use this code or have comments on it, please mail me at 
 * support@jbrowse.com or ben.peterson@riskcare.com
 * 
 */

using System;
using System.IO;

namespace Asmex.FileViewer
{
	public class ModHeaders
	{
		OSHeaders _hdr;
		MetaDataHeaders _md;
		COR20Header _cor20;
		MetaDataTableHeader _mdth;

		public ModHeaders(BinaryReader reader)
		{
			//read coff, pe, section headers
			_hdr = new OSHeaders(reader);

			//find and read COR20 header
			try
			{
				reader.BaseStream.Position = Rva2Offset(_hdr.PEHeader.DataDirs[14].Rva);
				_cor20 = new COR20Header(reader);
			}
			catch(Exception e)
			{
				return;
			}

			//find and read md headers
			try
			{
				reader.BaseStream.Position = Rva2Offset(_cor20.MetaData.Rva);
				_md = new MetaDataHeaders(reader);
			}
			catch(Exception e)
			{
				return;
			}

			try
			{
				reader.BaseStream.Position = _md.TableStreamHeader.Offset + _md.StorageSigAndHeader.Start;
				_mdth = new MetaDataTableHeader(reader);
			}
			catch(Exception e)
			{
				return;
			}
		}

		public uint Rva2Offset(uint rva)
		{
			for (int i = 0; i < _hdr.SectionHeaders.Length; i++)
			{
				SectionHeader sh = _hdr.SectionHeaders[i];
				if ((sh.VirtualAddress <= rva) && (sh.VirtualAddress + sh.SizeOfRawData > rva))
					return (sh.PointerToRawData + (rva - sh.VirtualAddress));
			}
		
			throw new ModException("Module:  Invalid RVA address.");
		}

		public OSHeaders OSHeaders{get{return _hdr;}}
		public MetaDataHeaders MetaDataHeaders{get{return _md;}}
		public COR20Header COR20Header{get{return _cor20;}}
		public MetaDataTableHeader MetaDataTableHeader{get{return _mdth;}}

	}



	public class MModule
	{
		ModHeaders _mh;
		MDStringHeap _stringHeap;
		MDBlobHeap _blobHeap;
		MDGUIDHeap _GUIDHeap;
		MDBlobHeap _USHeap;
		MDTables _tables;
		ImpExports _imp;
		Relocations _fix;

		public MModule(BinaryReader reader)
		{
			try
			{
				_mh = new ModHeaders(reader);
			}
			catch(Exception e)
			{
				return;
			}

			//imports
			try
			{
				_imp = new ImpExports(reader, this);
			}
			catch(Exception e)
			{
				return;
			}

			//relocs
			try
			{
				_fix = new Relocations(reader, this);
			}
			catch(Exception e)
			{
				return;
			}

			//heaps
			try
			{
				_stringHeap = new MDStringHeap(reader, _mh.MetaDataHeaders.StringStreamHeader.Offset + _mh.MetaDataHeaders.StorageSigAndHeader.Start, _mh.MetaDataHeaders.StringStreamHeader.Size, _mh.MetaDataHeaders.StringStreamHeader.Name);
				_blobHeap = new MDBlobHeap(reader, _mh.MetaDataHeaders.BlobStreamHeader.Offset + _mh.MetaDataHeaders.StorageSigAndHeader.Start, _mh.MetaDataHeaders.BlobStreamHeader.Size, _mh.MetaDataHeaders.BlobStreamHeader.Name);
				_GUIDHeap = new MDGUIDHeap(reader, _mh.MetaDataHeaders.GUIDStreamHeader.Offset + _mh.MetaDataHeaders.StorageSigAndHeader.Start, _mh.MetaDataHeaders.GUIDStreamHeader.Size, _mh.MetaDataHeaders.GUIDStreamHeader.Name);

				if (_mh.MetaDataHeaders.USStreamHeader != null)
					_USHeap = new MDBlobHeap(reader, _mh.MetaDataHeaders.USStreamHeader.Offset + _mh.MetaDataHeaders.StorageSigAndHeader.Start, _mh.MetaDataHeaders.USStreamHeader.Size, _mh.MetaDataHeaders.USStreamHeader.Name);
			}
			catch(Exception e)
			{
				return;
			}

			//tables
			try
			{
				reader.BaseStream.Position = _mh.MetaDataTableHeader.End;
				_tables = new MDTables(reader, this);
			}
			catch(Exception e)
			{
				return;
			}

		}

		public ModHeaders ModHeaders{get{return _mh;}}
		public MDStringHeap StringHeap{get{return _stringHeap;}}
		public MDBlobHeap BlobHeap{get{return _blobHeap;}}
		public MDGUIDHeap GUIDHeap{get{return _GUIDHeap;}}
		public MDBlobHeap USHeap{get{return _USHeap;}}
		public MDTables MDTables{get{return _tables;}}
		public ImpExports ImportExport{get{return _imp;}}
		public Relocations Relocations{get{return _fix;}}

		public static int DecodeInt32(BinaryReader reader)
		{
			int length = reader.ReadByte();
			if ((length & 0x80) == 0) return length;
			if ((length & 0xC0) == 0x80) return ((length & 0x3F) << 8) | reader.ReadByte();
			return ((length & 0x3F) << 24) | (reader.ReadByte() << 16) | (reader.ReadByte() << 8) | reader.ReadByte();
		}

		public string StringFromRVA(BinaryReader reader, uint rva)
		{
			long offs = reader.BaseStream.Position;
			string s;

			try
			{
				s = "";
				uint nameOffs = ModHeaders.Rva2Offset(rva);
				reader.BaseStream.Position = nameOffs;
				byte b = reader.ReadByte();
				while(b != 0)
				{
					s += (char)b;
					b = reader.ReadByte();
				}
			}
			catch(Exception e)
			{
				s = "Unable to find string";
			}
			finally
			{
				reader.BaseStream.Position = offs;
			}
			return s;
		}

	}


	public class ModException : Exception
	{
		public ModException(string ex, Exception e) : base(ex, e) {}
		public ModException(string ex) : base(ex) {}
	}
}

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United Kingdom United Kingdom
My interests are software engineering, Japanese, and talking about how good things used to be back in the good old days.

URL: http://www.jbrowse.com
Favorite Toy: http://www.ruby-lang.org


Comments and Discussions