6. Correlating Metadata Tables
In all the previous chapters that we presented, we had elucidated all the concepts and tables through distinct programs. In this chapter, we have endeavored to inscribe a single program, which encompasses all the tables and displays meaningful output. In lieu of displaying references to various tables, such as typeDef[1], MethodRef[2] etc., we shall display the actual values existent at these locations. Thus, we have essayed to resolve all the cross-references and to display the metadata information in a comprehensive manner.
But, prior to embarking on the explanation of this gargantuan program, which cross-references all the tables, we wish to shed light on a few crucial aspects.
Every table in the metadata world is constituted of fields. Moreover, even a structure is essentially a collection of fields. Therefore, in the C# program, we have represented the metadata tables in a structure.
For instance, we have created an ExportedTypeTable as a structure tag, which contains multiple fields. The structure in essence, is a logical entity, which has no physical existence. Hence, we generate an actual structure by creating a variable of the structure tag named ExportedTypeTableStruct. A structure is a value type, and hence, it does not have to be instantiated.
The variable ExportedTypeTableStruct is declared as an array of structures.
public struct ExportedTypeTable
{
public int flags ;
public int typedefindex ;
public int name ;
public int nspace ;
public int coded ;
}
public ExportedTypeTable [] ExportedTypeStruct;
The program gets underway by creating a structure tag for every table in the metadata. We have proffered the entire program to you, despite being aware of the fact that it would run into reams of pages. Before you get going with the main program, compile b.cs in the c:\mdata subdirectory and generate the file b.exe. The metadata information of this executable will be displayed in the output.
b.cs
using System.Runtime.InteropServices;
using System;
public class zzz
{
static int i;
const int j=2;
public event EventHandler a;
public event EventHandler b;
[DllImport("user32.dll")]
public static extern int MessageBox(int hWnd, String text, String caption, uint type);
public static void Main ()
{
i=10;
Console.WriteLine("hell {0}",i);
}
public int abc(float k)
{
return 0;
}
public long pqr( int[] i , char j)
{
return 0;
}
public void xyz()
{
}
}
public class yyy:iii
{
public int aa
{
set
{
}
get
{
return 10;
}
}
public string bb
{
set
{
}
get
{
return "hi";
}
}
public long uuu( int i , char[] j)
{
return 0;
}
void iii.xxx()
{
Console.WriteLine("hello");
}
public unsafe void aaa()
{
}
}
interface iii
{
void xxx();
}
public class uuu:yyy
{
class a1
{
}
}
a.txt
author=vijay
book=metadata
>resgen a.txt
>csc b.cs /res:a.resources /unsafe
a.cs
using System;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Configuration.Assemblies;
using System.Globalization;
public struct ExportedTypeTable
{
public int flags ;
public int typedefindex ;
public int name ;
public int nspace ;
public int coded ;
}
public struct NestedClassTable
{
public int nestedclass;
public int enclosingclass;
}
public struct MethodImpTable
{
public int classindex;
public int codedbody;
public int codeddef;
}
public struct ClassLayoutTable
{
public short packingsize ;
public int classsize ;
public int parent ;
}
public struct ManifestResourceTable
{
public int offset;
public int flags;
public int name;
public int coded;
}
public struct ModuleRefTable
{
public int name;
}
public struct FileTable
{
public int flags;
public int name;
public int index;
}
public struct EventTable
{
public short attr;
public int name;
public int coded;
}
public struct EventMapTable
{
public int index;
public int eindex;
}
public struct MethodSemanticsTable
{
public short methodsemanticsattributes;
public int methodindex;
public int association;
}
public struct PropertyMapTable
{
public int parent;
public int propertylist;
}
public struct PropertyTable
{
public int flags;
public int name;
public int type;
}
public struct ConstantsTable
{
public short dtype;
public int parent;
public int value ;
}
public struct FieldLayoutTable
{
public int offset;
public int fieldindex;
}
public struct FieldRVATable
{
public int rva ;
public int fieldi;
}
public struct FieldMarshalTable
{
public int coded;
public int index;
}
public struct FieldTable
{
public int flags;
public int name;
public int sig;
}
public struct ParamTable
{
public short pattr;
public int sequence;
public int name;
}
public struct TypeSpecTable
{
public int signature;
}
public struct MemberRefTable
{
public int clas;
public int name;
public int sig;
}
public struct StandAloneSigTable
{
public int index;
}
public struct InterfaceImplTable
{
public int classindex;
public int interfaceindex;
}
public struct TypeDefTable
{
public int flags;
public int name;
public int nspace;
public int cindex;
public int findex;
public int mindex;
}
public struct CustomAttributeTable
{
public int parent;
public int type;
public int value;
}
public struct AssemblyRefTable
{
public short major,minor,build,revision;
public int flags ;
public int publickey ;
public int name ;
public int culture ;
public int hashvalue ;
}
public struct AssemblyTable
{
public int HashAlgId;
public int major, minor,build,revision ;
public int flags ;
public int publickey ;
public int name ;
public int culture ;
}
public struct ModuleTable
{
public int Generation;
public int Name;
public int Mvid;
public int EncId;
public int EncBaseId;
}
public struct TypeRefTable
{
public int resolutionscope;
public int name;
public int nspace;
}
public struct MethodTable
{
public int rva;
public int impflags;
public int flags;
public int name;
public int signature;
public int param;
}
public struct DeclSecurityTable
{
public int action;
public int coded;
public int bindex;
}
public struct ImplMapTable
{
public short attr;
public int cindex;
public int name;
public int scope;
}
public class zzz
{
string [] typerefnames;
string [] typedefnames;
public static void Main (string [] args)
{
zzz a = new zzz();
a.abc(args);
}
public void abc(string [] args)
{
InitializeObjects(args);
ReadPEStructures();
DisplayPEStructures();
ImportAdressTable();
CLRHeader();
ReadStreamsData();
FillTableSizes();
ReadTablesIntoStructures();
DisplayTableForDebugging();
}
public AssemblyTable [] AssemblyStruct;
public AssemblyRefTable [] AssemblyRefStruct ;
public CustomAttributeTable [] CustomAttributeStruct;
public ModuleTable[] ModuleStruct;
public TypeDefTable [] TypeDefStruct;
public TypeRefTable [] TypeRefStruct;
public InterfaceImplTable [] InterfaceImplStruct;
public MethodTable [] MethodStruct;
public StandAloneSigTable [] StandAloneSigStruct;
public MemberRefTable [] MemberRefStruct;
public TypeSpecTable [] TypeSpecStruct;
public ParamTable [] ParamStruct;
public FieldTable [] FieldStruct;
public FieldMarshalTable [] FieldMarshalStruct;
public FieldRVATable [] FieldRVAStruct;
public FieldLayoutTable [] FieldLayoutStruct;
public ConstantsTable [] ConstantsStruct;
public PropertyMapTable [] PropertyMapStruct;
public PropertyTable [] PropertyStruct;
public MethodSemanticsTable [] MethodSemanticsStruct;
public EventTable [] EventStruct;
public EventMapTable [] EventMapStruct;
public FileTable [] FileStruct;
public ModuleRefTable [] ModuleRefStruct;
public ManifestResourceTable [] ManifestResourceStruct;
public ClassLayoutTable [] ClassLayoutStruct;
public MethodImpTable [] MethodImpStruct;
public NestedClassTable [] NestedClassStruct;
public ExportedTypeTable [] ExportedTypeStruct;
public DeclSecurityTable [] DeclSecurityStruct;
public ImplMapTable [] ImplMapStruct;
int [] sizes;
FileStream s ;
BinaryReader r ;
int subsystem;
int stackreserve ;
int stackcommit;
int datad;
int entrypoint;
int ImageBase;
int sectiona;
int filea;
int [] datadirectoryrva;
int [] datadirectorysize;
long sectionoffset;
short sections ;
int metadatarva;
int entrypointtoken;
int [] SVirtualAddress ;
int [] SSizeOfRawData;
int [] SPointerToRawData ;
long startofmetadata;
string [] streamnames;
int tableoffset ;
int [] rows;
long valid ;
byte [] metadata;
byte [] strings;
byte [] us;
byte [] guid;
byte [] blob;
int [] offset;
int [] ssize ;
byte [][] names;
int offsetstring = 2;
int offsetblob = 2;
int offsetguid = 2;
int vtablerva;
int vtablesize;
int exportaddressrva;
int exportaddresssize;
int corflags;
string [] tablenames;
string filename;
public void InitializeObjects(string [] args)
{
tablenames = new String[]{"Module" , "TypeRef" , "TypeDef" ,"FieldPtr","Field", "MethodPtr","Method","ParamPtr" , "Param", "InterfaceImpl", "MemberRef", "Constant", "CustomAttribute", "FieldMarshal", "DeclSecurity", "ClassLayout", "FieldLayout", "StandAloneSig" , "EventMap","EventPtr", "Event", "PropertyMap", "PropertyPtr", "Properties","MethodSemantics","MethodImpl","ModuleRef","TypeSpec","Imp
lMap","FieldRVA","ENCLog","ENCMap","Assembly",
"AssemblyProcessor","AssemblyOS","AssemblyRef","AssemblyRefProcessor",
"AssemblyRefOS","File","ExportedType","ManifestResource",
"NestedClass","TypeTyPar","MethodTyPar"};
if ( args.Length == 0)
filename = "C:\\mdata\\b.exe";
else
filename = args[0];
}
public void ReadPEStructures()
{
s = new FileStream(filename ,FileMode.Open);
r = new BinaryReader (s);
s.Seek(60, SeekOrigin.Begin);
int ii = r.ReadInt32();
s.Seek(ii, SeekOrigin.Begin);
byte sig1,sig2,sig3,sig4;
sig1 = r.ReadByte();
sig2 = r.ReadByte();
sig3 = r.ReadByte();
sig4 = r.ReadByte();
//First Structure
short machine = r.ReadInt16();
sections = r.ReadInt16();
int time = r.ReadInt32();
int pointer = r.ReadInt32();
int symbols = r.ReadInt32();
int headersize= r.ReadInt16();
int characteristics = r.ReadInt16();
sectionoffset = s.Position + headersize;
//Second Structure
int magic = r.ReadInt16();
int major = r.ReadByte();
int minor = r.ReadByte();
int sizeofcode = r.ReadInt32();
int sizeofdata = r.ReadInt32();
int sizeofudata = r.ReadInt32();
entrypoint = r.ReadInt32();
int baseofcode = r.ReadInt32();
int baseofdata = r.ReadInt32();
ImageBase = r.ReadInt32();
sectiona= r.ReadInt32();
filea = r.ReadInt32();
int majoros = r.ReadInt16();
int minoros = r.ReadInt16();
int majorimage = r.ReadInt16();
int minorimage = r.ReadInt16();
int majorsubsystem= r.ReadInt16();
int minorsubsystem = r.ReadInt16();
int verison = r.ReadInt32();
int imagesize = r.ReadInt32();
int sizeofheaders= r.ReadInt32();
int checksum = r.ReadInt32();
subsystem = r.ReadInt16();
int dllflags = r.ReadInt16();
stackreserve = r.ReadInt32();
stackcommit = r.ReadInt32();
int heapreserve = r.ReadInt32();
int heapcommit = r.ReadInt32();
int loader = r.ReadInt32();
datad = r.ReadInt32();
datadirectoryrva = new int[16];
datadirectorysize = new int[16];
for ( int i = 0 ; i <=15 ; i++)
{
datadirectoryrva[i] = r.ReadInt32();
datadirectorysize[i] = r.ReadInt32();
}
if ( datadirectorysize[14] == 0)
throw new System.Exception("Not a valid CLR file");
s.Position = sectionoffset ;
SVirtualAddress = new int[sections ];
SSizeOfRawData = new int[sections ];
SPointerToRawData = new int[sections ];
for ( int i = 0 ; i < sections ; i++)
{
r.ReadBytes(12);
SVirtualAddress[i] = r.ReadInt32();
SSizeOfRawData[i] = r.ReadInt32();
SPointerToRawData[i] = r.ReadInt32();
r.ReadBytes(16);
}
}
public void DisplayPEStructures()
{
Console.WriteLine();
Console.WriteLine("// Microsoft (R) .NET Framework IL Disassembler. Version 1.0.3705.0");
Console.WriteLine("// Copyright (C) Microsoft Corporation 1998-2001. All rights reserved.");
Console.WriteLine();
Console.WriteLine("// PE Header:");
Console.WriteLine("// Subsystem: {0}",subsystem.ToString("x8"));
Console.WriteLine("// Native entry point address: {0}",entrypoint.ToString("x8"));
Console.WriteLine("// Image base: {0}",ImageBase.ToString("x8"));
Console.WriteLine("// Section alignment: {0}",sectiona.ToString("x8"));
Console.WriteLine("// File alignment: {0}",filea.ToString("x8"));
Console.WriteLine("// Stack reserve size: {0}",stackreserve.ToString("x8"));
Console.WriteLine("// Stack commit size: {0}",stackcommit.ToString("x8"));
Console.WriteLine("// Directories: {0}",datad.ToString("x8"));
DisplayDataDirectory(datadirectoryrva[0] , datadirectorysize[0] , "Export Directory");
DisplayDataDirectory(datadirectoryrva[1] , datadirectorysize[1] , "Import Directory");
DisplayDataDirectory(datadirectoryrva[2] , datadirectorysize[2] , "Resource Directory");
DisplayDataDirectory(datadirectoryrva[3] , datadirectorysize[3] , "Exception Directory");
DisplayDataDirectory(datadirectoryrva[4] , datadirectorysize[4] , "Security Directory");
DisplayDataDirectory(datadirectoryrva[5] , datadirectorysize[5] , "Base Relocation Table");
DisplayDataDirectory(datadirectoryrva[6] , datadirectorysize[6] , "Debug Directory");
DisplayDataDirectory(datadirectoryrva[7] , datadirectorysize[7] , "Architecture Specific");
DisplayDataDirectory(datadirectoryrva[8] , datadirectorysize[8] , "Global Pointer");
DisplayDataDirectory(datadirectoryrva[9] , datadirectorysize[9] , "TLS Directory");
DisplayDataDirectory(datadirectoryrva[10] , datadirectorysize[10] , "Load Config Directory");
DisplayDataDirectory(datadirectoryrva[11] , datadirectorysize[11] , "Bound Import Directory");
DisplayDataDirectory(datadirectoryrva[12] , datadirectorysize[12] , "Import Address Table");
DisplayDataDirectory(datadirectoryrva[13] , datadirectorysize[13] , "Delay Load IAT");
DisplayDataDirectory(datadirectoryrva[14] , datadirectorysize[14] , "CLR Header");
Console.WriteLine();
}
public void DisplayDataDirectory(int rva, int size , string ss)
{
string sfinal = "";
sfinal = String.Format("// {0:x}" , rva);
sfinal = sfinal.PadRight(12);
sfinal = sfinal + String.Format("[{0:x}" , size);
sfinal = sfinal.PadRight(21);
sfinal = sfinal + String.Format("] address [size] of {0}:" , ss);
if (ss == "CLR Header")
sfinal = sfinal.PadRight(67);
else
sfinal = sfinal.PadRight(68);
Console.WriteLine(sfinal);
}
public void ImportAdressTable()
{
long stratofimports = ConvertRVA(datadirectoryrva[1]);
s.Position = stratofimports;
Console.WriteLine("// Import Address Table");
int j = 0;
while (true)
{
int rvaimportlookuptable = r.ReadInt32();
if ( rvaimportlookuptable == 0)
break;
int datetimestamp = r.ReadInt32();
int forwarderchain = r.ReadInt32();
int name = r.ReadInt32();
int rvaiat = r.ReadInt32();
s.Position = ConvertRVA(name);
Console.Write("// ");
DisplayStringFromFile();
Console.WriteLine("// {0} Import Address Table" , rvaiat.ToString("x8"));
Console.WriteLine("// {0} Import Name Table" , name.ToString("x8"));
Console.WriteLine("// {0} time date stamp" , datetimestamp);
Console.WriteLine("// {0} Index of first forwarder reference" , forwarderchain);
Console.WriteLine("//");
int jj = 0;
while ( true )
{
long pos = ConvertRVA(rvaimportlookuptable ) ;
if ( pos == -1)
break;
s.Position = pos + jj * 4;
int pos1 = r.ReadInt32();
if ( pos1 == 0)
break;
pos = ConvertRVA(rvaimportlookuptable ) ;
if ( pos == -1)
break;
s.Position = pos;
short hint = r.ReadInt16();
Console.Write("// ");
if ( hint.ToString("X").Length == 1)
Console.Write(" {0}" , hint.ToString("x"));
if ( hint.ToString("X").Length == 2)
Console.Write(" {0}" , hint.ToString("x"));
if ( hint.ToString("X").Length == 3)
Console.Write("{0}" , hint.ToString("x"));
Console.Write(" ");
DisplayStringFromFile();
jj++;
}
Console.WriteLine();
j++;
s.Position = stratofimports + j * 20;
}
Console.WriteLine("// Delay Load Import Address Table");
if (datadirectoryrva[13] == 0)
Console.WriteLine("// No data.");
}
public void DisplayStringFromFile()
{
while ( true )
{
byte b = (byte )s.ReadByte();
if ( b == 0)
break;
Console.Write("{0}" , (char)b);
}
Console.WriteLine();
}
public void FillTableSizes()
{
int modulesize = 2 + offsetstring + offsetguid + offsetguid + offsetguid ;
int typerefsize = GetCodedIndexSize("ResolutionScope") + offsetstring + offsetstring ;
int typedefsize = 4 + offsetstring + offsetstring + GetCodedIndexSize("TypeDefOrRef") + GetTableSize() + GetTableSize();
int fieldsize = 2 + offsetstring + offsetblob ;
int methodsize = 4 + 2 + 2 + offsetstring + offsetblob + GetTableSize();
int paramsize = 2 + 2 + offsetstring;
int interfaceimplsize = GetTableSize() + GetCodedIndexSize("TypeDefOrRef");
int memberrefsize = GetCodedIndexSize("MemberRefParent") + offsetstring + offsetblob ;
int constantsize = 2 + GetCodedIndexSize("HasConst") + offsetblob;
int customattributesize = GetCodedIndexSize("HasCustomAttribute") + GetCodedIndexSize("HasCustomAttributeType") + offsetblob;
int fieldmarshallsize = GetCodedIndexSize("HasFieldMarshal") + offsetblob;
int declsecuritysize = 2 + GetCodedIndexSize("HasDeclSecurity") + offsetblob;
int classlayoutsize = 2 + 4 + GetTableSize();
int fieldlayoutsize = 4 + GetTableSize();
int stanalonssigsize = offsetblob;
int eventmapsize = GetTableSize() + GetTableSize();
int eventsize = 2 + offsetstring + GetCodedIndexSize("TypeDefOrRef");
int propertymapsize = GetTableSize() + GetTableSize() ;
int propertysize = 2 + offsetstring + offsetblob;
int methodsemantics = 2 + GetTableSize() + GetCodedIndexSize("HasSemantics");
int methodimplsize = GetTableSize() + GetCodedIndexSize("MethodDefOrRef") + GetCodedIndexSize("MethodDefOrRef");
int modulerefsize = offsetstring;
int typespecsize = offsetblob;
int implmapsize = 2 + GetCodedIndexSize("MemberForwarded") + offsetstring + GetTableSize();
int fieldrvasize = 4 + GetTableSize();
int assemblysize = 4 + 2 + 2 + 2 + 2 + 4 + offsetblob + offsetstring + offsetstring ;
int assemblyrefsize = 2 + 2 + 2 + 2 + 4 + offsetblob + offsetstring + offsetstring + offsetblob;
int filesize = 4 + offsetstring + offsetblob;
int exportedtype = 4 + 4 + offsetstring + offsetstring + GetCodedIndexSize("Implementation");
int manifestresourcesize = 4 + 4 + offsetstring + GetCodedIndexSize("Implementation");
int nestedclasssize = GetTableSize() + GetTableSize() ;
sizes = new int[]{ modulesize, typerefsize , typedefsize ,2, fieldsize ,2,methodsize ,2,paramsize ,interfaceimplsize,memberrefsize ,constantsize ,customattributesize ,fieldmarshallsize ,declsecuritysize ,classlayoutsize ,fieldlayoutsize,stanalonssigsize ,eventmapsize ,2,eventsize ,propertymapsize ,2,propertysize ,methodsemantics ,methodimplsize ,modulerefsize ,typespecsize ,implmapsize ,fieldrvasize ,2 , 2 , assemblysize ,4,12,assemblyrefsize ,6,14,filesize ,exportedtype ,manifestresourcesize ,nestedclasssize };
}
public int GetCodedIndexSize(string i)
{
if ( i == "Implementation")
{
if ( rows[0x26] >= 16384 || rows[0x23] >= 16384 || rows[0x27] >= 16384 )
return 4;
else
return 2;
}
else if ( i == "MemberForwarded")
{
if ( rows[0x04] >= 32768 || rows[0x06] >= 32768)
return 4;
else
return 2;
}
else if ( i == "MethodDefOrRef")
{
if ( rows[0x06] >= 32768 || rows[0x0A] >= 32768)
return 4;
else
return 2;
}
else if ( i == "HasSemantics")
{
if ( rows[0x14] >= 32768 || rows[0x17] >= 32768)
return 4;
else
return 2;
}
else if ( i == "HasDeclSecurity")
{
if ( rows[0x02] >= 16384 || rows[0x06] >= 16384 || rows[0x20] >= 16384)
return 4;
else
return 2;
}
else if ( i == "HasFieldMarshal")
{
if ( rows[0x04] >= 32768|| rows[0x08] >= 32768)
return 4;
else
return 2;
}
else if ( i == "TypeDefOrRef")
{
if ( rows[0x02] >= 16384 || rows[0x01] >= 16384 || rows[0x1B] >= 16384 )
return 4;
else
return 2;
}
else if ( i == "ResolutionScope")
{
if ( rows[0x00] >= 8192 || rows[0x1a] >= 8192 || rows[0x23] >= 8192 || rows[0x01] >= 8192 )
return 4;
else
return 2;
}
else if ( i == "HasConst")
{
if ( rows[4] >= 16384 || rows[8] >= 16384 || rows[0x17] >= 16384 )
return 4;
else
return 2;
}
else if ( i == "MemberRefParent")
{
if ( rows[0x01] >= 8192 || rows[0x1a] >= 8192 || rows[0x06] >= 8192 || rows[0x1b] >= 8192 )
return 4;
else
return 2;
}
else if ( i == "HasCustomAttribute")
{
if ( rows[0x06] >= 2048 || rows[0x04] >= 2048 || rows[0x01] >= 2048 || rows[0x02] >= 2048 || rows[0x08] >= 2048 || rows[0x09] >= 2048 || rows[0x0a] >= 2048 || rows[0x00] >= 2048 || rows[0x0e] >= 2048 || rows[0x17] >= 2048 || rows[0x14] >= 2048 || rows[0x11] >= 2048 || rows[0x1a] >= 2048 || rows[0x1b] >= 2048 || rows[0x20] >= 2048 || rows[0x23] >= 2048 || rows[0x26] >= 2048 || rows[0x27] >= 2048 || rows[0x28] >= 2048 )
return 4;
else
return 2;
}
else if ( i == "HasCustomAttributeType")
{
if ( rows[0x06] >= 8192 || rows[0x0a] >= 8192)
return 4;
else
return 2;
}
else
return 2;
}
public int ReadCodedIndex(byte [] a , int o , string i)
{
int z = 0;
int z1 = GetCodedIndexSize(i);
if ( z1 == 2)
z = BitConverter.ToUInt16 (a , o );
if ( z1 == 4)
z = (int)BitConverter.ToUInt32 (a , o );
return z;
}
public bool tablepresent(byte i)
{
int p = (int)(valid >> i) & 1;
for ( int j = 0 ; j < i ; j++)
{
int o = sizes[j] * rows[j];
tableoffset = tableoffset + o;
}
if ( p == 1)
return true;
else
return false;
}
public void ReadTablesIntoStructures()
{
//Module
int old = tableoffset;
bool b = tablepresent(0);
int offs = tableoffset;
Console.WriteLine("\n Table Details \n\n");
Console.WriteLine("Module Table Offset {0} Size {1}" , offs , sizes[0]);
tableoffset = old;
if ( b )
{
ModuleStruct = new ModuleTable[rows[0] + 1];
for ( int k = 1 ; k <= rows[0] ; k++)
{
ModuleStruct[k].Generation = BitConverter.ToUInt16 (metadata, offs);
offs += 2;
ModuleStruct[k].Name = ReadStringIndex(metadata, offs);
offs += offsetstring;
ModuleStruct[k].Mvid = ReadGuidIndex(metadata, offs);
offs += offsetguid;
ModuleStruct[k].EncId = ReadGuidIndex(metadata, offs);
offs += offsetguid;
ModuleStruct[k].EncBaseId = ReadGuidIndex(metadata, offs);
offs += offsetguid;
}
}
//TypeRef
old = tableoffset;
b = tablepresent(1);
offs = tableoffset;
Console.WriteLine("TypeRef Table Offset {0} Size {1}" , offs , sizes[1]);
tableoffset = old;
if ( b )
{
typerefnames = new string[rows[1]+1];
TypeRefStruct = new TypeRefTable[rows[1] + 1];
for ( int k = 1 ; k <=rows[1] ; k++)
{
TypeRefStruct[k].resolutionscope = ReadCodedIndex(metadata , offs , "ResolutionScope");
offs = offs + GetCodedIndexSize("ResolutionScope");
TypeRefStruct[k].name = ReadStringIndex(metadata , offs);
typerefnames[k] = GetString(TypeRefStruct[k].name);
offs = offs + offsetstring;
TypeRefStruct[k].nspace = ReadStringIndex(metadata , offs);
offs = offs + offsetstring;
}
}
//TypeDef
old = tableoffset;
b = tablepresent(2);
offs = tableoffset;
Console.WriteLine("TypeDef Table Offset {0} Size {1}" , offs , sizes[2]);
tableoffset = old;
if ( b )
{
typedefnames = new string[rows[2]+1];
TypeDefStruct = new TypeDefTable[rows[2] + 1];
for ( int k = 1 ; k <= rows[2] ; k++)
{
TypeDefStruct[k].flags = BitConverter.ToInt32 (metadata, offs);
offs += 4;
TypeDefStruct[k].name = ReadStringIndex(metadata, offs);
typedefnames[k] = GetString(TypeDefStruct[k].name);
offs += offsetstring;
TypeDefStruct[k].nspace = ReadStringIndex(metadata, offs);
offs += offsetstring;
TypeDefStruct[k].cindex = ReadCodedIndex(metadata , offs , "TypeDefOrRef");
offs += GetCodedIndexSize("TypeDefOrRef");
TypeDefStruct[k].findex = ReadTableIndex(metadata, offs);
offs += GetTableSize();
TypeDefStruct[k].mindex = ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
//Field
old = tableoffset;
b = tablepresent(4);
offs = tableoffset;
Console.WriteLine("Field Table Offset {0} Size {1}" , offs , sizes[4]);
tableoffset = old;
if ( b )
{
FieldStruct = new FieldTable[rows[4] + 1];
for ( int k = 1 ; k <= rows[4] ; k++)
{
FieldStruct[k].flags = BitConverter.ToInt16 (metadata, offs);
offs += 2;
FieldStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
FieldStruct[k].sig = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//Method
old = tableoffset;
b = tablepresent(6);
offs = tableoffset;
Console.WriteLine("Method Table Offset {0} Size {1}" , offs , sizes[6]);
tableoffset = old;
if ( b )
{
MethodStruct = new MethodTable[rows[6] + 1];
for ( int k = 1 ; k <= rows[6] ; k++)
{
MethodStruct[k].rva = BitConverter.ToInt32 (metadata, offs);
offs += 4;
MethodStruct[k].impflags = BitConverter.ToInt16 (metadata, offs);
offs += 2;
MethodStruct[k].flags = (int)BitConverter.ToInt16 (metadata, offs);
offs += 2;
MethodStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
MethodStruct[k].signature = ReadBlobIndex(metadata, offs);
offs += offsetblob;
MethodStruct[k].param = ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
//Param
old = tableoffset;
b = tablepresent(8);
offs = tableoffset;
Console.WriteLine("Param Table Offset {0} Size {1}" , offs , sizes[8]);
tableoffset = old;
if ( b )
{
ParamStruct = new ParamTable[rows[8] + 1];
for ( int k = 1 ; k <= rows[8] ; k++)
{
ParamStruct[k].pattr = BitConverter.ToInt16 (metadata, offs);
offs += 2;
ParamStruct[k].sequence = BitConverter.ToInt16 (metadata, offs);
offs += 2;
ParamStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
}
}
//InterfaceImpl
old = tableoffset;
b = tablepresent(9);
offs = tableoffset;
Console.WriteLine("InterfaceImpl Table Offset {0} Size {1}" , offs , sizes[9]);
tableoffset = old;
if ( b )
{
InterfaceImplStruct = new InterfaceImplTable[rows[9] + 1];
for ( int k = 1 ; k <= rows[9] ; k++)
{
InterfaceImplStruct[k].classindex = ReadCodedIndex(metadata , offs , "TypeDefOrRef");
offs += GetCodedIndexSize("TypeDefOrRef");
InterfaceImplStruct[k].interfaceindex = ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
//MemberRef
old = tableoffset;
b = tablepresent(10);
offs = tableoffset;
Console.WriteLine("MemberRef Table Offset {0} Size {1}" , offs, sizes[10]);
tableoffset = old;
if ( b )
{
MemberRefStruct = new MemberRefTable[rows[10] + 1];
for ( int k = 1 ; k <= rows[10] ; k++)
{
MemberRefStruct[k].clas = ReadCodedIndex(metadata , offs , "MemberRefParent");
offs += GetCodedIndexSize("MemberRefParent");
MemberRefStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
MemberRefStruct[k].sig = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//Constants
old = tableoffset;
b = tablepresent(11);
offs = tableoffset;
Console.WriteLine("Constant Table Offset {0} Size {1}" , offs, sizes[11]);
tableoffset = old;
if ( b )
{
ConstantsStruct = new ConstantsTable[rows[11] + 1];
for ( int k = 1 ; k <= rows[11] ; k++)
{
ConstantsStruct[k].dtype = metadata[offs];
offs += 2;
ConstantsStruct[k].parent = ReadCodedIndex(metadata , offs , "HasConst");
offs += GetCodedIndexSize("HasConst");
ConstantsStruct[k].value = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//CustomAttribute
old = tableoffset;
b = tablepresent(12);
offs = tableoffset;
Console.WriteLine("CustomAttribute Table Offset {0} Size {1}" , offs , sizes[12]);
tableoffset = old;
if ( b )
{
CustomAttributeStruct = new CustomAttributeTable[rows[12] + 1];
for ( int k = 1 ; k <= rows[12] ; k++)
{
CustomAttributeStruct[k].parent = ReadCodedIndex(metadata , offs , "HasCustomAttribute");
offs += GetCodedIndexSize("HasCustomAttribute");
CustomAttributeStruct[k].type = ReadCodedIndex(metadata , offs , "HasCustomAttributeType");
offs += GetCodedIndexSize("HasCustomAttributeType");
CustomAttributeStruct[k].value = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//FieldMarshal
old = tableoffset;
b = tablepresent(13);
offs = tableoffset;
Console.WriteLine("FieldMarshal Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
FieldMarshalStruct = new FieldMarshalTable[rows[13] + 1];
for ( int k = 1 ; k <= rows[13] ; k++)
{
FieldMarshalStruct[k].coded = ReadCodedIndex(metadata , offs , "HasFieldMarshal");
offs += GetCodedIndexSize("HasFieldMarshal");
FieldMarshalStruct[k].index = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//DeclSecurity
old = tableoffset;
b = tablepresent(14);
offs = tableoffset;
Console.WriteLine("DeclSecurity Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
DeclSecurityStruct = new DeclSecurityTable[rows[14] + 1];
for ( int k = 1 ; k <= rows[14] ; k++)
{
DeclSecurityStruct[k].action = BitConverter.ToInt16 (metadata, offs);
offs += 2;
DeclSecurityStruct[k].coded = ReadCodedIndex(metadata , offs , "HasDeclSecurity");
offs += GetCodedIndexSize("HasDeclSecurity");
DeclSecurityStruct[k].bindex = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//ClassLayout
old = tableoffset;
b = tablepresent(15);
offs = tableoffset;
Console.WriteLine("ClassLayout Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
ClassLayoutStruct = new ClassLayoutTable[rows[15] + 1];
for ( int k = 1 ; k <= rows[15] ; k++)
{
ClassLayoutStruct[k].packingsize = BitConverter.ToInt16 (metadata, offs);
offs += 2;
ClassLayoutStruct[k].classsize = BitConverter.ToInt32 (metadata, offs);
offs += 4;
ClassLayoutStruct[k].parent = ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
//FieldLayout
old = tableoffset;
b = tablepresent(16);
offs = tableoffset;
Console.WriteLine("FieldLayout Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
FieldLayoutStruct = new FieldLayoutTable[rows[16] + 1];
for ( int k = 1 ; k <= rows[16] ; k++)
{
FieldLayoutStruct[k].offset = BitConverter.ToInt32 (metadata, offs);
offs += 4;
FieldLayoutStruct[k].fieldindex = ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
//StandAloneSig
old = tableoffset;
b = tablepresent(17);
offs = tableoffset;
Console.WriteLine("StandAloneSig Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
StandAloneSigStruct = new StandAloneSigTable[rows[17] + 1];
for ( int k = 1 ; k <= rows[17] ; k++)
{
StandAloneSigStruct[k].index = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//EventMap
old = tableoffset ;
b = tablepresent(18);
offs = tableoffset;
Console.WriteLine("EventMap Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
EventMapStruct = new EventMapTable [rows[18] + 1];
for ( int k = 1 ; k <= rows[18] ; k++)
{
EventMapStruct[k].index = ReadTableIndex(metadata, offs);
offs += GetTableSize();
EventMapStruct[k].eindex = ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
//Event
old = tableoffset;
b = tablepresent(20);
offs = tableoffset;
Console.WriteLine("Event Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
EventStruct = new EventTable[rows[20] + 1];
for ( int k = 1 ; k <= rows[20] ; k++)
{
EventStruct[k].attr = BitConverter.ToInt16 (metadata, offs);
offs += 2;
EventStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
EventStruct[k].coded = ReadCodedIndex(metadata , offs , "TypeDefOrRef");
offs += GetCodedIndexSize("TypeDefOrRef");
}
}
//PropertyMap
old = tableoffset;
b = tablepresent(21);
offs = tableoffset;
Console.WriteLine("PropertyMap Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
PropertyMapStruct = new PropertyMapTable[rows[21] + 1];
for ( int k = 1 ; k <= rows[21] ; k++)
{
PropertyMapStruct[k].parent = ReadTableIndex(metadata, offs);
offs += GetTableSize();
PropertyMapStruct[k].propertylist = ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
//Property
old = tableoffset;
b = tablepresent(23);
offs = tableoffset;
Console.WriteLine("Property Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
PropertyStruct = new PropertyTable[rows[23] + 1];
for ( int k = 1 ; k <= rows[23] ; k++)
{
PropertyStruct[k].flags = BitConverter.ToInt16 (metadata, offs);
offs += 2;
PropertyStruct[k].name= ReadStringIndex(metadata, offs);
offs += offsetstring;
PropertyStruct[k].type = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//MethodSemantics
old = tableoffset ;
b = tablepresent(24);
offs = tableoffset;
Console.WriteLine("MethodSemantics Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
MethodSemanticsStruct = new MethodSemanticsTable[rows[24] + 1];
for ( int k = 1 ; k <= rows[24] ; k++)
{
MethodSemanticsStruct[k].methodsemanticsattributes = BitConverter.ToInt16 (metadata, offs);
offs += 2;
MethodSemanticsStruct[k].methodindex = ReadTableIndex(metadata, offs);
offs += GetTableSize();
MethodSemanticsStruct[k].association = ReadCodedIndex(metadata , offs , "HasSemantics");
offs += GetCodedIndexSize("HasSemantics");
}
}
//MethodImpl
old = tableoffset;
b = tablepresent(25);
offs = tableoffset;
Console.WriteLine("MethodImpl Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
MethodImpStruct = new MethodImpTable[rows[25] + 1];
for ( int k = 1 ; k <= rows[25] ; k++)
{
MethodImpStruct[k].classindex = ReadTableIndex(metadata, offs);
offs += GetTableSize();
MethodImpStruct[k].codedbody = ReadCodedIndex(metadata , offs , "MethodDefOrRef");
offs += GetCodedIndexSize("MethodDefOrRef");
MethodImpStruct[k].codeddef = ReadCodedIndex(metadata , offs , "MethodDefOrRef");
offs += GetCodedIndexSize("MethodDefOrRef");
}
}
//ModuleRef
old = tableoffset;
b = tablepresent(26);
offs = tableoffset;
Console.WriteLine("ModuleRef Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
ModuleRefStruct = new ModuleRefTable[rows[26] + 1];
for ( int k = 1 ; k <= rows[26] ; k++)
{
ModuleRefStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
}
}
//TypeSpec
old = tableoffset;
b = tablepresent(27);
offs = tableoffset;
Console.WriteLine("TypeSpec Table Offset {0} size={1}" , offs , rows[27]);
tableoffset = old;
if ( b )
{
TypeSpecStruct = new TypeSpecTable[rows[27] + 1];
for ( int k = 1 ; k <= rows[27] ; k++)
{
TypeSpecStruct[k].signature = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//ImplMap
old = tableoffset;
b = tablepresent(28);
offs = tableoffset;
Console.WriteLine("ImplMap Table Offset offs={0} rows={1} len={2}" , offs , rows[28] , metadata.Length);
tableoffset = old;
if ( b )
{
ImplMapStruct = new ImplMapTable[rows[28] + 1];
for ( int k = 1 ; k <= rows[28] ; k++)
{
ImplMapStruct[k].attr = BitConverter.ToInt16 (metadata, offs);
offs += 2;
ImplMapStruct[k].cindex = ReadCodedIndex(metadata , offs , "MemberForwarded");
offs += GetCodedIndexSize("MemberForwarded");
ImplMapStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
ImplMapStruct[k].scope = ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
//FieldRVA
old = tableoffset;
b = tablepresent(29);
offs = tableoffset;
Console.WriteLine("FieldRVA Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
FieldRVAStruct = new FieldRVATable[rows[29] + 1];
for ( int k = 1 ; k <= rows[29] ; k++)
{
FieldRVAStruct[k].rva = BitConverter.ToInt32 (metadata, offs);
offs += 4;
FieldRVAStruct[k].fieldi = ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
//Assembly
old = tableoffset;
b = tablepresent(32);
offs = tableoffset;
Console.WriteLine("Assembly Table Offset {0}" , offs);
tableoffset = old;
AssemblyStruct = new AssemblyTable[rows[32] + 1];
if ( b )
{
for ( int k = 1 ; k <= rows[32] ; k++)
{
AssemblyStruct[k].HashAlgId = BitConverter.ToInt32 (metadata, offs);
offs += 4;
AssemblyStruct[k].major = BitConverter.ToInt16 (metadata, offs);
offs += 2;
AssemblyStruct[k].minor = BitConverter.ToInt16 (metadata, offs);
offs += 2;
AssemblyStruct[k].build= BitConverter.ToInt16 (metadata, offs);
offs += 2;
AssemblyStruct[k].revision = BitConverter.ToInt16 (metadata, offs);
offs += 2;
AssemblyStruct[k].flags = BitConverter.ToInt32 (metadata, offs);
offs += 4;
AssemblyStruct[k].publickey = ReadBlobIndex(metadata, offs);
offs += offsetblob;
AssemblyStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
AssemblyStruct[k].culture = ReadStringIndex(metadata, offs);
offs += offsetstring;
}
}
//AssemblyRef
old = tableoffset;
b = tablepresent(35);
offs = tableoffset;
Console.WriteLine("AssembleyRef Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
AssemblyRefStruct = new AssemblyRefTable[rows[35] + 1];
for ( int k = 1 ; k <= rows[35]; k++)
{
AssemblyRefStruct[k].major = BitConverter.ToInt16 (metadata, offs);
offs += 2;
AssemblyRefStruct[k].minor = BitConverter.ToInt16 (metadata, offs);
offs += 2;
AssemblyRefStruct[k].build= BitConverter.ToInt16 (metadata, offs);
offs += 2;
AssemblyRefStruct[k].revision = BitConverter.ToInt16 (metadata, offs);
offs += 2;
AssemblyRefStruct[k].flags = BitConverter.ToInt32 (metadata, offs);
offs += 4;
AssemblyRefStruct[k].publickey = ReadBlobIndex(metadata, offs);
offs += offsetblob;
AssemblyRefStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
AssemblyRefStruct[k].culture = ReadStringIndex(metadata, offs);
offs += offsetstring;
AssemblyRefStruct[k].hashvalue = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//File
old = tableoffset;
b = tablepresent(38);
offs = tableoffset;
Console.WriteLine("File Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
FileStruct = new FileTable[rows[38] + 1];
for ( int k = 1 ; k <= rows[38] ; k++)
{
FileStruct[k].flags = BitConverter.ToInt32 (metadata, offs);
offs += 4;
FileStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
FileStruct[k].index = ReadBlobIndex(metadata, offs);
offs += offsetblob;
}
}
//ExportedType
old = tableoffset;
b = tablepresent(39);
offs = tableoffset;
Console.WriteLine("ExportedType Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
ExportedTypeStruct = new ExportedTypeTable[rows[39] + 1];
for ( int k = 1 ; k <= rows[39] ; k++)
{
ExportedTypeStruct[k].flags = BitConverter.ToInt32 (metadata, offs);
offs += 4;
ExportedTypeStruct[k].typedefindex = BitConverter.ToInt32 (metadata, offs);
offs += 4;
ExportedTypeStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
ExportedTypeStruct[k].nspace = ReadStringIndex(metadata, offs);
offs += offsetstring;
ExportedTypeStruct[k].coded = ReadCodedIndex ( metadata, offs , "Implementation");
offs += GetCodedIndexSize("Implementation");
}
}
//ManifestResource
old = tableoffset;
b = tablepresent(40);
offs = tableoffset;
Console.WriteLine("ManifestResource Table Offset {0}" , offs);
tableoffset = old;
if ( b )
{
ManifestResourceStruct = new ManifestResourceTable[rows[40] + 1];
for ( int k = 1 ; k <= rows[40] ; k++)
{
ManifestResourceStruct[k].offset = BitConverter.ToInt32 (metadata, offs);
offs += 4;
ManifestResourceStruct[k].flags = BitConverter.ToInt32 (metadata, offs);
offs += 4;
ManifestResourceStruct[k].name = ReadStringIndex(metadata, offs);
offs += offsetstring;
ManifestResourceStruct[k].coded = ReadCodedIndex(metadata , offs , "Implementation");
offs += GetCodedIndexSize("");
}
}
//Nested Classes
old = tableoffset;
b = tablepresent(41);
offs = tableoffset;
Console.WriteLine("Nested Classes Offset {0}" , offs);
tableoffset = old;
if ( b )
{
NestedClassStruct = new NestedClassTable[rows[41] + 1];
for ( int k = 1 ; k <= rows[41] ; k++)
{
NestedClassStruct[k].nestedclass= ReadTableIndex(metadata, offs);
offs += GetTableSize();
NestedClassStruct[k].enclosingclass= ReadTableIndex(metadata, offs);
offs += GetTableSize();
}
}
}
public long ConvertRVA(long rva)
{
int i;
for ( i = 0 ; i < sections ; i++)
{
if ( rva >= SVirtualAddress[i] && ( rva < SVirtualAddress[i] + SSizeOfRawData[i] ))
break ;
}
if ( i >= SPointerToRawData.Length)
return -1;
return SPointerToRawData[i] + ( rva - SVirtualAddress[i] );
}
public void CLRHeader()
{
Console.WriteLine("// CLR Header:");
s.Position = ConvertRVA(datadirectoryrva[14]);
int size = r.ReadInt32();
int majorruntimeversion = r.ReadInt16();
int minorruntimeversion = r.ReadInt16();
metadatarva = r.ReadInt32();
int metadatasize = r.ReadInt32();
corflags = r.ReadInt32();
entrypointtoken = r.ReadInt32();
int resourcesrva = r.ReadInt32();
int resourcessize = r.ReadInt32();
int strongnamesigrva = r.ReadInt32();
int strongnamesigsize = r.ReadInt32();
int codemanagerrva = r.ReadInt32();
int codemanagersize = r.ReadInt32();
vtablerva = r.ReadInt32();
vtablesize = r.ReadInt32();
exportaddressrva = r.ReadInt32();
exportaddresssize = r.ReadInt32();
int managednativeheaderrva = r.ReadInt32();
int managednativeheadersize = r.ReadInt32();
Console.WriteLine("// {0} Header Size", size);
Console.WriteLine("// {0} Major Runtime Version", majorruntimeversion);
Console.WriteLine("// {0} Minor Runtime Version", minorruntimeversion);
Console.WriteLine("// {0} Flags", corflags);
string dummy = "// " + entrypointtoken.ToString("x");
dummy = dummy.PadRight(12) + "Entrypoint Token";
Console.WriteLine(dummy);
DisplayDataDirectory(metadatarva , metadatasize , "Metadata Directory");
DisplayDataDirectory(resourcesrva, resourcessize, "Resources Directory");
DisplayDataDirectory(strongnamesigrva, strongnamesigsize, "Strong Name Signature");
DisplayDataDirectory(codemanagerrva, codemanagersize, "CodeManager Table");
DisplayDataDirectory(vtablerva, vtablesize, "VTableFixups Directory");
DisplayDataDirectory(exportaddressrva, exportaddresssize , "Export Address Table");
DisplayDataDirectory(managednativeheaderrva, managednativeheadersize, "Precompile Header");
Console.WriteLine("// Code Manager Table:");
if ( codemanagerrva == 0)
Console.WriteLine("// default");
}
public void DisplayStrings()
{
Console.WriteLine("\n Strings Stream\n");
for ( int k = 0 ; k < ssize[1] ; k ++ )
{
Console.Write("{0}" , (char) strings[k]);
if ( strings[k] == 0 )
Console.WriteLine();
}
}
public void DisplayUS()
{
Console.WriteLine("\n US Stream\n");
for ( int k = 0 ; k < ssize[2] ; k +=2 )
{
Console.Write("{0}" , (char) us[k]);
if ( us[k] == 0 )
Console.WriteLine();
}
}
public void DisplayGuid()
{
int st=1;
Console.WriteLine("\n GUID Stream\n");
Console.Write("{");
Console.Write("{0}{1}{2}{3}", guid[st+2].ToString("X") , guid[st+1].ToString("X") , guid[st].ToString("X") , guid[st-1].ToString("X"));
Console.Write("-{0}{1}-",guid[st+3].ToString("X") , guid[st+4].ToString("X"));
Console.Write("{0}{1}-",guid[st+6].ToString("X") , guid[st+5].ToString("X"));
Console.Write("{0}{1}-",guid[st+7].ToString("X") , guid[st+8].ToString("X"));
Console.Write("{0}{1}{2}{3}{4}{5}",guid[st+9].ToString("X"),guid[st+10].ToString("X"),guid[st+11].ToString("X"),guid[st+12].ToString("X"),guid[st+13].ToString("X"),guid[st+14].ToString("X"));
Console.Write("}\n");
}
public void ReadStreamsData()
{
startofmetadata = ConvertRVA(metadatarva);
Console.WriteLine("\nMetadata Details\n");
Console.WriteLine("Start of Metadata {0} rva={1}" , metadatarva , startofmetadata );
s.Position = startofmetadata ;
s.Seek(4 + 2 + 2 + 4 , SeekOrigin.Current);
int lengthofstring = r.ReadInt32();
Console.WriteLine("Length of String {0}" , lengthofstring );
s.Seek(lengthofstring , SeekOrigin.Current);
long padding = s.Position % 4 ;
padding = 4 - padding;
s.Seek(2 , SeekOrigin.Current);
int streams = r.ReadInt16();
Console.WriteLine("No of streams {0} Position={1}" , streams , s.Position);
streamnames = new string[5];
offset = new int[5];
ssize = new int[5];
names = new byte[5][];
names[0] = new byte[10];
names[1] = new byte[10];
names[2] = new byte[10];
names[3] = new byte[10];
names[4] = new byte[10];
int j ;
Console.WriteLine("\n Stream Details\n");
for ( int i = 0 ; i < streams ; i++)
{
offset[i] = r.ReadInt32();
ssize[i] = r.ReadInt32();
Console.WriteLine("offset={0} size={1} Position={2}" , offset[i] , ssize[i] , s.Position);
j = 0;
byte bb ;
while ( true )
{
bb = r.ReadByte();
if ( bb == 0)
break;
names[i][j] = bb;
j++;
}
names[i][j] = bb;
streamnames[i] = GetStreamNames(names[i]);
while ( true )
{
if ( s.Position % 4 == 0 )
break;
byte b = r.ReadByte();
if ( b != 0)
{
s.Seek(-1, SeekOrigin.Current);
break;
}
}
}
for ( int i = 0 ; i < streams ; i++)
{
if ( streamnames[i] == "#~" )
{
metadata = new byte[ssize[i]];
s.Seek(startofmetadata + offset[i] , SeekOrigin.Begin);
for ( int k = 0 ; k < ssize[i] ; k ++)
metadata[k] = r.ReadByte();
}
if ( streamnames[i] == "#Strings" )
{
strings = new byte[ssize[i]];
s.Seek(startofmetadata + offset[i] , SeekOrigin.Begin);
for ( int k = 0 ; k < ssize[i] ; k ++)
strings[k] = r.ReadByte();
DisplayStrings();
}
if ( streamnames[i] == "#US" )
{
us = new byte[ssize[i]];
s.Seek(startofmetadata + offset[i] , SeekOrigin.Begin);
for ( int k = 0 ; k < ssize[i] ; k ++)
us[k] = r.ReadByte();
DisplayUS();
}
if ( streamnames[i] == "#GUID" )
{
guid = new byte[ssize[i]];
s.Seek(startofmetadata + offset[i] , SeekOrigin.Begin);
for ( int k = 0 ; k < ssize[i] ; k ++)
guid[k] = r.ReadByte();
DisplayGuid();
}
if ( streamnames[i] == "#Blob" )
{
blob = new byte[ssize[i]];
s.Seek(startofmetadata + offset[i] , SeekOrigin.Begin);
for ( int k = 0 ; k < ssize[i] ; k ++)
blob[k] = r.ReadByte();
}
}
Console.WriteLine("\n Stream offset and stream size\n");
for ( int i = 0 ; i < streams ; i++)
{
Console.WriteLine("{0}...offset: {1} size:{2}" , streamnames[i] , offset[i] , ssize[i]);
}
int heapsizes = metadata[6];
if ( (heapsizes & 0x01) == 0x01)
offsetstring = 4;
if ( (heapsizes & 0x02) == 0x02)
offsetguid = 4;
if ( (heapsizes & 0x04) == 0x04)
offsetblob = 4;
valid = BitConverter.ToInt64(metadata, 8);
tableoffset = 24;
rows = new int[64];
Array.Clear (rows, 0, rows.Length);
for ( int k = 0 ; k <= 63 ; k++)
{
int tablepresent = (int)(valid >> k ) & 1;
if ( tablepresent == 1)
{
rows[k] = BitConverter.ToInt32(metadata , tableoffset);
tableoffset += 4;
}
}
Console.WriteLine("\nNumber of Rows in the tables: \n");
for ( int k = 62 ; k >= 0 ; k--)
{
int tablepresent = (int)(valid >> k ) & 1;
if ( tablepresent == 1)
{
Console.WriteLine("{0} : {1}" , tablenames[k] , rows[k]);
}
}
}
public string GetStreamNames(byte [] b)
{
int i = 0;
while (b[i] != 0 )
{
i++;
}
System.Text.Encoding e = System.Text.Encoding.UTF8;
string s = e.GetString(b , 0 , i );
return s;
}
public int GetTableSize()
{
return 2;
}
public int ReadStringIndex(byte [] a , int o)
{
int z = 0;
if ( offsetstring == 2)
z = BitConverter.ToUInt16 (a , o );
if ( offsetstring == 4)
z = (int)BitConverter.ToUInt32 (a , o );
return z;
}
public int ReadBlobIndex(byte [] a , int o)
{
int z = 0;
if ( offsetblob == 2)
z = BitConverter.ToUInt16 (a , o );
if ( offsetblob == 4)
z = (int)BitConverter.ToUInt32 (a , o );
return z;
}
public int ReadGuidIndex(byte [] a , int o)
{
int z = 0;
if ( offsetguid == 2)
z = BitConverter.ToUInt16 (a , o );
if ( offsetguid == 4)
z = (int)BitConverter.ToUInt32 (a , o );
return z;
}
public int ReadTableIndex(byte [] a , int o)
{
int z = 0;
int z1 = GetTableSize();
if ( z1 == 2)
z = BitConverter.ToUInt16 (a , o );
if ( z1 == 4)
z = (int)BitConverter.ToUInt32 (a , o );
return z;
}
public void DisplayAllMethods (int i)
{
int start , startofnext=0;
start = TypeDefStruct[i].mindex ;
if ( i == (TypeDefStruct.Length -1) )
{
startofnext= MethodStruct.Length;
}
else
startofnext = TypeDefStruct[i+1].mindex ;
Console.WriteLine("Number Of Methods {0}" , startofnext - start);
for ( int j = start ; j < startofnext ; j++)
{
Console.WriteLine("{0}. {1}", j , GetString(MethodStruct[j].name));
}
}
public void DisplayAllFields (int i)
{
if ( FieldStruct == null)
return;
int start , startofnext=0;
start = TypeDefStruct[i].findex ;
if ( i == (TypeDefStruct.Length -1) )
{
startofnext= FieldStruct.Length;
}
else
startofnext = TypeDefStruct[i+1].findex ;
Console.WriteLine("Number Of Fields {0}" , startofnext - start);
for ( int j = start ; j < startofnext ; j++)
{
Console.WriteLine("{0}. {1}", j , GetString(FieldStruct[j].name));
}
}
public void DisplayAllParams (int i)
{
if ( ParamStruct== null)
return;
int start , startofnext=0;
start = MethodStruct[i].param;
if ( i == (MethodStruct.Length -1) )
{
startofnext= ParamStruct.Length;
}
else
startofnext = MethodStruct[i+1].param ;
Console.WriteLine("Number Of Params {0}" , startofnext - start);
for ( int j = start ; j < startofnext ; j++)
{
Console.WriteLine("{0}. {1}", j , GetString(ParamStruct[j].name));
}
}
public void DisplayAllEvents(int i)
{
int ii;
if ( EventMapStruct == null )
return;
for ( ii = 1 ; ii < EventMapStruct.Length ; ii++)
{
if ( i == (EventMapStruct[ii].index ) )
break;
}
if ( ii == EventMapStruct.Length)
return;
int start = EventMapStruct[ii].eindex;
int end;
if ( ii == EventMapStruct.Length -1 )
end = EventStruct.Length - 1;
else
end = EventMapStruct[ii + 1].eindex -1;
Console.WriteLine("Number of Events {0}" , end - start + 1);
for ( int jj = start ; jj <= end ; jj++)
{
Console.WriteLine("{0}. {1}" , jj , GetString(EventStruct[jj].name));
}
}
public void DisplayAllProperties(int i)
{
int ii;
if ( PropertyMapStruct == null || PropertyMapStruct.Length == 1 )
return;
for ( ii = 1 ; ii < PropertyMapStruct.Length ; ii++)
{
if ( i == (PropertyMapStruct[ii].parent) )
break;
}
if ( ii == PropertyMapStruct.Length)
return;
int start = PropertyMapStruct[ii].propertylist;
int end;
if ( ii+1 == PropertyMapStruct.Length )
end = PropertyStruct.Length - 1;
else
end = PropertyMapStruct[ii + 1].propertylist -1;
Console.WriteLine("Number of Properties {0}" , end - start + 1);
for ( int jj = start ; jj <= end ; jj++)
{
Console.WriteLine("{0}. {1}" , jj , GetString(PropertyStruct[jj].name));
}
}
public string GetString(int starting)
{
int i = starting;
while (strings[i] != 0 )
{
i++;
}
System.Text.Encoding e = System.Text.Encoding.UTF8;
string s = e.GetString(strings, starting , i - starting );
if ( s.Length == 0)
return "";
else
return s;
}
public int CorSigUncompressData( byte [] b , int index , out int answer)
{
int cb = 0;
answer = 0;
if ( (b[index] & 0x80) == 0x00)
{
cb = 1;
answer = b[index];
}
if ( (b[index] & 0xC0) == 0x80)
{
cb = 2;
answer = ((b[index] & 0x3f) <<8 ) | b[index+1];
}
if ( (b[index] & 0xE0) == 0xC0)
{
cb = 3;
answer = ((b[index] & 0x1f) <<24 ) | (b[index+1] << 16) | (b[index+2] << 8) | b[index+3];
}
return cb;
}
public string GetType(int b)
{
if ( b == 0x01)
return "void";
if ( b == 0x02)
return "bool";
if ( b == 0x03)
return "char";
if ( b == 0x04)
return "int8";
if ( b == 0x05)
return "unsigned int8";
if ( b == 0x06)
return "int16";
if ( b == 0x07)
return "unsigned int16";
if ( b == 0x08)
return "int32";
if ( b == 0x09)
return "unsigned int32";
if ( b == 0x0a)
return "int64";
if ( b == 0x0b)
return "unsigned int64";
if ( b == 0x0c)
return "float32";
if ( b == 0x0d)
return "float64";
if ( b == 0x0e)
return "string";
if ( b == 0x0f)
return "pointer";
if ( b == 0x10)
return "referencetype";
if ( b== 0x11)
return "valuetype";
if ( b== 0x12)
return "class";
if ( b== 0x14)
return "array";
if ( b== 0x16)
return "typed byref";
if ( b== 0x18)
return "intptr";
if ( b== 0x19)
return "uintptr";
if ( b== 0x1b)
return "function ptr";
if ( b== 0x1c)
return "object";
if ( b== 0x1d)
return "sd array";
if ( b== 0x1f)
return "reqd mod";
if ( b== 0x20)
return "opt mod";
if ( b== 0x21)
return "internal";
if ( b== 0x40)
return "typed mod";
if ( b== 0x41)
return "sentinel";
if ( b== 0x45)
return "pinned";
return "user defined...unknown";
}
public string GetCustomAttributeTypeTable( int a)
{
string s = "";
int tag = a & 0x07;
if ( tag == 0)
s = s + "NotUsed";
if ( tag == 1)
s = s + "NotUsed";
if ( tag == 2)
s = s + "MethodDef";
if ( tag == 3)
s = s + "MethodRef";
if ( tag == 4)
s = s + "NotUsed";
return s;
}
public int GetResolutionScopeValue(int a)
{
return a >> 2;
}
public string GetResolutionScopeTable(int a)
{
string s = "";
int tag = a & 0x03;
if ( tag == 0 )
s = s + "Module" ;
if ( tag == 1 )
s = s + "ModuleRef" ;
if ( tag == 2 )
s = s + "AssemblyRef" ;
if ( tag == 3 )
s = s + "TypeRef" ;
return s;
}
public void DisplayModuleTable()
{
if( ModuleStruct != null)
{
Console.WriteLine("\nModule Table\n");
for ( int ii = 1 ; ii <= ModuleStruct.Length-1 ; ii++)
{
Console.WriteLine("Generation: {0}" ,ModuleStruct[ii].Generation );
Console.WriteLine("Name :{0} {1}" , GetString(ModuleStruct[ii].Name) , ModuleStruct[ii].Name.ToString("X"));
Console.WriteLine("Mvid :#GUID[{0}]" , ModuleStruct[ii].Mvid);
Console.WriteLine("EncId :#GUID[{0}]" , ModuleStruct[ii].EncId );
Console.WriteLine("EncBaseId :#GUID[{0}]" , ModuleStruct[ii].EncBaseId);
Console.WriteLine();
}
}
}
public void DisplayTypeRefTable()
{
if ( TypeRefStruct != null)
{
Console.WriteLine("\nTypeRef Table\n");
for ( int ii = 1 ; ii <= TypeRefStruct.Length-1 ; ii++)
{
Console.WriteLine("Row[{0}]" , ii);
string tablename = GetResolutionScopeTable(TypeRefStruct[ii].resolutionscope) ;
int index = GetResolutionScopeValue(TypeRefStruct[ii].resolutionscope);
string s = DisplayTable(tablename ,index );
Console.WriteLine("ResolutionScope:{0}[{1}]...{2} " , tablename , index,s );
Console.WriteLine("Name :{0}",GetString(TypeRefStruct[ii].name));
Console.WriteLine("Namespace :{0}",GetString(TypeRefStruct[ii].nspace));
Console.WriteLine("\n");
}
}
}
public void DisplayTypeDefTable()
{
if (TypeDefStruct != null)
{
Console.WriteLine("TypeDefTable\n");
for ( int ii = 1 ; ii <= TypeDefStruct.Length -1 ; ii++)
{
Console.WriteLine("Row:{0}" , ii);
TypeAttributes flags = (TypeAttributes)TypeDefStruct[ii].flags;
Console.WriteLine("Flags : {0}" , flags);
Console.WriteLine("Name : {0}" , GetString(TypeDefStruct[ii].name));
Console.WriteLine("NameSpace : {0}" , GetString(TypeDefStruct[ii].nspace));
string tablename = GetTypeDefOrRefTable(TypeDefStruct[ii].cindex);
int index = GetTypeDefOrRefValue(TypeDefStruct[ii].cindex);
string s = DisplayTable(tablename , index);
Console.WriteLine("Extends: {0}[{1}].....{2}",tablename,index, s);
Console.WriteLine("FieldList Field[{0}]", TypeDefStruct[ii].findex);
Console.WriteLine("MethodList Method[{0}]", TypeDefStruct[ii].mindex);
DisplayAllMethods(ii);
DisplayAllFields(ii);
DisplayAllEvents(ii);
DisplayAllProperties(ii);
Console.WriteLine();
}
}
}
public void DisplayNestedClassTable()
{
if( NestedClassStruct != null)
{
Console.WriteLine("\nNested Classes Table\n");
for ( int ii = 1 ; ii <= NestedClassStruct.Length - 1 ; ii++)
{
Console.WriteLine("Row {0}",ii);
Console.WriteLine("Nested Class TypeDef[{0}]...{1}" , NestedClassStruct[ii].nestedclass,GetTypeDefTable(NestedClassStruct[ii].nestedclass ));
Console.WriteLine("Enclosing Class TypeDef[{0}]...{1}" , NestedClassStruct[ii].enclosingclass,GetTypeDefTable(NestedClassStruct[ii].enclosingclass ));
}
Console.WriteLine();
}
}
public string DisplayFieldSignature(int index)
{
string s = "";
int count = blob[index];
Console.WriteLine("count {0} index {1}",count, index);
for ( int l = 1; l <= count ; l++)
s = s + blob[index+l].ToString() + " ";
if ( blob[index+1] == 0x06)
{
s = s+".."+GetType(blob[index+2]);
}
return s;
}
public void DisplayFieldTable()
{
if ( FieldStruct != null)
{
Console.WriteLine("\nFieldTable\n");
for ( int ii = 1 ; ii <= FieldStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}",ii );
Console.WriteLine("Flags: {0}", FieldStruct[ii].flags);
Console.WriteLine("Name : {0}", GetString(FieldStruct[ii].name));
string s = DisplayFieldSignature(FieldStruct[ii].sig);
Console.WriteLine("Signature BLOB[{0}]...{1}", FieldStruct[ii].sig,s );
}
}
}
public void DisplayMethodTable()
{
if (MethodStruct != null)
{
Console.WriteLine("\nMethod Table\n");
for ( int ii = 1 ; ii <= MethodStruct.Length -1 ; ii++)
{
Console.WriteLine("Row :{0}", ii);
Console.WriteLine("RVA :{0}", MethodStruct[ii].rva.ToString("X"));
MethodImplAttributes impflags = (MethodImplAttributes ) MethodStruct[ii].impflags;
Console.WriteLine("ImpFlags :{0}",impflags );
Console.WriteLine("Flags :{0}",MethodStruct[ii].flags);
Console.WriteLine("Name : {0}", GetString(MethodStruct[ii].name));
Console.WriteLine("Signature: #Blob[{0}]",MethodStruct[ii].signature);
Console.WriteLine("ParamList: Param[{0}]",MethodStruct[ii].param);
DisplayAllParams(ii);
DisplayMethodSignature(MethodStruct[ii].signature, ii);
}
}
}
public string GetParamAttributes(short a)
{
if ( a == 0x00)
return "None";
if ( (a & 0x01) == 0x01)
return "[In]";
if ( (a & 0x02) == 0x02)
return "[Out]";
if ( (a & 0x04) == 0x04)
return "[Optional]";
if ( (a & 0x1000) == 0x1000)
return "[Default]";
if ( (a & 0x2000) == 0x2000)
return "[Field Marshal]";
if ( (a & 0xcfe0) == 0xcfe0)
return "[Field Marshall]";
return "Unknown";
}
public void DisplayParamTable()
{
if ( ParamStruct != null)
{
Console.WriteLine();
Console.WriteLine("\nParam Table\n");
for ( int ii = 1 ; ii <= ParamStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("ParamAttributes {0} Bytes {1}" , GetParamAttributes(ParamStruct[ii].pattr) , ParamStruct[ii].pattr.ToString("X") );
Console.WriteLine("Sequence {0}" , ParamStruct[ii].sequence );
Console.WriteLine("Name {0}" , GetString(ParamStruct[ii].name));
Console.WriteLine("\n");
}
}
}
public void DisplayInterfaceImplTable()
{
if ( InterfaceImplStruct != null)
{
Console.WriteLine("InterfaceImpl Table");
for ( int ii = 1 ; ii <= InterfaceImplStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
int ind = InterfaceImplStruct[ii].classindex ;
Console.WriteLine("Class TypeDef[{0}]...{1}" , ind , GetTypeDefTable(ind) );
string tablename = GetTypeDefOrRefTable(InterfaceImplStruct[ii].interfaceindex);
int index = GetTypeDefOrRefValue(InterfaceImplStruct[ii].interfaceindex);
Console.WriteLine("Interface {0}[{1}] {2}" , tablename , index , DisplayTable(tablename , index));
}
}
}
public string GetCallingConvention ( int uncompressedbyte )
{
int firstbyte = uncompressedbyte;
byte firstfourbits = (byte)(firstbyte & 0x0f);
string s = " Calling Convention ";
if ( firstfourbits == 0x00)
s = s + " DEFAULT ";
if ( firstfourbits == 0x01)
s = s + " C ";
if ( firstfourbits == 0x02)
s = s + " STDCALL ";
if ( firstfourbits == 0x03)
s = s + " THISCALL ";
if ( firstfourbits == 0x04)
s = s + " FASTCALL ";
if ( firstfourbits == 0x05)
s = s + " VARARG ";
if ( (firstbyte & 0x20) == 0x20)
s = s + " HASTHIS ";
if ( (firstbyte & 0x40) == 0x40)
s = s + " EXPLICIT ";
s = s + "\n";
return s;
}
public string GetValueType(byte [] b , int bytes , int index , out int cb1)
{
int uncompressedbyte;
int cb = CorSigUncompressData(b , index + 1 , out uncompressedbyte);
byte table = (byte)(uncompressedbyte & 0x03);
int ind = uncompressedbyte >> 2;
string s1= "";
if ( table == 1)
s1 = typerefnames[ind];
if ( table == 0)
s1 = typedefnames[ind];
cb1 = cb;
return s1;
}
public string GetClassType(byte [] b , int bytes , int index , out int cb1)
{
int uncompressedbyte;
int cb = CorSigUncompressData(b , index + 1 , out uncompressedbyte);
Console.WriteLine("Token Count cb={0} uncompresedbyte={1}", cb,uncompressedbyte);
byte table = (byte)(uncompressedbyte & 0x03);
int ind = uncompressedbyte >> 2;
Console.WriteLine("Token Table={0} index={1}", table ,ind);
string s1= "";
if ( table == 1)
s1 = typerefnames[ind];
if ( table == 0)
s1 = typedefnames[ind];
cb1 = cb;
return s1;
}
public string GetElemType ( int index , byte [] b , out int cb1)
{
cb1 = 0;
string s = "";
if ( index == b.Length )
return s;
byte type = b[index];
if ( type >= 0x01 && type <= 0x0e )
{
s = GetType(type);
cb1 = 1;
}
if ( type == 0x0f)
{
int cb2;
if ( b[index+1] <= 0x0e)
{
s = GetPointerType( b , index + 1, out cb2);
cb1 = cb2 + 1;
}
else if (b[index + 1] == 0x11 )
{
s = "valuetype " + GetTokenType( b , index + 1, out cb2) + "*";
cb1 = cb2 + 2;
}
else if (b[index + 2] == 0x12 )
{
s = "class " + GetTokenType( b , index + 1, out cb2) + "*";
cb1 = cb2 + 2;
}
else
{
s = GetTokenType( b , index + 1, out cb2) + "*";
cb1 = cb2 + 1;
}
}
if ( type == 0x10)
{
int cb2;
if ( b[index+1] >= 0x00 && b[index+1] <= 0x0e)
{
s = GetType(b[index+1]) + "&";
cb1 = 2;
}
else if ( b[index+1] == 0x1D)
{
s = GetType(b[index+1]) + "[]&";
cb1 = 2;
}
else
{
s = GetTokenType( b , index , out cb2);
cb1 = cb2 + 1;
}
}
if ( type == 0x11 || type == 0x12 )
{
int cb2;
s = GetTokenType( b , index , out cb2);
cb1 = cb2 + 1;
}
if ( type == 0x14 )
{
int cb2;
s = GetArrayType( b , index , out cb2);
cb1 = cb2 + 1;
}
if ( type == 0x16)
{
s = "typedbyref";
cb1 = 1;
}
if ( type == 0x18)
{
s = "native int";
cb1 = 1;
}
if ( type == 0x19)
{
s = "native unsigned int";
cb1 = 1;
}
if ( type == 0x1c)
{
s = "object";
cb1 = 1;
}
if ( type == 0x1d)
{
int i = 1;
s = "[]";
while ( true )
{
byte next = b[index+i];
if ( next != 0x1d )
break;
s = s + "[]";
i = i +1 ;
}
int cb2;
s = s + GetElemType(index + i , b , out cb2);
cb1 = i + cb2;
}
if ( type == 0x20 )
{
int cb2;
s = "modopt " + GetTokenType( b , index , out cb2);
cb1 = cb2 + 1;
}
if ( type == 0x45 )
{
int cb2 ;
s = GetElemType( index + 1 , b , out cb2) + " pinned";
cb1 = cb2 + 1;
}
return s;
}
public string GetTokenType ( byte [] b , int index , out int cb1)
{
string s = "";
int uncompressedbyte;
int cb = 0;
if ( b[index] == 0x10 && b[index + 1] == 0x11)
{
index++;
cb=1;
}
if ( b[index] == 0x10 && b[index + 1] == 0x12)
{
index++;
cb=1;
}
cb = cb + CorSigUncompressData(b , index + 1 , out uncompressedbyte);
string s1 = DecodeToken(uncompressedbyte);
if ( b[index] == 0x12)
{
s = "class " + s1;
}
else if ( b[index] == 0x11)
{
s = "valuetype " + s1;
}
else if ( b[index] == 0x10)
{
s = "[out] " + s1;
}
else
s = s1;
cb1 = cb;
return s;
}
public string DecodeToken (int token)
{
byte table = (byte)(token & 0x03);
int ind = token >> 2;
string s1 = "";
if ( table == 0)
s1 = GetString(TypeDefStruct[ind].name);
if ( table == 1 )
s1 = GetString(TypeRefStruct[ind].name) ;
return s1;
}
public string GetPointerType( byte [] b , int index , out int cb1)
{
string s = "";
s = GetElemType(index , b , out cb1) + " *" ;
return s;
}
public string GetArrayType (byte [] b , int index , out int cb1)
{
string s ;
int total = 1;
int uncompressedbyte;
int rank;
int numsizes;
int cb;
s = GetElemType(index +1 , b , out cb1);
total = total + cb1;
s = s + " [";
cb = CorSigUncompressData(b , index + total, out uncompressedbyte);
total = total + cb;
rank = uncompressedbyte;
cb = CorSigUncompressData(b , index + total, out uncompressedbyte);
total = total + cb;
numsizes = uncompressedbyte;
int [] sizearray = new int[numsizes];
for ( int l = 1 ; l <= numsizes ; l++)
{
cb = CorSigUncompressData(b , index + total, out uncompressedbyte);
total = total + cb;
sizearray[l-1] = uncompressedbyte;
}
cb = CorSigUncompressData(b , index + total, out uncompressedbyte);
total = total + cb;
int bounds = uncompressedbyte;
int [] boundsarray = new int[bounds];
for ( int l = 1 ; l <= bounds ; l++)
{
cb = CorSigUncompressData(b , index + total, out uncompressedbyte);
total = total + cb;
int ulSigned = uncompressedbyte & 0x1;
uncompressedbyte = uncompressedbyte >> 1;
if (ulSigned == 1)
{
if (cb == 1)
{
uncompressedbyte = (int) ((ushort)uncompressedbyte | 0xffffffc0);
}
else if (cb == 2)
{
uncompressedbyte = (int) ((ushort)uncompressedbyte | 0xffffe000) ;
}
else
{
uncompressedbyte = (int)((ushort)uncompressedbyte | 0xf0000000);
}
}
boundsarray[l-1] = uncompressedbyte ;
}
for ( int l = 0 ; l < bounds ; l++)
{
if (numsizes != 0)
{
int upper = boundsarray[l] + sizearray[l] - 1 ;
if ( boundsarray[l] == 0 && sizearray[l] != 0 )
{
s = s + sizearray[l] ;
if ( l != bounds -1 )
s = s + ",";
}
if (boundsarray[l] == 0 && sizearray[l] == 0)
s = s + "," ;
if (boundsarray[l] != 0 && sizearray[l] != 0)
{
s = s + boundsarray[l] + "..." + upper.ToString() ;
}
if ( !(bounds - l == 1) )
s = s + ",";
}
}
int leftover = rank - numsizes ;
if ( numsizes == 0)
leftover--;
for ( int l = 1 ; l <= leftover ; l++)
s = s + ",";
s = s + "]";
cb1 = total-1;
return s;
}
public string GetMemberRefParentTable(int a)
{
string s = "";
int tag = a & 0x07;
if ( tag == 0)
s = s + "NotUsed";
if ( tag == 1)
s = s + "TypeRef";
if ( tag == 2)
s = s + "ModuleRef";
if ( tag == 3)
s = s + "MethodDef";
if ( tag == 4)
s = s + "TypeSpec";
return s;
}
public int GetMemberRefParentValue(int a)
{
return a >> 3;
}
public void DisplayMemberRefTable()
{
if ( MemberRefStruct != null)
{
Console.WriteLine("\nMemberRef Table\n");
for ( int ii = 1 ; ii <= MemberRefStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}",ii);
string s = GetMemberRefParentTable(MemberRefStruct[ii].clas);
int rid = (int)GetMemberRefParentValue(MemberRefStruct[ii].clas);
Console.WriteLine("{0}[{1}]:{2}",s,rid,DisplayTable(s,rid));
Console.WriteLine("Name:{0}" , GetString(MemberRefStruct[ii].name));
Console.Write("Signature #BLOB[{0}] ", MemberRefStruct[ii].sig);
Console.WriteLine("\n");
}
}
}
public int GetHasConstValue(int a)
{
return a >> 2;
}
public string GetHasConstTable(int a)
{
string s = "";
int tag = a & 0x03;
Console.Write("Parent: ");
if ( tag == 0)
s = s + "FieldDef";
if ( tag == 1)
s = s + "ParamDef";
if ( tag == 2)
s = s + "Property";
return s;
}
public long GetBytesFromArray(int value , int dtype)
{
long z = 0;
if ( dtype == 2 || dtype == 4 || dtype == 5 )
z = blob[value + 1];
if ( dtype == 3 || dtype == 6 || dtype == 7 )
z = BitConverter.ToInt16 (blob , value + 1);
if ( dtype == 8 || dtype == 9 )
z = BitConverter.ToInt32 (blob , value + 1);
if ( dtype == 0x0a || dtype == 0x0b )
z = BitConverter.ToInt64 (blob , value + 1);
return z;
}
public void GetStringFromBlobArray(int value)
{
int count = blob[value];
Console.Write(" Value ");
for ( int i = 1 ; i <= count ; i = i+2)
Console.Write("{0}" , (char) blob[value + i] );
}
public void GetBlobConstant(int value , int dtype)
{
int count = blob[value];
Console.Write("Blob BLOB[{0}] Count {1} ",value , count);
for ( int l = 1 ; l <= count ; l++)
{
Console.Write("{0} " , blob[value+l].ToString("X"));
}
if ( dtype <= 0x0b )
{
long val = GetBytesFromArray(value , dtype );
Console.Write(" Value {0} " , val);
}
if (dtype == 0x0e)
GetStringFromBlobArray(value );
Console.WriteLine();
}
public void DisplayConstantTable()
{
if ( ConstantsStruct != null)
{
Console.WriteLine("\nConstant Table\n");
for ( int ii = 1 ; ii <= ConstantsStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Type {0}" , GetType(ConstantsStruct[ii].dtype));
string s = GetHasConstTable(ConstantsStruct[ii].parent);
int off = GetHasConstValue(ConstantsStruct[ii].parent);
int p = 0;
if ( s == "FieldDef" )
{
p = FieldStruct[off].name;
}
if ( s == "ParamDef" )
{
p = ParamStruct[off].name;
}
if ( s == "Property" )
{
p = PropertyStruct[off].name;
}
Console.WriteLine("{0}[{1}] Name of Constant... {2} ", s, off , GetString(p));
GetBlobConstant(ConstantsStruct[ii].value , ConstantsStruct[ii].dtype);
}
}
}
public int GetCustomAttributeTypevalue(int a)
{
return a >> 3;
}
public int GetHasCustomAttributeValue( int a)
{
return a >> 5;
}
public string GetHasCustomAttributeTable( int a)
{
string s = "";
int tag = a & 0x1F;
if ( tag == 0)
s = s + "MethodDef";
if ( tag == 1)
s = s + "FieldDef";
if ( tag == 2)
s = s + "TypeRef";
if ( tag == 3)
s = s + "TypeDef";
if ( tag == 4)
s = s + "ParamDef";
if ( tag == 5)
s = s + "InterfaceImpl";
if ( tag == 6)
s = s + "MemberRef";
if ( tag == 7)
s = s + "Module";
if ( tag == 8)
s = s + "DeclSecurity";
if ( tag == 9)
s = s + "Property";
if ( tag == 10)
s = s + "Event";
if ( tag == 11)
s = s + "Signature";
if ( tag == 12)
s = s + "ModuleRef";
if ( tag == 13)
s = s + "TypeSpec";
if ( tag == 14)
s = s + "Assembly";
if ( tag == 15)
s = s + "AssemblyRef";
if ( tag == 16)
s = s + "File";
if ( tag == 17)
s = s + "ExportedType";
if ( tag == 18)
s = s + "ManifestResource";
return s;
}
public void GetCustomAttributeBlob( int index )
{
int count = blob[index];
Console.Write("Value Blob[{0}] Count {1} Bytes ",index, count );
for ( int l = 1 ; l <= count ; l++)
{
Console.Write("{0} " , blob[index+l].ToString("X"));
}
Console.WriteLine();
}
public void DisplayCustomAttributeTable()
{
if ( CustomAttributeStruct != null)
{
Console.WriteLine("\n CustomAttribute Table\n");
for ( int ii = 1 ; ii <= CustomAttributeStruct.Length-1 ; ii++)
{
Console.WriteLine("Row [{0}]", ii);
string tablename= GetHasCustomAttributeTable(CustomAttributeStruct[ii].parent) ;
int index = GetHasCustomAttributeValue(CustomAttributeStruct[ii].parent);
string s = DisplayTable(tablename , index );
Console.WriteLine("Parent: {0}[{1}]...{2}" , tablename, index,s );
tablename = GetCustomAttributeTypeTable(CustomAttributeStruct[ii].type) ;
index = GetCustomAttributeTypevalue(CustomAttributeStruct[ii].type);
s = DisplayTable(tablename , index );
Console.WriteLine("Type: {0}[{1}]...{2} " , tablename , index,s );
GetCustomAttributeBlob(CustomAttributeStruct[ii].value);
}
}
}
public string GetFieldMarshalTable(int a)
{
string s = "";
short tag = (short)(a & (short)0x01);
if ( tag == 0)
s = s + "Field";
if ( tag == 1)
s = s + "Param";
return s;
}
public int GetFieldMarshalValue(int a)
{
return a >> 1;
}
public string GetMarshallType(byte a)
{
if ( a == 2)
return "NATIVE_TYPE_BOOLEAN";
if ( a == 3)
return "NATIVE_TYPE_I1";
if ( a == 0x04)
return "NATIVE_TYPE_U1";
if ( a == 0x05)
return "NATIVE_TYPE_I2";
if ( a == 0x06)
return "NATIVE_TYPE_U2";
if ( a == 0x07)
return "NATIVE_TYPE_I4";
if ( a == 0x08)
return "NATIVE_TYPE_U4";
if ( a == 0x09)
return "NATIVE_TYPE_I8";
if ( a == 0x0a)
return "NATIVE_TYPE_U8";
if ( a == 0x0b)
return "NATIVE_TYPE_R4";
if ( a == 0x0c)
return "NATIVE_TYPE_R8";
if ( a == 0x14)
return "NATIVE_TYPE_LPSTR";
if ( a == 0x1f)
return "NATIVE_TYPE_INT";
if ( a == 0x20)
return "NATIVE_TYPE_UINT";
if ( a == 0x26)
return "NATIVE_TYPE_FUNC";
if ( a == 0x2a)
return "NATIVE_TYPE_ARRAY";
if ( a == 0x0f)
return "NATIVE_TYPE_CURRENCY";
if ( a == 0x13)
return "NATIVE_TYPE_BSTR";
if ( a == 0x15)
return "NATIVE_TYPE_LPWSTR";
if ( a == 0x16)
return "NATIVE_TYPE_LPTSTR";
if ( a == 0x17)
return "NATIVE_TYPE_FIXEDSYSSTRING";
if ( a == 0x19)
return "NATIVE_TYPE_IUNKNOWN";
if ( a == 0x1a)
return "NATIVE_TYPE_IDISPATCH";
if ( a == 0x1b)
return "NATIVE_TYPE_STRUCT";
if ( a == 0x1c)
return "NATIVE_TYPE_INTF";
if ( a == 0x1d)
return "NATIVE_TYPE_SAFEARRAY";
if ( a == 0x1e)
return "NATIVE_TYPE_FIXEDARRAY";
if ( a == 0x22)
return "NATIVE_TYPE_BYVALSTR";
if ( a == 0x13)
return "NATIVE_TYPE_ANSIBSTR";
if ( a == 0x24)
return "NATIVE_TYPE_TBSTR";
if ( a == 0x25)
return "NATIVE_TYPE_VARIANTBOOL";
if ( a == 0x28)
return "NATIVE_TYPE_ASANY";
if ( a == 0x2b)
return "NATIVE_TYPE_LPSTRUCT";
if ( a == 0x2c)
return "NATIVE_TYPE_CUSTOMMARSHALER";
if ( a == 0x2d)
return "NATIVE_TYPE_ERROR";
if ( a == 0x50)
return "NATIVE_TYPE_NOINFO";
return "Unknown";
}
public void DisplayFieldMarshalTable()
{
if ( FieldMarshalStruct != null)
{
Console.WriteLine("\nFieldMarshal Table\n");
for ( int ii = 1 ; ii <= FieldMarshalStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
string tablename = GetFieldMarshalTable(FieldMarshalStruct[ii].coded) ;
int index = GetFieldMarshalValue(FieldMarshalStruct[ii].coded);
Console.WriteLine("Parent {0}[{1}]...{2}" ,tablename , index , DisplayTable(tablename ,index ));
int count = blob[FieldMarshalStruct[ii].index];
Console.WriteLine("Native Type Blob[{0}] Count {1} {2} " , index , count , GetMarshallType(blob[FieldMarshalStruct[ii].index+1]));
}
}
}
public string GetDeclSecurityTable(int a)
{
string s = "";
short tag = (short)(a & (short)0x03);
if ( tag == 0)
s = s + "TypeDef";
if ( tag == 1)
s = s + "MethodDef";
if ( tag == 2)
s = s + "Assembly";
return s;
}
public int GetDeclSecurityValue(int a)
{
return a >> 2;
}
public void DisplayDeclSecurityTable()
{
if ( DeclSecurityStruct != null)
{
Console.WriteLine("\nDeclSecurity Table\n");
for ( int ii = 1 ; ii <= DeclSecurityStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Action {0}" , DeclSecurityStruct[ii].action);
string tablename = GetDeclSecurityTable(DeclSecurityStruct[ii].coded);
int ind = GetDeclSecurityValue(DeclSecurityStruct[ii].coded);
Console.WriteLine("Parent: {0}[{1}]... {2}" , tablename , ind , DisplayTable(tablename , ind));
int uncompressedbyte;
int cb = CorSigUncompressData(blob , DeclSecurityStruct[ii].bindex, out uncompressedbyte);
int count = uncompressedbyte;
int index1 = DeclSecurityStruct[ii].bindex + cb;
Console.WriteLine("Permission Set BLOB[{0}] Count={1} " , index1, count );
for ( int l = 0 ; l < count ; l++)
Console.Write("{0}", (char)blob[index1 + l]);
}
Console.WriteLine();
}
}
public void DisplayClassLayoutTable()
{
if ( ClassLayoutStruct != null)
{
Console.WriteLine("\nClassLayout Table\n");
for ( int ii = 1 ; ii <= ClassLayoutStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Packing Size {0}" , ClassLayoutStruct[ii].packingsize );
Console.WriteLine("Class Size {0}" , ClassLayoutStruct[ii].classsize );
int i = ClassLayoutStruct[ii].parent;
string s = GetTypeDefTable(i);
Console.WriteLine("Parent TypeDef[{0}]...{1} " , i,s );
}
}
}
public void DisplayFieldLayoutTable()
{
if ( FieldLayoutStruct != null)
{
Console.WriteLine("\n Field Layout Table\n");
for ( int ii= 1 ; ii<= FieldLayoutStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Offset:{0}" , FieldLayoutStruct[ii].offset);
int index = FieldLayoutStruct[ii].fieldindex;
string s = GetFieldTable(index);
Console.WriteLine("Field :Field[{0}]...{1}" , index , s);
}
}
}
public string DisplayStandAloneSigSignature(int index)
{
string s = "";
int count = blob[index];
s = s + count.ToString() + " ";
for ( int l = 1; l <= count ; l++)
s = s + blob[index+l].ToString() + " ";
return s;
}
public void DisplayStandAloneSigTable()
{
if ( StandAloneSigStruct != null)
{
Console.WriteLine("\nStandAloneSig Table\n");
for ( int ii = 1 ; ii <= StandAloneSigStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
string s = DisplayStandAloneSigSignature(StandAloneSigStruct[ii].index );
Console.WriteLine("Signature BLOB[{0}] Count {1} " , StandAloneSigStruct[ii].index , s );
}
}
}
public string GetTypeRefTable( int index)
{
int name = TypeRefStruct[index].name;
int nspace = TypeRefStruct[index].nspace;
string s = GetString(nspace) ;
if ( s != "null" )
s = s + ".";
else
s = "";
s = s + GetString(name);
return s;
}
public string GetTypeDefOrRefTable(int a)
{
string s = "";
short tag = (short)(a & (short)0x03);
if ( tag == 0)
s = s + "TypeDef";
if ( tag == 1)
s = s + "TypeRef";
if ( tag == 2)
s = s + "TypeSpec";
return s;
}
public int GetTypeDefOrRefValue(int a)
{
return a >> 2;
}
public string GetTypeDefTable( int index)
{
int name = TypeDefStruct[index].name;
int nspace = TypeDefStruct[index].nspace;
int cindex = TypeDefStruct[index].cindex;
int typereftableindex = GetTypeDefOrRefValue(cindex);
string tablename = GetTypeDefOrRefTable(cindex);
string s1 = "";
if ( tablename == "TypeRef")
s1 = " Extends " + GetTypeRefTable(typereftableindex);
if (GetString(nspace)!= "")
s1 = s1 + " Namespace: " + GetString(nspace);
string s = "Class " + GetString(name) + s1 ;
return s;
}
public string GetEventTable(int index)
{
string s = "";
int ind = EventStruct[index].name;
s = GetString(ind);
int coded = EventStruct[index].coded;
string tablename = GetTypeDefOrRefTable(coded);
int ind1 = GetTypeDefOrRefValue(coded);
string s1 = DisplayTable(tablename , ind1);
s = "Event " + s + " " + s1 + " ";
return s;
}
public string DisplayEventsList(int start , int rowindex)
{
string s = "";
int end = EventStruct.Length;
int end1 = 10000;
if ( rowindex <= EventMapStruct.Length)
end1 = EventMapStruct[rowindex].eindex;
int end2 = 0;
if ( end <= end1)
end2 = end;
else
end2 = end1;
for ( int i = start ; i <= end2 ; i++)
s = s + GetEventTable(i) + "\n";
return s;
}
public void DisplayEventMapTable()
{
if ( EventMapStruct != null)
{
Console.WriteLine("\nEventMap Table\n");
for ( int ii = 1 ; ii <= EventMapStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Parent TypeDef[{0}]...{1}" , EventMapStruct[ii].index , GetTypeDefTable(EventMapStruct[ii].index ) );
string s=DisplayEventsList(EventMapStruct[ii].eindex,ii);
Console.Write("EventList Event[{0}]...{1}" , EventMapStruct[ii].eindex,s);
}
}
}
public string GetEventsAttributes(int a)
{
string s = "";
if ( (a & 0x0200) == 0x0200)
s = s + "Special Name";
if ( (a & 0x0400) == 0x0400)
s = s + "RTSpecialName";
if (s.Length == 0)
return "None";
else
return s;
}
public void DisplayEventTable()
{
if ( EventStruct != null)
{
Console.WriteLine("\nEvent Table\n");
for ( int ii = 1 ; ii <= EventStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Event Flags: {0}" , GetEventsAttributes(EventStruct[ii].attr));
Console.WriteLine("Name: {0}" , GetString(EventStruct[ii].name));
string tablename = GetTypeDefOrRefTable(EventStruct[ii].coded) ;
int index = GetTypeDefOrRefValue(EventStruct[ii].coded);
Console.WriteLine("Event Type:{0}[{1}]... {2}" , tablename ,
index , DisplayTable(tablename, index));
}
}
}
public string DisplayPropertiesList(int start , int rowindex)
{
string s = "";
int end = PropertyStruct.Length;
int end1 = 10000;
if ( rowindex <= PropertyMapStruct.Length)
end1 = PropertyMapStruct[rowindex].propertylist;
int end2 = 0;
if ( end <= end1)
end2 = end;
else
end2 = end1;
for ( int i = start ; i <= end2 ; i++)
s = s + GetPropertyTable(i) + "\n";
return s;
}
public string GetPropertyTable(int index)
{
string s = "";
int ind = PropertyStruct[index].name;
s = GetString(ind);
return s;
}
public void DisplayPropertyMapTable()
{
if ( PropertyMapStruct != null)
{
Console.WriteLine("\n Property Map Table\n");
for ( int ii = 1 ; ii <= PropertyMapStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Parent TypeDef[{0}]...{1}" , PropertyMapStruct[ii].parent , GetTypeDefTable(PropertyMapStruct[ii].parent ));
string s=DisplayPropertiesList(PropertyMapStruct[ii].propertylist,ii);
Console.WriteLine("PropertyList Property[{0}]...{1}" , PropertyMapStruct[ii].propertylist,s );
}
}
}
public string DisplayPropertySignature(int index)
{
string s = "";
int count = blob[index];
s = s + count.ToString() + " ";
for ( int l = 1; l <= count ; l++)
s = s + blob[index+l].ToString() + " ";
return s;
}
public void DisplayPropertiesTable()
{
if ( PropertyStruct != null)
{
Console.WriteLine("\nProperties Table\n");
for ( int ii = 1 ; ii <= PropertyStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Flags [{0}]" , PropertyStruct[ii].flags);
Console.WriteLine("Name {0}" , GetString(PropertyStruct[ii].name));
string s = DisplayPropertySignature(PropertyStruct[ii].type);
Console.WriteLine("Type BLOB[{0}]...{1} " , PropertyStruct[ii].type , s);
}
}
}
public string GetMethodSemanticsAttributes(short a)
{
string s = "";
if ( (a & 0x01) == 0x01)
s = s + "Setter";
if ( (a & 0x02) == 0x02)
s = s + "Getter";
if ( (a & 0x04) == 0x04)
s = s + "Other";
if ( (a & 0x08) == 0x08)
s = s + "Event Addon";
if ( (a & 0x10) == 0x10)
s = s + "Event Remove";
if ( (a & 0x20) == 0x20)
s = s + "Event Fire";
return s;
}
public int GetMethodDefValue(int a)
{
return a >> 1;
}
public string GetMethodDefTable(int a)
{
string s = "";
short tag = (short)(a & (short)0x01);
if ( tag == 0)
s = s + "MethodDef";
if ( tag == 1)
s = s + "MethodRef";
return s;
}
public string GetMethodTable( int index)
{
string s = "";
int ind = MethodStruct[index].name;
s = GetString(ind);
return s;
}
public int GetHasSemanticsValue(int a)
{
return a >> 1;
}
public string GetHasSemanticsTable(int a)
{
string s = "";
int tag = a & 0x01;
if ( tag == 0 )
s = s + "Event";
if ( tag == 1 )
s = s + "Property";
return s;
}
public void DisplayMethodSemanticsTable()
{
if ( MethodSemanticsStruct != null)
{
Console.WriteLine("\nMethodSemantics Table\n");
for ( int ii = 1 ; ii <= MethodSemanticsStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Semantics {0} ", GetMethodSemanticsAttributes(MethodSemanticsStruct[ii].methodsemanticsattributes));
string s = GetMethodTable(MethodSemanticsStruct[ii].methodindex );
Console.WriteLine("Method Method[{0}]...{1}", MethodSemanticsStruct[ii].methodindex , s);
string tablename = GetHasSemanticsTable(MethodSemanticsStruct[ii].association);
int index = GetHasSemanticsValue(MethodSemanticsStruct[ii].association);
s = DisplayTable(tablename,index );
Console.WriteLine("Association:{0}[{1}]...{2} ",tablename,index,s );
}
}
}
public void DisplayMethodImpTable()
{
if ( MethodImpStruct != null)
{
Console.WriteLine("\n MethodImp Table\n");
for ( int ii = 1 ; ii <= MethodImpStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Class TypeDef[{0}]...{1}" , MethodImpStruct[ii].classindex , GetTypeDefTable(MethodImpStruct[ii].classindex));
string tablename = GetMethodDefTable(MethodImpStruct[ii].codedbody );
int index = GetMethodDefValue(MethodImpStruct[ii].codedbody );
string s = DisplayTable(tablename , index );
Console.WriteLine("MethodBody {0}[{1}]...{2} " , tablename , index,s );
tablename = GetMethodDefTable(MethodImpStruct[ii].codeddef );
index = GetMethodDefValue(MethodImpStruct[ii].codeddef);
s = DisplayTable(tablename , index );
Console.WriteLine("MethodDeclaration {0}[{1}]...{2} " , tablename , index,s );
}
}
}
public void DisplayModuleRefTable()
{
if ( ModuleRefStruct != null)
{
Console.WriteLine("\nModuleRef Table\n");
for ( int ii = 1 ; ii <= ModuleRefStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Name {0}" , GetString(ModuleRefStruct[ii].name));
}
}
}
public void DisplayTypeSpecTableTable()
{
if ( TypeSpecStruct != null)
{
Console.WriteLine("\nTypeSpec Table\n");
for ( int ii = 1 ; ii <= TypeSpecStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}",ii);
byte count = blob[TypeSpecStruct[ii].signature ];
Console.WriteLine("Signature BLOB[{0}] Count {1}" , TypeSpecStruct[ii].signature , count );
for (int l = 1 ; l <= count ; l++)
{
Console.WriteLine("{0} {1}" , blob[TypeSpecStruct[ii].signature + l],GetType(blob[TypeSpecStruct[ii].signature + l]));
}
Console.WriteLine();
}
}
}
public string GetPInvokeAttributes(short a)
{
string s = "";
if ( (a & 0x0001) == 0x0001)
s = s + "NoMangle ";
if ( (a & 0x0006) == 0x0006)
s = s + "CharSetMask ";
if ( (a & 0x0000) == 0x0000)
s = s + "CharSetNotSpec ";
if ( (a & 0x0002) == 0x0002)
s = s + "CharSetAnsi ";
if ( (a & 0x0004) == 0x0004)
s = s + "CharSetUnicode ";
if ( (a & 0x0004) == 0x0004)
s = s + "CharSetAuto ";
if ( (a & 0x0040) == 0x0040)
s = s + "SupportsLastError ";
if ( (a & 0x0700) == 0x0700)
s = s + "CallConvMask ";
if ( (a & 0x0100) == 0x0100 )
s = s + "CallConvWinapi ";
if ( (a & 0x0200) == 0x0200)
s = s + "CallConvCdecl ";
if ( (a & 0x0300) == 0x0300)
s = s + "CallConvStdcall ";
if ( (a & 0x0400) == 0x0400)
s = s + "CallConvThiscall ";
if ( (a & 0x0500) == 0x0500)
s = s + "CallConvFastcall ";
return s;
}
public int GetMemberForwardedValue(int a)
{
return a >> 1 ;
}
public string GetMemberForwardedTable(int a)
{
string s = "";
int tag = a & 0x01;
if ( tag == 0 )
s = "Field";
if ( tag == 1 )
s = "MethodDef";
return s;
}
public string GetModuleRefTable(int index)
{
string s = "";
int ind = ModuleRefStruct[index].name;
s = GetString(ind);
return s;
}
public void DisplayImplMapTable()
{
if ( ImplMapStruct != null)
{
Console.WriteLine("ImplMap Table\n");
for ( int ii = 1 ; ii <= ImplMapStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Mapping Flags :{0}", GetPInvokeAttributes(ImplMapStruct[ii].attr));
string tablename = GetMemberForwardedTable(ImplMapStruct[ii].cindex);
int index = GetMemberForwardedValue(ImplMapStruct[ii].cindex);
string s = DisplayTable(tablename , index);
Console.WriteLine("MemberForwarded:{0}[{1}]...{2} " , tablename , index,s );
Console.WriteLine("Name :{0}" , GetString(ImplMapStruct[ii].name));
index = ImplMapStruct[ii].scope ;
Console.WriteLine("Import Scope :ModuleRef[{0}] {1}" , index , GetModuleRefTable(index));
}
}
}
public string GetFieldTable( int index)
{
string s = "";
int ind = FieldStruct[index].name;
s = GetString(ind);
return s;
}
public string GetFileAttributes(int a)
{
string s = "";
if ( a == 0x00)
s= "ContainsMetaData";
if ( a == 0x01)
s= "ContainsNoMetaData";
return s;
}
public void DisplayFieldRVATable()
{
if ( FieldRVAStruct != null)
{
Console.WriteLine("\n FieldRVA Tble \n");
for ( int ii = 1 ; ii <= FieldRVAStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("RVA {0}" , FieldRVAStruct[ii].rva.ToString("X"));
int index = FieldRVAStruct[ii].fieldi;
Console.WriteLine("Field Field[{0}]... {1}" ,index , GetFieldTable(index) );
}
}
}
public string GetAssemblyTable( int index)
{
int ind = AssemblyStruct[index].name;
return GetString(ind);
}
public string GetAssemblyRefTable( int index)
{
int ind = AssemblyRefStruct[index].name;
return GetString(ind);
}
public void DisplayAssemblyTable()
{
if ( AssemblyStruct != null)
{
Console.WriteLine("Assembly Table\n");
for ( int ii = 1 ; ii <= AssemblyStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("HashAlgId {0}",AssemblyStruct[ii].HashAlgId );
Console.WriteLine("MajorVersion {0}",AssemblyStruct[ii].major );
Console.WriteLine("MinorVersion {0}",AssemblyStruct[ii].minor);
Console.WriteLine("BuildNumber {0}",AssemblyStruct[ii].build);
Console.WriteLine("RevisionNumber {0}",AssemblyStruct[ii].revision);
Console.WriteLine("Flags {0}",AssemblyStruct[ii].flags.ToString());
int uncompressedbyte;
int cb = CorSigUncompressData( blob , AssemblyStruct[ii].publickey , out uncompressedbyte );
cb--;
int count = uncompressedbyte;
Console.WriteLine("Public Key #BLOB[{0}] Count {1}",AssemblyStruct[ii].publickey , count );
for ( int l = 1 ; l <= count ; l++)
{
Console.Write("{0} " , blob[AssemblyStruct[ii].publickey+l+cb].ToString("X"));
}
if ( count != 0 )
Console.WriteLine();
Console.WriteLine("Name:{0}",GetString(AssemblyStruct[ii].name));
Console.WriteLine("Culture:{0}",GetString(AssemblyStruct[ii].culture));
}
}
}
public void DisplayAssemblyRefTable()
{
if ( AssemblyRefStruct != null)
{
Console.WriteLine("\n AssemblyRef Table\n");
for ( int ii = 1 ; ii <= AssemblyRefStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("MajorVersion {0}",AssemblyRefStruct[ii].major );
Console.WriteLine("MinorVersion {0}",AssemblyRefStruct[ii].minor);
Console.WriteLine("BuildNumber {0}",AssemblyRefStruct[ii].build);
Console.WriteLine("RevisionNumber {0}",AssemblyRefStruct[ii].revision);
Console.WriteLine("Flags {0}",AssemblyRefStruct[ii].flags.ToString());
int uncompressedbyte;
int cb = CorSigUncompressData( blob , AssemblyRefStruct[ii].publickey ,
out uncompressedbyte );
cb--;
int count = uncompressedbyte;
Console.WriteLine("Public Key or Token #BLOB[{0}] Count {1}",
AssemblyRefStruct[ii].publickey , count);
for ( int l = 1 ; l <= count ; l++)
{
Console.Write("{0} " , blob[AssemblyRefStruct[ii].publickey+l+cb].ToString("X"));
}
if ( count != 0 )
Console.WriteLine();
Console.WriteLine("Name:{0}",GetString(AssemblyRefStruct[ii].name));
Console.WriteLine("Culture:{0}",GetString(AssemblyRefStruct[ii].culture));
cb = CorSigUncompressData( blob , AssemblyRefStruct[ii].hashvalue , out uncompressedbyte );
cb--;
count = uncompressedbyte;
Console.WriteLine("Hash Value #BLOB[{0}] Count {1} ",
AssemblyRefStruct[ii].hashvalue , count);
for ( int l = 1 ; l <= count ; l++)
{
Console.Write("{0} " , blob[AssemblyRefStruct[ii].hashvalue +l+cb].ToString("X"));
}
if ( count != 0 )
Console.WriteLine();
}
}
}
public void DisplayFileTable()
{
if ( FileStruct != null)
{
Console.WriteLine("\nFile Table\n");
for ( int ii = 1 ; ii <= FileStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Flags {0}" , GetFileAttributes(FileStruct[ii].flags));
Console.WriteLine("Name {0}" , GetString(FileStruct[ii].name));
int uncompressedbyte;
int cb = CorSigUncompressData(blob , FileStruct[ii].index, out uncompressedbyte);
int count = uncompressedbyte;
cb--;
Console.WriteLine("HashValue BLOB[{0}] Count {1}" , FileStruct[ii].index , count);
for ( int l = 1 ; l <= count ; l++)
{
Console.Write("{0} " , blob[FileStruct[ii].index+l+cb]);
}
Console.WriteLine();
}
}
}
public int GetImplementationValue( int a)
{
return a >> 2;
}
public string GetImplementationTable( int a)
{
string s = "";
int tag = a & 0x03;
if ( tag == 0 )
s = s + "File";
if ( tag == 1 )
s = s + "AssemblyRef";
if ( tag == 2 )
s = s + "ExportedType";
return s;
}
public void DisplayExportedTypeTable()
{
if ( ExportedTypeStruct!= null)
{
Console.WriteLine("\nExported Table\n");
for ( int ii = 1 ; ii<=ExportedTypeStruct.Length -1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Flags {0}" , ExportedTypeStruct[ii].flags);
Console.WriteLine("TypeDef TYPEDEF[{0}]...{1}" , ExportedTypeStruct[ii].typedefindex,GetTypeDefTable(ExportedTypeStruct[ii].typedefindex) );
Console.WriteLine("TypeName {0}" , GetString(ExportedTypeStruct[ii].name));
Console.WriteLine("NameSpace {0}" , GetString(ExportedTypeStruct[ii].nspace));
string tablename = GetImplementationTable(ExportedTypeStruct[ii].coded) ;
int ind = GetImplementationValue(ExportedTypeStruct[ii].coded);
Console.WriteLine("Implementation {0}[{1}]...{2} " , tablename, ind,DisplayTable(tablename,ind) );
}
}
}
public int GetManifestResourceValue(int a)
{
return a >> 2;
}
public string GetManifestResourceAttributes(int a)
{
string s="";
if ( (a & 0x007) == 0x007)
s = s + "VisibilityMask ";
if ( (a & 0x001) == 0x001)
s = s + "Public ";
if ( (a & 0x002) == 0x002)
s = s + "Private ";
return s;
}
public string GetManifestResourceTable(int a)
{
string s = "";
short tag = (short)(a & (short)0x03);
if ( tag == 0)
s = s + "File";
if ( tag == 1)
s = s + "AssemblyRef";
if ( tag == 2)
s = s + "ExportedType";
return s;
}
public void DisplayManifestResourceTable()
{
if ( ManifestResourceStruct != null)
{
Console.WriteLine("\nManifest Resource Table\n");
for ( int ii = 1 ; ii <= ManifestResourceStruct.Length-1 ; ii++)
{
Console.WriteLine("Row {0}" , ii);
Console.WriteLine("Offset {0}" , ManifestResourceStruct[ii].offset);
Console.WriteLine("Flags {0}" , GetManifestResourceAttributes(ManifestResourceStruct[ii].flags));
Console.WriteLine("Name {0}" , GetString(ManifestResourceStruct[ii].name));
string tablename = GetManifestResourceTable(ManifestResourceStruct[ii].coded);
int index = GetManifestResourceValue(ManifestResourceStruct[ii].coded);
Console.WriteLine("Implementation: {0}[{1}]...{2}" ,
tablename , index,DisplayTable(tablename,index));
}
}
}
public string GetModuleTable(int index)
{
string s = "";
int ind = ModuleStruct[index].Name;
s = GetString(ind);
return s;
}
public string GetParamTable( int index)
{
string s = "";
int ind = ParamStruct[index].name;
s = GetString(ind);
return s;
}
public string GetMemberRefTable( int index)
{
string s = "";
int ind = MemberRefStruct[index].name;
s = GetString(ind);
return s;
}
public string GetFileTable( int index)
{
string s = "";
int ind = FileStruct[index].name;
s = GetString(ind);
return s;
}
public string DisplayTable( string tablename , int index)
{
string s = "";
if ( index == 0)
return s;
if ( tablename == "Module")
s = GetModuleTable(index);
if ( tablename == "TypeRef")
s = GetTypeRefTable(index);
if ( tablename == "TypeDef")
s = GetTypeDefTable(index);
if ( tablename == "Field")
s = GetFieldTable(index);
if ( tablename == "MethodDef")
s = GetMethodTable(index);
if ( tablename == "Param")
s = GetParamTable(index);
if ( tablename == "MethodRef")
s = GetMemberRefTable(index);
if ( tablename == "AssemblyRef")
s = GetAssemblyRefTable(index);
if ( tablename == "Assembly")
s = GetAssemblyTable(index);
if ( tablename == "ModuleRef")
s = GetModuleRefTable(index);
if ( tablename == "File")
s = GetFileTable(index);
if ( tablename == "Property")
s = GetPropertyTable(index);
if ( tablename == "Event")
s = GetEventTable(index);
return s;
}
public void DisplayMethodSignature(int index1 , int row)
{
if ( !(index1 >= 0 && index1 < blob.Length) )
return;
int cb,uncompressedbyte , count;
cb = CorSigUncompressData(blob , index1 , out uncompressedbyte);
count = uncompressedbyte;
byte [] b = new byte[count];
Array.Copy(blob , index1 + cb , b , 0 , count);
if ( b[2] == 0x20 )
return ; // modopt not implemented
if ( b[2] == 0x1B)
return ;// Pointer To function not implemented
int index = 0;
cb = CorSigUncompressData(b , index , out uncompressedbyte);
index++;
cb = CorSigUncompressData(b , index , out uncompressedbyte);
count = uncompressedbyte;
index = index + cb;
string ss11 = "";
ss11 = GetElemType( index,b,out cb) + " " + ss11;
Console.Write(ss11 + " " + GetString(MethodStruct[row].name) + "(");
index = index + cb;
int paramindex = MethodStruct[row].param;
string ss = "" , s1;
string ss2 = "";
int emptyparam = 0;
if ( ParamStruct != null && paramindex < ParamStruct.Length &&
ParamStruct[paramindex].sequence == 0)
emptyparam++;
for ( int l = 1 ; l <= count ; l++)
{
if ( b[index] == 0x2d)
break;
s1 = GetElemType(index,b,out cb);
while ( s1[0] == '[' && s1[1] == ']' )
{
string ss1 = s1.Substring(2);
ss1 = ss1 + "[]";
s1 = ss1;
}
index = index + cb;
ss2 = ss2 + s1 ;
if (l != count)
ss2 = ss2 + ",";
int ind = paramindex + l + emptyparam - 1;
ss = ss + s1 + " " + GetString(ParamStruct[ind].name) ;
if ( l != count)
ss = ss + " , " ;
}
Console.Write(ss + ")");
Console.WriteLine();
Console.WriteLine();
}
public void DisplayTableForDebugging ()
{
DisplayModuleTable();
DisplayTypeRefTable();
DisplayTypeDefTable();
DisplayNestedClassTable();
DisplayFieldTable();
DisplayMethodTable();
DisplayParamTable();
DisplayInterfaceImplTable();
DisplayMemberRefTable();
DisplayConstantTable();
DisplayCustomAttributeTable();
DisplayFieldMarshalTable();
DisplayDeclSecurityTable();
DisplayClassLayoutTable();
DisplayFieldLayoutTable();
DisplayStandAloneSigTable();
DisplayEventMapTable();
DisplayEventTable();
DisplayPropertyMapTable();
DisplayPropertiesTable();
DisplayMethodSemanticsTable();
DisplayMethodImpTable();
DisplayModuleRefTable();
DisplayTypeSpecTableTable();
DisplayImplMapTable();
DisplayFieldRVATable();
DisplayAssemblyTable();
DisplayAssemblyRefTable();
DisplayFileTable();
DisplayExportedTypeTable();
DisplayManifestResourceTable();
}
}
Output
// Microsoft (R) .NET Framework IL Disassembler. Version 1.0.3705.0
// Copyright (C) Microsoft Corporation 1998-2001. All rights reserved.
// PE Header:
// Subsystem: 00000003
// Native entry point address: 00002c7e
// Image base: 00400000
// Section alignment: 00002000
// File alignment: 00000200
// Stack reserve size: 00100000
// Stack commit size: 00001000
// Directories: 00000010
// 0 [0 ] address [size] of Export Directory:
// 2c2c [4f ] address [size] of Import Directory:
// 4000 [318 ] address [size] of Resource Directory:
// 0 [0 ] address [size] of Exception Directory:
// 0 [0 ] address [size] of Security Directory:
// 6000 [c ] address [size] of Base Relocation Table:
// 0 [0 ] address [size] of Debug Directory:
// 0 [0 ] address [size] of Architecture Specific:
// 0 [0 ] address [size] of Global Pointer:
// 0 [0 ] address [size] of TLS Directory:
// 0 [0 ] address [size] of Load Config Directory:
// 0 [0 ] address [size] of Bound Import Directory:
// 2000 [8 ] address [size] of Import Address Table:
// 0 [0 ] address [size] of Delay Load IAT:
// 2008 [48 ] address [size] of CLR Header:
// Import Address Table
// mscoree.dll
// 00002000 Import Address Table
// 00002c6e Import Name Table
// 0 time date stamp
// 0 Index of first forwarder reference
//
//
// Delay Load Import Address Table
// No data.
// CLR Header:
// 72 Header Size
// 2 Major Runtime Version
// 0 Minor Runtime Version
// 1 Flags
// 6000006 Entrypoint Token
// 22d4 [958 ] address [size] of Metadata Directory:
// 2174 [15f ] address [size] of Resources Directory:
// 0 [0 ] address [size] of Strong Name Signature:
// 0 [0 ] address [size] of CodeManager Table:
// 0 [0 ] address [size] of VTableFixups Directory:
// 0 [0 ] address [size] of Export Address Table:
// 0 [0 ] address [size] of Precompile Header:
// Code Manager Table:
// default
Metadata Details
Start of Metadata 8916 rva=1236
Length of String 12
No of streams 5 Position=1268
Stream Details
offset=108 size=928 Position=1276
offset=1036 size=500 Position=1288
offset=1536 size=40 Position=1308
offset=1576 size=16 Position=1320
offset=1592 size=800 Position=1336
Strings Stream
<Module>
b.exe
mscorlib
System
Object
zzz
iii
yyy
uuu
a1
j
i
EventHandler
a
add_a
remove_a
b
add_b
remove_b
MessageBox
Main
abc
pqr
xyz
.ctor
xxx
set_aa
get_aa
set_bb
get_bb
iii.xxx
aaa
aa
bb
System.Security.Permissions
SecurityPermissionAttribute
SecurityAction
System.Diagnostics
DebuggableAttribute
value
Delegate
Combine
Remove
System.Runtime.InteropServices
DllImportAttribute
user32.dll
hWnd
text
caption
type
Int32
Console
WriteLine
k
System.Security
UnverifiableCodeAttribute
a.resources
US Stream
hell {0}
hi
hello
GUID Stream
{A7CC9DDA-703D-4946-8C4C-DE78659FDC3}
Stream offset and stream size
#~...offset: 108 size:928
#Strings...offset: 1036 size:500
#US...offset: 1536 size:40
#GUID...offset: 1576 size:16
#Blob...offset: 1592 size:800
Number of Rows in the tables:
NestedClass : 1
ManifestResource : 1
AssemblyRef : 1
Assembly : 1
ImplMap : 1
ModuleRef : 1
MethodImpl : 1
MethodSemantics : 8
Properties : 2
PropertyMap : 1
Event : 2
EventMap : 1
StandAloneSig : 3
DeclSecurity : 1
CustomAttribute : 2
Constant : 1
MemberRef : 9
InterfaceImpl : 1
Param : 15
Method : 21
Field : 4
TypeDef : 6
TypeRef : 10
Module : 1
Table Details
Module Table Offset 120 Size 10
TypeRef Table Offset 130 Size 6
TypeDef Table Offset 190 Size 14
Field Table Offset 274 Size 6
Method Table Offset 298 Size 14
Param Table Offset 592 Size 6
InterfaceImpl Table Offset 682 Size 4
MemberRef Table Offset 686 Size 6
Constant Table Offset 740 Size 6
CustomAttribute Table Offset 746 Size 6
FieldMarshal Table Offset 758
DeclSecurity Table Offset 758
ClassLayout Table Offset 764
FieldLayout Table Offset 764
StandAloneSig Table Offset 764
EventMap Table Offset 770
Event Table Offset 774
PropertyMap Table Offset 786
Property Table Offset 790
MethodSemantics Table Offset 802
MethodImpl Table Offset 850
ModuleRef Table Offset 856
TypeSpec Table Offset 858 size=0
ImplMap Table Offset offs=858 rows=1 len=928
FieldRVA Table Offset 866
Assembly Table Offset 866
AssembleyRef Table Offset 888
File Table Offset 908
ExportedType Table Offset 908
ManifestResource Table Offset 908
Nested Classes Offset 920
Module Table
Generation: 0
Name :b.exe A
Mvid :#GUID[1]
EncId :#GUID[0]
EncBaseId :#GUID[0]
TypeRef Table
Row[1]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :Object
Namespace :System
Row[2]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :EventHandler
Namespace :System
Row[3]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :SecurityPermissionAttribute
Namespace :System.Security.Permissions
Row[4]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :SecurityAction
Namespace :System.Security.Permissions
Row[5]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :DebuggableAttribute
Namespace :System.Diagnostics
Row[6]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :Delegate
Namespace :System
Row[7]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :DllImportAttribute
Namespace :System.Runtime.InteropServices
Row[8]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :Int32
Namespace :System
Row[9]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :Console
Namespace :System
Row[10]
ResolutionScope:AssemblyRef[1]...mscorlib
Name :UnverifiableCodeAttribute
Namespace :System.Security
TypeDefTable
Row:1
Flags : Class
Name : <Module>
NameSpace :
Extends: TypeDef[0].....
FieldList Field[1]
MethodList Method[1]
Number Of Methods 0
Number Of Fields 0
Row:2
Flags : AutoLayout, AnsiClass, NotPublic, Public, BeforeFieldInit
Name : zzz
NameSpace :
Extends: TypeRef[1].....System.Object
FieldList Field[1]
MethodList Method[1]
Number Of Methods 10
1. add_a
2. remove_a
3. add_b
4. remove_b
5. MessageBox
6. Main
7. abc
8. pqr
9. xyz
10. .ctor
Number Of Fields 4
1. j
2. i
3. a
4. b
Number of Events 2
1. a
2. b
Row:3
Flags : AutoLayout, AnsiClass, NotPublic, ClassSemanticsMask, Abstract
Name : iii
NameSpace :
Extends: TypeDef[0].....
FieldList Field[5]
MethodList Method[11]
Number Of Methods 1
11. xxx
Number Of Fields 0
Row:4
Flags : AutoLayout, AnsiClass, NotPublic, Public, BeforeFieldInit
Name : yyy
NameSpace :
Extends: TypeRef[1].....System.Object
FieldList Field[5]
MethodList Method[12]
Number Of Methods 8
12. set_aa
13. get_aa
14. set_bb
15. get_bb
16. uuu
17. iii.xxx
18. aaa
19. .ctor
Number Of Fields 0
Number of Properties 2
1. aa
2. bb
Row:5
Flags : AutoLayout, AnsiClass, NotPublic, Public, BeforeFieldInit
Name : uuu
NameSpace :
Extends: TypeDef[4].....Class yyy Extends System.Object
FieldList Field[5]
MethodList Method[20]
Number Of Methods 1
20. .ctor
Number Of Fields 0
Row:6
Flags : AutoLayout, AnsiClass, NotPublic, NestedPrivate, BeforeFieldInit
Name : a1
NameSpace :
Extends: TypeRef[1].....System.Object
FieldList Field[5]
MethodList Method[21]
Number Of Methods 1
21. .ctor
Number Of Fields 0
Nested Classes Table
Row 1
Nested Class TypeDef[6]...Class a1 Extends System.Object
Enclosing Class TypeDef[5]...Class uuu
FieldTable
Row 1
Flags: -32687
Name : j
count 2 index 10
Signature BLOB[10]...6 8 ..int32
Row 2
Flags: 17
Name : i
count 2 index 10
Signature BLOB[10]...6 8 ..int32
Row 3
Flags: 1
Name : a
count 3 index 18
Signature BLOB[18]...6 18 9 ..class
Row 4
Flags: 1
Name : b
count 3 index 18
Signature BLOB[18]...6 18 9 ..class
Method Table
Row :1
RVA :2050
ImpFlags :Synchronized
Flags :2182
Name : add_a
Signature: #Blob[22]
ParamList: Param[1]
Number Of Params 1
1. value
void add_a(class EventHandler value)
Row :2
RVA :2069
ImpFlags :Synchronized
Flags :2182
Name : remove_a
Signature: #Blob[22]
ParamList: Param[2]
Number Of Params 1
2. value
void remove_a(class EventHandler value)
Row :3
RVA :2082
ImpFlags :Synchronized
Flags :2182
Name : add_b
Signature: #Blob[22]
ParamList: Param[3]
Number Of Params 1
3. value
void add_b(class EventHandler value)
Row :4
RVA :209B
ImpFlags :Synchronized
Flags :2182
Name : remove_b
Signature: #Blob[22]
ParamList: Param[4]
Number Of Params 1
4. value
void remove_b(class EventHandler value)
Row :5
RVA :0
ImpFlags :PreserveSig
Flags :8342
Name : MessageBox
Signature: #Blob[28]
ParamList: Param[5]
Number Of Params 4
5. hWnd
6. text
7. caption
8. type
int32 MessageBox(int32 hWnd , string text , string caption , unsigned int32 type)
Row :6
RVA :20B4
ImpFlags :Managed
Flags :150
Name : Main
Signature: #Blob[36]
ParamList: Param[9]
Number Of Params 0
void Main()
Row :7
RVA :20D4
ImpFlags :Managed
Flags :134
Name : abc
Signature: #Blob[40]
ParamList: Param[9]
Number Of Params 1
9. k
int32 abc(float32 k)
Row :8
RVA :20E8
ImpFlags :Managed
Flags :134
Name : pqr
Signature: #Blob[45]
ParamList: Param[10]
Number Of Params 2
10. i
11. j
int64 pqr(int32[] i , char j)
Row :9
RVA :20FB
ImpFlags :Managed
Flags :134
Name : xyz
Signature: #Blob[52]
ParamList: Param[12]
Number Of Params 0
void xyz()
Row :10
RVA :20FD
ImpFlags :Managed
Flags :6278
Name : .ctor
Signature: #Blob[52]
ParamList: Param[12]
Number Of Params 0
void .ctor()
Row :11
RVA :0
ImpFlags :Managed
Flags :1478
Name : xxx
Signature: #Blob[52]
ParamList: Param[12]
Number Of Params 0
void xxx()
Row :12
RVA :2105
ImpFlags :Managed
Flags :2182
Name : set_aa
Signature: #Blob[56]
ParamList: Param[12]
Number Of Params 1
12. value
void set_aa(int32 value)
Row :13
RVA :2108
ImpFlags :Managed
Flags :2182
Name : get_aa
Signature: #Blob[61]
ParamList: Param[13]
Number Of Params 0
int32 get_aa()
Row :14
RVA :211B
ImpFlags :Managed
Flags :2182
Name : set_bb
Signature: #Blob[65]
ParamList: Param[13]
Number Of Params 1
13. value
void set_bb(string value)
Row :15
RVA :2120
ImpFlags :Managed
Flags :2182
Name : get_bb
Signature: #Blob[70]
ParamList: Param[14]
Number Of Params 0
string get_bb()
Row :16
RVA :2138
ImpFlags :Managed
Flags :134
Name : uuu
Signature: #Blob[74]
ParamList: Param[14]
Number Of Params 2
14. i
15. j
int64 uuu(int32 i , char[] j)
Row :17
RVA :214B
ImpFlags :Managed
Flags :481
Name : iii.xxx
Signature: #Blob[52]
ParamList: Param[16]
Number Of Params 0
void iii.xxx()
Row :18
RVA :2157
ImpFlags :Managed
Flags :134
Name : aaa
Signature: #Blob[52]
ParamList: Param[16]
Number Of Params 0
void aaa()
Row :19
RVA :2159
ImpFlags :Managed
Flags :6278
Name : .ctor
Signature: #Blob[52]
ParamList: Param[16]
Number Of Params 0
void .ctor()
Row :20
RVA :2161
ImpFlags :Managed
Flags :6278
Name : .ctor
Signature: #Blob[52]
ParamList: Param[16]
Number Of Params 0
void .ctor()
Row :21
RVA :2169
ImpFlags :Managed
Flags :6278
Name : .ctor
Signature: #Blob[52]
ParamList: Param[16]
Number Of Params 0
void .ctor()
Param Table
Row 1
ParamAttributes None Bytes 0
Sequence 1
Name value
Row 2
ParamAttributes None Bytes 0
Sequence 1
Name value
Row 3
ParamAttributes None Bytes 0
Sequence 1
Name value
Row 4
ParamAttributes None Bytes 0
Sequence 1
Name value
Row 5
ParamAttributes None Bytes 0
Sequence 1
Name hWnd
Row 6
ParamAttributes None Bytes 0
Sequence 2
Name text
Row 7
ParamAttributes None Bytes 0
Sequence 3
Name caption
Row 8
ParamAttributes None Bytes 0
Sequence 4
Name type
Row 9
ParamAttributes None Bytes 0
Sequence 1
Name k
Row 10
ParamAttributes None Bytes 0
Sequence 1
Name i
Row 11
ParamAttributes None Bytes 0
Sequence 2
Name j
Row 12
ParamAttributes None Bytes 0
Sequence 1
Name value
Row 13
ParamAttributes None Bytes 0
Sequence 1
Name value
Row 14
ParamAttributes None Bytes 0
Sequence 1
Name i
Row 15
ParamAttributes None Bytes 0
Sequence 2
Name j
InterfaceImpl Table
Row 1
Class TypeDef[4]...Class yyy Extends System.Object
Interface TypeDef[3] Class iii
MemberRef Table
Row 1
TypeRef[3]:System.Security.Permissions.SecurityPermissionAttribute
Name:.ctor
Signature #BLOB[89]
Row 2
TypeRef[5]:System.Diagnostics.DebuggableAttribute
Name:.ctor
Signature #BLOB[95]
Row 3
TypeRef[6]:System.Delegate
Name:Combine
Signature #BLOB[101]
Row 4
TypeRef[6]:System.Delegate
Name:Remove
Signature #BLOB[101]
Row 5
TypeRef[7]:System.Runtime.InteropServices.DllImportAttribute
Name:.ctor
Signature #BLOB[65]
Row 6
TypeRef[9]:System.Console
Name:WriteLine
Signature #BLOB[110]
Row 7
TypeRef[1]:System.Object
Name:.ctor
Signature #BLOB[52]
Row 8
TypeRef[9]:System.Console
Name:WriteLine
Signature #BLOB[128]
Row 9
TypeRef[10]:System.Security.UnverifiableCodeAttribute
Name:.ctor
Signature #BLOB[52]
Constant Table
Row 1
Type int32
Parent: FieldDef[1] Name of Constant... j
Blob BLOB[13] Count 4 2 0 0 0 Value 2
CustomAttribute Table
Row [1]
Parent: Module[1]...b.exe
Type: MethodRef[9]....ctor
Value Blob[133] Count 4 Bytes 1 0 0 0
Row [2]
Parent: Assembly[1]...b
Type: MethodRef[2]....ctor
Value Blob[138] Count 6 Bytes 1 0 0 1 0 0
DeclSecurity Table
Row 1
Action 8
Parent: Assembly[1]... b
Permission Set BLOB[147] Count=652
< P e r m i s s i o n S e t c l a s s = " S y s t e m . S e c u r i t y . P e r m i s s i o n S e t "
v e r s i o n = " 1 " >
< I P e r m i s s i o n c l a s s = " S y s t e m . S e c u r i t y . P e r m i s s i o n s . S e c u r i t y P e r m i s s i o n , m s c o r l i b , V e r s i o n = 1 . 0 . 3 3 0 0 . 0 , C u l t u r e = n e u t r a l , P u b l i c K e y T o k e n = b 7 7 a 5 c 5 6 1 9 3 4 e 0 8 9 "
v e r s i o n = " 1 "
F l a g s = " S k i p V e r i f i c a t i o n " / >
< / P e r m i s s i o n S e t >
StandAloneSig Table
Row 1
Signature BLOB[116] Count 3 7 1 8
Row 2
Signature BLOB[120] Count 3 7 1 10
Row 3
Signature BLOB[124] Count 3 7 1 14
EventMap Table
Row 1
Parent TypeDef[2]...Class zzz Extends System.Object
EventList Event[1]...Event a System.EventHandler
Event Table
Row 1
Event Flags: None
Name: a
Event Type:TypeRef[2]... System.EventHandler
Row 2
Event Flags: None
Name: b
Event Type:TypeRef[2]... System.EventHandler
Property Map Table
Row 1
Parent TypeDef[4]...Class yyy Extends System.Object
PropertyList Property[1]...aa
Properties Table
Row 1
Flags [0]
Name aa
Type BLOB[81]...3 40 0 8
Row 2
Flags [0]
Name bb
Type BLOB[85]...3 40 0 14
MethodSemantics Table
Row 1
Semantics Event Remove
Method Method[2]...remove_a
Association:Event[1]...Event a System.EventHandler
Row 2
Semantics Event Addon
Method Method[1]...add_a
Association:Event[1]...Event a System.EventHandler
Row 3
Semantics Setter
Method Method[12]...set_aa
Association:Property[1]...aa
Row 4
Semantics Getter
Method Method[13]...get_aa
Association:Property[1]...aa
Row 5
Semantics Event Remove
Method Method[4]...remove_b
Association:Event[2]...Event b System.EventHandler
Row 6
Semantics Event Addon
Method Method[3]...add_b
Association:Event[2]...Event b System.EventHandler
Row 7
Semantics Getter
Method Method[15]...get_bb
Association:Property[2]...bb
Row 8
Semantics Setter
Method Method[14]...set_bb
Association:Property[2]...bb
MethodImp Table
Row 1
Class TypeDef[4]...Class yyy Extends System.Object
MethodBody MethodDef[17]...iii.xxx
MethodDeclaration MethodDef[11]...xxx
ModuleRef Table
Row 1
Name user32.dll
ImplMap Table
Row 1
Mapping Flags :CharSetNotSpec CallConvWinapi
MemberForwarded:MethodDef[5]...MessageBox
Name :MessageBox
Import Scope :ModuleRef[1] user32.dll
Assembly Table
Row 1
HashAlgId 32772
MajorVersion 0
MinorVersion 0
BuildNumber 0
RevisionNumber 0
Flags 0
Public Key #BLOB[0] Count 0
Name:b
Culture:
AssemblyRef Table
Row 1
MajorVersion 1
MinorVersion 0
BuildNumber 3300
RevisionNumber 0
Flags 0
Public Key or Token #BLOB[1] Count 8
B7 7A 5C 56 19 34 E0 89
Name:mscorlib
Culture:
Hash Value #BLOB[0] Count 0
Manifest Resource Table
Row 1
Offset 0
Flags Public
Name a.resources
Implementation: File[0]...
The Main function in the zzz class calls the abc function, which launches forthwith the task of displaying information from the metadata table, by calling other functions.
public void abc(string [] args)
{
InitializeObjects(args);
ReadPEStructures();
DisplayPEStructures();
ImportAdressTable();
CLRHeader();
ReadStreamsData();
FillTableSizes();
ReadTablesIntoStructures();
DisplayTableForDebugging();
}
The first function to be called is InitializeObject.
public void InitializeObjects(string [] args) {
tablenames = new String[]{"Module" , "TypeRef" , "TypeDef" ,"FieldPtr","Field", "MethodPtr","Method","ParamPtr" , "Param", "InterfaceImpl", "MemberRef", "Constant", "CustomAttribute", "FieldMarshal", "DeclSecurity", "ClassLayout", "FieldLayout", "StandAloneSig" , "EventMap","EventPtr", "Event", "PropertyMap", "PropertyPtr", “Properties","MethodSemantics",
"MethodImpl","ModuleRef","TypeSpec","ImplMap","FieldRVA","ENCLog","ENCMap",
"Assembly","AssemblyProcessor","AssemblyOS","AssemblyRef",
"AssemblyRefProcessor","AssemblyRefOS","File","ExportedType",
"ManifestResource","NestedClass","TypeTyPar","MethodTyPar"};
if ( args.Length == 0)
filename = "C:\\mdata\\b.exe";
else
filename = args[0];
}
This function verifies if the executable has been called with any command line arguments or not. If the executable has been called with a single argument, i.e. >a mscorlib.dll, the 0th member becomes the first argument, i.e. mscorlib.dll and the length member becomes a non-zero number. In the case where command line arguments have not been supplied, the file named b.exe gets scrutinized by default. We have tried and tested this program with mscorlib.dll, and with various other dlls that are furnished together with the .Net framework. You may disassemble the main program to authenticate whether the output relates to the program file or not. Just make a copy of a.exe as bb.exe, and then, run the program as
>a bb.exe
Every metadata table is identified by a name and an id. The first table has an id of 0 and the name of 'module'. Similarly, the second table has an id of 1 and the name of 'TypeDef'. There are a total of 43 such defined tables. However, in the IL disassembled mode, the name is not stored anywhere, since the table is referenced by its id. So, in order to display a readable output, we have stored the tables' names in an array, where the offset in the array can be regarded as the id.
We start deciphering the file contents from the next function named ReadPEStructures. The PE file header is read first, followed by the Image Optional Header. The virtual address, size of rawdata and pointer to rawdata, are all stored in separate arrays.
The function DisplayPEStructures displays the output as emitted by the Microsoft ILDASM program utility. Also, the functions of ImportAddressTable and DisplayFromFile facilitate the display of the output as depicted by the utility.
The Data Directory renders information about where the Directories begin, i.e. its Relative Virtual Address (RVA) and the size. An RVA is a memory location. However, since the file is read from the disk and is not loaded into the memory, the disk locations of these directories need to be ascertained. The DisplayDataDirectory function prints out these details in a proper format for every directory.
The second last data directory member, i.e. CLR header, is a recipient of special treatment, since it forms the very foundation of the metadata information. The CLRHeader function details every aspect of the header.
The PE file format has a sections table, which is a series of structures containing variegated information about data code, etc. It also stores the starting locations of these sections in both, the memory and on the disk, together with the size of each section. The ConvertRVA function determines the actual disk location of a section whose memory location has been provided.
The metadata header is read into different variables and then, these details are displayed using the WriteLine function.
The next function to be called in the abc function is ReadStreamsData(). It is very similar to what we have observed in the earlier chapters. The lone dissimilarity is that, the variable startofmetadata has been initialized using the ConvertRVA function. The filepointer is then positioned at the startofmetadata in memory, by using the Position property in the stream. A vital point to be taken into account is that, everything in the .Net world is aligned at 4.
In the .Net world, the metadata tables are stored as offsets or indexes in the streams of String, GUID or Blob. The question that crops up now is, whether these indexes should take up 2 bytes or 4 bytes. The answer depends entirely on the stream sizes.
If the stream size is upto 64K, then the index field takes up 2 byes. However, if it exceeds 64K, then the index takes up 4 bytes. The designers of metadata could have stringently fixed it at 4 bytes, but they were quick to realize that this approach would result in excessive wastage of space. Thus, it is amply evident that the metadata concept has been primarily designed for efficiency.
Five arrays have been created for the five streams. Then, the data contained within the streams is stored within them. Thereafter, the details of the streams, barring the #~ stream, are printed out.
The 6th byte from the start of the metadata header is a byte called heapsize. Out of the 8 bits, 3 bits are inspected to ascertain the size of the index. If the first bit is on, the string size is larger than 64 K, and therefore, the offsetstring variable is set to 4.
if ( (heapsizes & 0x01) == 0x01)
offsetstring = 4;
Similarly, the second and the third bits are checked, and if these bits are on, the variables of offsetguid and offsetblob are assigned a value of 4 each, respectively.
if ( (heapsizes & 0x02) == 0x02)
offsetguid = 4;
if ( (heapsizes & 0x04) == 0x04)
offsetblob = 4;
By default, the three variables of offsetstring, offsetguid and offsetblob are initialized to a value of 3. Thereafter, to eschew any further complications, the functions of ReadStringIndex, ReadGuidIndex and ReadBlobIndex determine the values of the offset variables offsetstring, offsetguid and offsetblob, respectively; it is done whenever indexes are to be read off the stream. If the value is set to 2, the Int16 converter is used, however if it is 4, the converter of Int32 is employed.
All the earlier programs in this book had utilized small program snippets. As a consequence, the values never exceeded 64 K. Therefore, we had worked under the assumption that the value is 2 bytes.
An index into a table may also be either 2 bytes or 4 bytes. However, we have set the value to 2, assuming that the tablesizes, i.e. the rows in the tables, shall never exceed 64K.
public int GetTableSize()
{
return 2;
}
The apposite approach here would be to ascertain if the rows exceed 64K in the rows array; and based on the value, either 2 or 4 shall be returned.
As perceived in the earlier programs, before the function ReadStreamsData terminates, the tables in the valid field are inspected, and simultaneously, the number of rows that it contains is placed in the rows array.
Once the rows size array is filled up, the size of every table is checked to fill up the sizes array. The most imperative function here is the GetCodedIndexSize function. Let us consider a specific case where the tablesize of the typeref table is to be ascertained. The function of GetCodedIndexSize("ResolutionScope") is called to establish whether the size of the field is 2 bytes or 4 bytes.
Thus, the GetCodedIndexSize function gets called, and the 'if' statement that checks for the ReolutionScope, returns True. Then, the following statements get executed:
if ( rows[0x00]>= 8192 || rows[0x1a] >= 8192 || rows[0x23] >= 8192 || rows[0x01] >= 8192 )
return 4;
else
return 2;
For those with an evasive memory, the resolutionscope is an index into one of the 4 tables, i.e. Module, ModuleRef, AssemblyRef or TypeRef, having the id of 0x00, 0x1a, 0x23 and 0x01, respectively. In one of the earlier chapters, we had observed that if the three bits held the value of 0, it referred to the module table. A value of 1 was for moduleref, 3 was for assemblyref and 4 was for typeref. In the GetCodedIndexSize function, the rows in these three tables are verified to establish if they exceed 8192, i.e. 2^13, since the remaining 3 bits of 2 bytes are occupied by the table references. If they do, the resolutionscope takes up 4 bytes, or else, it occupies 2 bytes.
In brief, GetCodedIndexSize takes a string parameter, which is the name of the coded index. It uses the rows array to determine if the rows for the table exceed the 2 byte limit. This is accomplished by subtracting the bits that have been utilized for the table. If this is the case, then 4 bytes are used for accommodating the resolutionscope.
The sizes of these tables are never constant. If the rows expand in size, then the number of bytes that are consumed to accommodate these, also undergoes expansion. For the MemberRef table, out of the 3 fields, the first one is the coded index, the second is an index to the string, while the third one is an index into the Blob. In case of the table being small, the fields can be assumed to have a size of 2 bytes each, thus resulting in a total size of 6 bytes. However, this assumption is far from being technically accurate. Thus, GetCodedIndexSize dynamically assigns the size for the coded index field in the tables.
The computed sizes of these tables are stored in the sizes array. Thus, to retrieve the size of the MemberRef table, you can merely use size[0x0a].
The tablepresent function computes the offset of every table and stores it in the variable tableoffset. It returns a boolean value of True, if the table is present in the metadata stream; however, in case of its absence, it returns a value of False.
This nugget of information is exploited in the next function named ReadTablesIntoStructures. If the table exists, an array of structures is created, which is large enough to store all the rows in the table. We have appended an additional structure to the quantity in existence, since we would be ignoring the 0th member in the array and shall be starting the array index from 1. Every member in the structure is then filled up for the entire array. This has been repeated for all the tables.
Once the structures are filled up, the function of DisplayTableForDebugging() is called, which displays the information stored in every table of the file.
We have already explicated each one of the tables in great detail earlier. The only divergence here is that, the cross references to several tables are specified in values, along with other relevant information. For example, the function of DisplayTypeDefTable generates a lot more information, as compared to what we had encountered earlier.
The DisplayTable function called in this function, returns intelligent information. It takes two parameters, viz. the tablename and the index. Let us consider the case of class zzz, which is the second row in the typedef table. The function DisplayTable is called with the table name of TypeRef and with an index of 1. Since the table is TypeRef, the function GetTypeRefTable is called with the index parameter.
In GetTypeRefTable, the value in the name field is extracted from the typeref structure, with the index variable comporting itself as the row number. Moreover, the namespace is also retrieved. If the namespace is not null, then a dot is specified after the namespace name.
Finally, using the GetString function, the actual name is obtained, which is then specified as the return value. Thus, in place of TypeRef[1], we see the value of System.Object.
Apart from this, all the methods contained in the class are also displayed, using the DisplayAllMethods function. This function is passed the rowindex member named ii, as the parameter. The mindex member of the structure provides the starting method index owned by the type. Thus, we have stored it in the variable named 'start'. However, there is no technique of ascertaining the last method owned by the type. Yet again, the ease of understanding has been sacrificed at the altar of efficiency.
In order to obtain the last method, the next typedef member is checked. The function pointed by this typedef, marks the new set of functions owned by the next type. Thus, it can be safely concluded that all functions preceding the new set, are owned by the current type. The difference between startofnext and start belong to the current type. Then, by employing a 'for' loop, all the methods falling within the range are displayed.
A small glitch rears its head, if the type happens to be the last type in the typedeftable.
In such a case, the startofnext variable is initialized to the length of the methodstruct -1. So, when the index in the typedef table corresponds to the last entry in the table, all methods from the start upto the end of methods in the method table, are assigned to the type. Moreover, when two types share the same start, it is assumed that the current typedef does not enclose any methods in it.
The same rules have been applied while displaying all fields, events, parameters and properties.
We have chosen to abstain from explicating any more code, since a large quantum of it has already been elucidated in the preceding chapters in diminutive bits and pieces. However, there are a few things that have been left unfinished, such as complex types, which have not been attended to; and signatures, which have not been decoded in their entirety.
We set aside these as an exercise for you, since these have already been expounded in considerable detail in the earlier chapters. One can synthesize all this knowledge and write a thesis on the subject with effortless ease. However, we are going to save you this effort, since our next book shall cater to all these requests with a re-production of Microsoft's IL disassembler utility, using the C# language. It shall incorporate all the formatting issues too. Au revoir!