Esempio n. 1
0
        private void InitEntryType()
        {
            var c          = peFile.ClrHeader.EntryPointToken;
            var entryPoint = c & 0xFF;

            if (entryPoint == 0)
            {
                //No entry point
                entryType   = null;
                entryMethod = null;
                return;
            }

            foreach (var item in Types)
            {
                foreach (var m2 in item.Methods)
                {
                    if (m2.BackendTabel == peFile.Tabels.MethodTabel[(int)entryPoint - 1])
                    {
                        entryType   = m2.Parent;
                        entryMethod = m2;
                        break;
                    }
                }
            }
        }
Esempio n. 2
0
        public IlDecompiler(DotNetMethod method)
        {
            if (method == null)
            {
                throw new ArgumentException("method");
            }

            m        = method;
            mainFile = m.File;
            code     = m.GetBody();
            AddReference(m.Parent.File);
        }
Esempio n. 3
0
        /// <summary>
        /// Calls the entrypoint in the file.
        /// </summary>
        public void Start()
        {
            DotNetMethod m = null;

            foreach (var item in file.Types)
            {
                foreach (var m2 in item.Methods)
                {
                    if (m2.IsStatic && m2.Name == "Main")
                    {
                        m = m2;
                        break;
                    }
                }
            }
            if (m == null)
            {
                throw new System.Exception("Invaild .NET EXE: Entry Point not found!");
            }
            ProcessMethod(m, "Arg 1", "Arg 2");
        }
Esempio n. 4
0
        public ILInstruction GetInstructionAtOffset(int Offset, int relPostion)
        {
            byte opCodeb = code[Offset];
            var  opCode  = OpCodes.SingleOpCodes[opCodeb];

            int size = 0;

            if (opCodeb == 0xFE)
            {
                opCodeb = code[Offset + 1];
                opCode  = OpCodes.MultiOpCodes[opCodeb];
                Offset++;
                size++;
            }
            if (opCode == null)
            {
                Console.WriteLine("ILDecompiler failed decompilation.");
                opCode = OpCodes.SingleOpCodes[0];
            }

            ILInstruction ret = new ILInstruction()
            {
                OpCode = opCode.Value, OpCodeName = opCode.Name, OperandType = opCode.OpCodeOperandType, Position = Offset, RelPosition = relPostion, Size = size
            };

            if (relPostion == -1)
            {
                var arr = Decompile();
                foreach (var item in arr)
                {
                    if (item.Position == Offset)
                    {
                        return(item);
                    }
                }
                throw new Exception("Target instruction not found!");
            }
            //TODO: Implment the rest of these
            switch (opCode.OpCodeOperandType)
            {
            case OpCodeOperandType.InlineNone:
            {
                return(ret);
            }

            case OpCodeOperandType.InlinePhi:
                //Never should be used
                throw new InvalidOperationException();

            case OpCodeOperandType.InlineTok:
            {
                byte   fi     = code[Offset + 1];
                byte   s2     = code[Offset + 2];
                byte   t      = code[Offset + 3];
                byte   Tabel  = code[Offset + 4];
                byte[] num2   = new byte[] { fi, s2, t, 0 };
                var    numb2  = BitConverter.ToInt32(num2, 0);
                var    tabel2 = BitConverter.ToInt32(code, Offset + 1);
                var    tabel  = tabel2 >> 24;


                var info = new FieldInfo();
                info.IndexInTabel = numb2;

                //TODO: fix this as the below if statement maybe incorrect

                if (Tabel == 1)
                {
                    // type ref
                    var typeRef = mainFile.Backend.Tabels.TypeRefTabel[numb2 - 1];

                    info.IsInFieldTabel = false;
                    info.Name           = mainFile.Backend.ClrStringsStream.GetByOffset(typeRef.TypeName);
                    info.Namespace      = mainFile.Backend.ClrStringsStream.GetByOffset(typeRef.TypeNamespace);
                }
                else if (Tabel == 2)
                {
                    //type def
                    var typeRef = mainFile.Backend.Tabels.TypeDefTabel[numb2 - 1];

                    info.IsInFieldTabel = true;
                    info.Name           = mainFile.Backend.ClrStringsStream.GetByOffset(typeRef.Name);
                    info.Namespace      = mainFile.Backend.ClrStringsStream.GetByOffset(typeRef.Namespace);
                }
                else if (Tabel == 0x1B)
                {
                    throw new NotImplementedException();
                }
                else
                {
                    throw new NotImplementedException();
                }

                ret.Size   += 4;
                ret.Operand = info;
                return(ret);
            }

            //8 bit int operand
            case OpCodeOperandType.ShortInlineVar:
            {
                byte fi = code[Offset + 1];
                ret.Size   += 1;
                ret.Operand = fi;
                return(ret);
            }

            case OpCodeOperandType.ShortInlineBrTarget:
            {
                sbyte fi = (sbyte)code[Offset + 1];
                ret.Size   += 1;
                ret.Operand = fi + 1;
                return(ret);
            }

            case OpCodeOperandType.ShortInlineI:
            {
                byte fi = code[Offset + 1];
                ret.Size   += 1;
                ret.Operand = fi;
                return(ret);
            }

            // 16 bit int
            case OpCodeOperandType.InlineVar:
                throw new NotImplementedException();

            // 32 bit int
            case OpCodeOperandType.InlineI:
            {
                var numb2 = BitConverter.ToInt32(code, Offset + 1);

                ret.Size   += 4;
                ret.Operand = numb2;
                return(ret);
            }

            case OpCodeOperandType.InlineBrTarget:
            {
                var numb2 = BitConverter.ToInt32(code, Offset + 1);

                ret.Size   += 4;
                ret.Operand = numb2 + 4;         //add the size
                return(ret);
            }

            case OpCodeOperandType.InlineField:
            {
                byte f     = code[Offset + 4];
                var  numb2 = BitConverter.ToUInt16(code, Offset + 1);

                ret.Size += 4;

                if (f == 4)
                {
                    //Inside of field table
                    var c    = mainFile.Backend.Tabels.FieldTabel[numb2 - 1];
                    var ret2 = new FieldInfo()
                    {
                        Name = mainFile.Backend.ClrStringsStream.GetByOffset(c.Name), IsInFieldTabel = true, IndexInTabel = numb2
                    };


                    ret.Operand = ret2;
                }
                else if (f == 10)
                {
                    //Inside of MemberRef table
                    var c = mainFile.Backend.Tabels.MemberRefTabelRow[numb2 - 1];

                    var ret2 = new FieldInfo()
                    {
                        Name = mainFile.Backend.ClrStringsStream.GetByOffset(c.Name), IsInFieldTabel = true, IndexInTabel = numb2
                    };

                    DecodeMemberRefParent(c.Class, out MemberRefParentType type, out uint row2);
                    if (type == MemberRefParentType.TypeSpec)
                    {           //Method spec
                        var tt = mainFile.Backend.Tabels.TypeSpecTabel[(int)(row2 - 1)];

                        //See https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/metadata/corelementtype-enumeration for more info
                        var b  = mainFile.Backend.BlobStream[tt.Signature];
                        var bi = new BinaryReader(new MemoryStream(mainFile.Backend.BlobStream));
                        bi.BaseStream.Position = tt.Signature;

                        var  a     = bi.ReadByte();    //Normally 0x5
                        var  type3 = bi.ReadByte();    //Normally 0x15 (ELEMENT_TYPE_GENERICINST)
                        var  n     = ParseNumber(bi);  //
                        var  n2    = ParseNumber(bi);
                        var  bb    = bi.ReadByte();    //PTR_END
                        var  aa    = bi.ReadByte();    //depends on the generic type.
                        uint type2;
                        uint index;
                        DecodeTypeDefOrRef((uint)n2, out type2, out index);
                        uint Namespace = 0;
                        uint classs    = 0;

                        if (type2 == 0)
                        {
                            //Type def
                            var Realtabel = mainFile.Backend.Tabels.TypeDefTabel[(int)(index - 1)];
                            Namespace = Realtabel.Namespace;
                            classs    = Realtabel.Name;
                        }
                        else if (type2 == 1)
                        {
                            //Type ref
                            var Realtabel = mainFile.Backend.Tabels.TypeRefTabel[(int)(index - 1)];
                            Namespace = Realtabel.TypeNamespace;
                            classs    = Realtabel.TypeName;
                        }
                        else if (type2 == 2)
                        {
                            //Type spec???? What
                            throw new NotImplementedException();
                        }
                        else
                        {
                            throw new NotImplementedException("Invaild type");
                        }

                        ret2.Namespace = mainFile.Backend.ClrStringsStream.GetByOffset(Namespace);
                        ret2.Class     = mainFile.Backend.ClrStringsStream.GetByOffset(classs);
                        ret.Operand    = ret2;
                    }
                    else if (type == MemberRefParentType.TypeRef)
                    {
                        var tt = mainFile.Backend.Tabels.TypeDefTabel[(int)(row2 - 1)];

                        ret2.Name      = mainFile.Backend.ClrStringsStream.GetByOffset(tt.Name);
                        ret2.Namespace = mainFile.Backend.ClrStringsStream.GetByOffset(tt.Namespace);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }

                return(ret);
            }

            case OpCodeOperandType.InlineMethod:
            {
                byte   fi    = code[Offset + 1];
                byte   s2    = code[Offset + 2];
                byte   t     = code[Offset + 3];
                byte   f     = code[Offset + 4];              //Method type. 6=Method,10=MemberRef
                byte[] num2  = new byte[] { fi, s2, t, 0 };
                var    numb2 = BitConverter.ToInt32(num2, 0); //Method Token

                if (f == 10)                                  //MemberRef
                {
                    //Get the method that we are calling
                    var c = mainFile.Backend.Tabels.MemberRefTabelRow[numb2 - 1];

                    #region Decode
                    //Decode the class bytes
                    DecodeMemberRefParent(c.Class, out MemberRefParentType tabel, out uint row);


                    var    funcName       = mainFile.Backend.ClrStringsStream.GetByOffset(c.Name);
                    uint   classs         = 0;
                    uint   Namespace      = 0;
                    string genericArgType = "";

                    //TYPE def
                    if (tabel == MemberRefParentType.TypeDef)
                    {
                        var tt = mainFile.Backend.Tabels.TypeDefTabel[(int)row - 1];

                        classs    = tt.Name;
                        Namespace = tt.Namespace;
                    }
                    //Type REF
                    else if (tabel == MemberRefParentType.TypeRef)
                    {
                        var tt = mainFile.Backend.Tabels.TypeRefTabel[(int)row - 1];

                        classs = tt.TypeName;


                        Namespace = tt.TypeNamespace;
                    }
                    //Module Ref
                    else if (tabel == MemberRefParentType.ModuleRef)
                    {
                        var tt = mainFile.Backend.Tabels.ModuleRefTabel[(int)row - 1];

                        classs    = tt.Name;
                        Namespace = tt.Name;
                    }
                    //Type Spec
                    else if (tabel == MemberRefParentType.TypeSpec)
                    {
                        //See https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/metadata/corelementtype-enumeration for more info
                        var tt = mainFile.Backend.Tabels.TypeSpecTabel[(int)row - 1];
                        var b  = mainFile.Backend.BlobStream[tt.Signature];
                        var bi = new BinaryReader(new MemoryStream(mainFile.Backend.BlobStream));
                        bi.BaseStream.Position = tt.Signature;

                        var  a    = bi.ReadByte();     //Normally 0x5
                        var  type = bi.ReadByte();     //Normally 0x15 (ELEMENT_TYPE_GENERICINST)
                        var  n    = ParseNumber(bi);   //
                        var  n2   = ParseNumber(bi);
                        var  bb   = bi.ReadByte();     //PTR_END
                        var  aa   = bi.ReadByte();     //depends on the generic type.
                        uint type2;
                        uint index;
                        DecodeTypeDefOrRef((uint)n2, out type2, out index);

                        if (type2 == 0)
                        {
                            //Type def
                            var Realtabel = mainFile.Backend.Tabels.TypeDefTabel[(int)(index - 1)];
                            Namespace = Realtabel.Namespace;
                            classs    = Realtabel.Name;
                        }
                        else if (type2 == 1)
                        {
                            //Type ref
                            var Realtabel = mainFile.Backend.Tabels.TypeRefTabel[(int)(index - 1)];
                            Namespace = Realtabel.TypeNamespace;
                            classs    = Realtabel.TypeName;
                        }
                        else if (type2 == 2)
                        {
                            //Type spec???? What
                            throw new NotImplementedException();
                        }
                        else
                        {
                            throw new NotImplementedException("Invaild type");
                        }
                        if (aa == 0xE)
                        {
                            //String
                            genericArgType = "string";
                        }
                        else if (aa == 0x13)
                        {
                            genericArgType = "var";
                        }
                        else
                        {
                            //TODO: implement the rest of these
                            genericArgType = "Todo";
                            //throw new NotImplementedException();
                        }
                    }
                    //Unknown
                    else
                    {
                        classs    = 0;
                        Namespace = 0;
                        throw new NotImplementedException();
                    }
                    #endregion
                    var anamespace = mainFile.Backend.ClrStringsStream.GetByOffset(Namespace);
                    var typeName   = mainFile.Backend.ClrStringsStream.GetByOffset(classs);

                    //Now, resolve this method
                    //TODO: Resolve the method properly by first
                    //1) resolve the type of the method
                    //2) search for the method in the type
                    //3) get method RVA

                    //For now, resolve it by name
                    var          sig = DotNetMethod.ParseMethodSignature(c.Signature, mainFile, funcName).Signature;
                    DotNetMethod m   = null;
                    foreach (var type in ContextTypes)
                    {
                        foreach (var item in type.Types)
                        {
                            foreach (var meth in item.Methods)
                            {
                                if (meth.Name == funcName && meth.Parent.Name == typeName && meth.Parent.NameSpace == anamespace && meth.Signature == sig)
                                {
                                    m = meth;
                                }
                            }
                        }
                    }
                    uint rva = 0;
                    if (m != null)
                    {
                        rva = m.RVA;
                    }
                    else
                    {
                        //Ignore if it is system object constructor
                        if (anamespace == "System" && typeName == "Object" && funcName == ".ctor")
                        {
                        }
                        else
                        {
                            // Console.WriteLine($"[ILDecompiler: WARN] Cannot resolve method RVA. Are you missing a call to AddReference()??. Method data: {anamespace}.{typeName}.{funcName}");
                        }
                    }

                    ret.Size   += 4;
                    ret.Operand = new InlineMethodOperandData()
                    {
                        NameSpace    = anamespace,
                        ClassName    = typeName,
                        FunctionName = funcName,
                        RVA          = rva,
                        GenericArg   = genericArgType,
                        Signature    = sig
                    };
                    return(ret);
                }
                else if (f == 6)        //method
                {
                    //Get the method that we are calling
                    var    c    = mainFile.Backend.Tabels.MethodTabel[numb2 - 1];
                    string name = mainFile.Backend.ClrStringsStream.GetByOffset(c.Name);
                    //Now, resolve this method
                    DotNetMethod m = null;
                    foreach (var item in mainFile.Types)
                    {
                        foreach (var meth in item.Methods)
                        {
                            if (meth.RVA == c.RVA && meth.Name == name && meth.ParamListIndex == c.ParamList)
                            {
                                m = meth;
                            }
                        }
                    }

                    string className = "CannotFind";
                    string Namespace = "CannotFind";

                    if (m != null)
                    {
                        className = m.Parent.Name;
                        Namespace = m.Parent.NameSpace;
                    }
                    ret.Size   += 4;
                    ret.Operand = new InlineMethodOperandData()
                    {
                        NameSpace      = Namespace,
                        ClassName      = className,
                        FunctionName   = name,
                        RVA            = c.RVA,
                        Signature      = m.Signature,
                        ParamListIndex = c.ParamList
                    };
                    return(ret);
                }
                else if (f == 0x2B)
                {
                    //Method spec
                    var  idx = mainFile.Backend.Tabels.MethodSpecTable[numb2 - 1];
                    uint fa;
                    uint row;
                    DecodeMethodDefOrRef(idx.Method, out fa, out row);

                    if (fa == 0)
                    {
                        //Method
                        var    c    = mainFile.Backend.Tabels.MethodTabel[(int)(row - 1)];
                        string name = mainFile.Backend.ClrStringsStream.GetByOffset(c.Name);
                        //Now, resolve this method
                        DotNetMethod m = null;
                        foreach (var item in mainFile.Types)
                        {
                            foreach (var meth in item.Methods)
                            {
                                if (meth.RVA == c.RVA && meth.Name == name)
                                {
                                    m = meth;
                                }
                            }
                        }

                        string className = "CannotFind";
                        string Namespace = "CannotFind";

                        if (m != null)
                        {
                            className = m.Parent.Name;
                            Namespace = m.Parent.NameSpace;
                        }
                        ret.Size   += 4;
                        ret.Operand = new InlineMethodOperandData()
                        {
                            NameSpace    = Namespace,
                            ClassName    = className,
                            FunctionName = name,
                            RVA          = c.RVA,
                            Signature    = m.Signature,
                        };
                        return(ret);
                    }
                    else if (fa == 1)
                    {
                        //MemberRef
                        var c = mainFile.Backend.Tabels.MemberRefTabelRow[(int)(row - 1)];

                        #region Decode
                        //Decode the class bytes
                        DecodeMemberRefParent(c.Class, out MemberRefParentType tabel, out uint row2);


                        var    funcName       = mainFile.Backend.ClrStringsStream.GetByOffset(c.Name);
                        uint   classs         = 0;
                        uint   Namespace      = 0;
                        string genericArgType = "";

                        //TYPE def
                        if (tabel == MemberRefParentType.TypeDef)
                        {
                            var tt = mainFile.Backend.Tabels.TypeDefTabel[(int)row2 - 1];

                            classs    = tt.Name;
                            Namespace = tt.Namespace;
                        }
                        //Type REF
                        else if (tabel == MemberRefParentType.TypeRef)
                        {
                            var tt = mainFile.Backend.Tabels.TypeRefTabel[(int)row2 - 1];

                            classs = tt.TypeName;


                            Namespace = tt.TypeNamespace;
                        }
                        //Module Ref
                        else if (tabel == MemberRefParentType.ModuleRef)
                        {
                            var tt = mainFile.Backend.Tabels.ModuleRefTabel[(int)row2 - 1];

                            classs    = tt.Name;
                            Namespace = tt.Name;
                        }
                        //Type Spec
                        else if (tabel == MemberRefParentType.TypeSpec)
                        {
                            //See https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/metadata/corelementtype-enumeration for more info
                            var tt = mainFile.Backend.Tabels.TypeSpecTabel[(int)row2 - 1];
                            var b  = mainFile.Backend.BlobStream[tt.Signature];
                            var bi = new BinaryReader(new MemoryStream(mainFile.Backend.BlobStream));
                            bi.BaseStream.Position = tt.Signature;

                            var  a    = bi.ReadByte();     //Normally 0x5
                            var  type = bi.ReadByte();     //Normally 0x15 (ELEMENT_TYPE_GENERICINST)
                            var  n    = ParseNumber(bi);   //
                            var  n2   = ParseNumber(bi);
                            var  bb   = bi.ReadByte();     //PTR_END
                            var  aa   = bi.ReadByte();     //depends on the generic type.
                            uint type2;
                            uint index;
                            DecodeTypeDefOrRef((uint)n2, out type2, out index);

                            if (type2 == 0)
                            {
                                //Type def
                                var Realtabel = mainFile.Backend.Tabels.TypeDefTabel[(int)(index - 1)];
                                Namespace = Realtabel.Namespace;
                                classs    = Realtabel.Name;
                            }
                            else if (type2 == 1)
                            {
                                //Type ref
                                var Realtabel = mainFile.Backend.Tabels.TypeRefTabel[(int)(index - 1)];
                                Namespace = Realtabel.TypeNamespace;
                                classs    = Realtabel.TypeName;
                            }
                            else if (type2 == 2)
                            {
                                //Type spec???? What
                                throw new NotImplementedException();
                            }
                            else
                            {
                                throw new NotImplementedException("Invaild type");
                            }
                            if (aa == 0xE)
                            {
                                //String
                                genericArgType = "string";
                            }
                            else if (aa == 0x13)
                            {
                                genericArgType = "var";
                            }
                            else
                            {
                                //TODO: implement the rest of these
                                genericArgType = "Todo";
                                //throw new NotImplementedException();
                            }
                        }
                        //Unknown
                        else
                        {
                            classs    = 0;
                            Namespace = 0;
                            throw new NotImplementedException();
                        }
                        #endregion
                        var anamespace = mainFile.Backend.ClrStringsStream.GetByOffset(Namespace);
                        var typeName   = mainFile.Backend.ClrStringsStream.GetByOffset(classs);

                        //Now, resolve this method
                        //TODO: Resolve the method properly by first
                        //1) resolve the type of the method
                        //2) search for the method in the type
                        //3) get method RVA

                        //For now, resolve it by name

                        DotNetMethod m = null;
                        foreach (var type in ContextTypes)
                        {
                            foreach (var item in type.Types)
                            {
                                foreach (var meth in item.Methods)
                                {
                                    if (meth.Name == funcName && meth.Parent.Name == typeName && meth.Parent.NameSpace == anamespace)
                                    {
                                        m = meth;
                                    }
                                }
                            }
                        }
                        uint rva = 0;
                        if (m != null)
                        {
                            rva = m.RVA;
                        }
                        else
                        {
                            //Ignore if it is system object constructor
                            if (anamespace == "System" && typeName == "Object" && funcName == ".ctor")
                            {
                            }
                            else
                            {
                                Console.WriteLine($"[ILDecompiler: WARN] Cannot resolve method RVA. Are you missing a call to AddReference()??. Method data: {anamespace}.{typeName}.{funcName}");
                            }
                        }

                        ret.Size   += 4;
                        ret.Operand = new InlineMethodOperandData()
                        {
                            NameSpace    = anamespace,
                            ClassName    = typeName,
                            FunctionName = funcName,
                            RVA          = rva,
                            GenericArg   = genericArgType,
                            Signature    = DotNetMethod.ParseMethodSignature(c.Signature, mainFile, funcName).Signature
                        };
                        return(ret);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            case OpCodeOperandType.InlineSig:
            {
                var numb2 = BitConverter.ToInt32(code, Offset + 1);

                ret.Size   += 4;
                ret.Operand = numb2;
                return(ret);
            }

            case OpCodeOperandType.InlineString:
            {
                byte   first = code[Offset + 1];       //1st index
                byte   sec   = code[Offset + 2];       //2nd
                byte   third = code[Offset + 3];       //3rd
                byte   forth = code[Offset + 4];       //string type
                byte[] num   = new byte[] { first, sec, third, 0 };
                var    numb  = BitConverter.ToInt32(num, 0);

                //Get the string
                string s;

                if (forth != 112)
                {
                    //Will this ever be in the String Stream?
                    s = mainFile.Backend.ClrStringsStream.GetByOffset((uint)numb);
                }
                else
                {
                    //US stream
                    s = mainFile.Backend.ClrUsStream.GetByOffset((uint)numb);
                }
                ret.Size   += 4;
                ret.Operand = s;
                return(ret);
            }

            case OpCodeOperandType.InlineSwitch:
                throw new NotImplementedException();

            case OpCodeOperandType.ShortInlineR:
            {
                var numb2 = BitConverter.ToSingle(code, Offset + 1);

                ret.Size   += 4;
                ret.Operand = numb2;
                return(ret);
            }

            case OpCodeOperandType.InlineType:
            {
                byte fi = code[Offset + 1];

                ret.Size   += 4;
                ret.Operand = fi;
                return(ret);
            }

            // 64 bit int
            case OpCodeOperandType.InlineI8:
            {
                var numb2 = BitConverter.ToInt64(code, Offset + 1);
                ret.Size   += 8;
                ret.Operand = numb2;
                return(ret);
            }

            case OpCodeOperandType.InlineR:
            {
                var numb2 = BitConverter.ToDouble(code, Offset + 1);
                ret.Size   += 8;
                ret.Operand = numb2;
                return(ret);
            }

            default:
                break;
            }

            return(null);
        }
Esempio n. 5
0
        /// <summary>
        /// Makes things much easier for the DoStartMethod() function
        /// </summary>
        /// <param name="m"></param>
        /// <param name="args"></param>
        // All of the Opcodes that have additional parameters have to be processed here.
        private void ProcessMethod(DotNetMethod m, params string[] args)
        {
            byte[] code = m.GetBody();
            List <ILInstruction> inr = new List <ILInstruction>();

            for (int i = 0; i < code.Length; i++)
            {
                byte opCode = code[i];

                if (opCode == (byte)OpCodes.Ldstr)
                {
                    //Decode the number
                    byte   first = code[i + 1]; //1st index
                    byte   sec   = code[i + 2]; //2nd
                    byte   third = code[i + 3];
                    byte   forth = code[i + 4];
                    byte[] num   = new byte[] { first, sec, third, 0 };
                    var    numb  = BitConverter.ToInt32(num, 0);

                    //Get the string
                    string s;

                    //Microsoft does really good documentation on front-end things. For example: Windows Apis, and the dot net framework.
                    //But, They don't do backend documentation, for example: Decoding this string token.
                    //I have to go through 100,000+ lines of code in the .NET Clr to figure out how these string tokens work and still didnt figure it out.

                    if (forth != 112)
                    {
                        //Will this ever be in the String Stream?
                        s = file.Backend.ClrStringsStream.GetByOffset((uint)numb);
                    }
                    else
                    {
                        //US stream

                        //This is only a temp. hack
                        s = file.Backend.ClrUsStream.GetByOffset((uint)numb);
                    }
                    int rid = numb & 0x00ffffff; //Not sure weather this is needed, but I found it in the CLR
                    i += 4;                      //skip past the string

                    inr.Add(new ILInstruction()
                    {
                        OpCode  = OpCodes.Ldstr,
                        Operand = s
                    });
                }
                else if (opCode == OpCodes.Call)
                {
                    try
                    {
                        byte   fi   = code[i + 1];
                        byte   s    = code[i + 2];
                        byte   t    = code[i + 3];
                        byte   f    = code[i + 4];
                        byte[] num  = new byte[] { fi, s, t, f };
                        short  numb = BitConverter.ToInt16(num, 0); //Method Token


                        //Get the method that we are calling
                        var c = file.Backend.tabels.MemberRefTabelRow[numb - 1]; //is the -1 needed?

                        i += 4;                                                  //skip past the string
                        #region Decode
                        //Decode the class bytes
                        uint tabel;
                        uint row;
                        DecodeMemberRefParent(c.Class, out tabel, out row);


                        var    funcName = file.Backend.ClrStringsStream.GetByOffset(c.Name);
                        string classs;
                        string Namespace;

                        //TYPE def
                        if (tabel == 02)
                        {
                            var tt = file.Backend.tabels.TypeDefTabel[(int)row - 1];

                            classs    = file.Backend.ClrStringsStream.GetByOffset(tt.Name);
                            Namespace = file.Backend.ClrStringsStream.GetByOffset(tt.Namespace);
                        }
                        //Type REF
                        else if (tabel == 01)
                        {
                            var tt = file.Backend.tabels.TypeRefTabel[(int)row - 1];

                            classs    = file.Backend.ClrStringsStream.GetByOffset(tt.TypeName);
                            Namespace = file.Backend.ClrStringsStream.GetByOffset(tt.TypeNamespace);
                        }
                        //Module Ref
                        else if (tabel == 26)
                        {
                            //var tt = file.Backend.MetaDataStreamTablesHeader.Tables.ModuleRef[(int)row - 1];

                            //classs = file.Backend.ClrStringsStream.GetByOffset(tt.Name);
                            //Namespace = file.Backend.ClrStringsStream.GetByOffset(tt.Namespace);
                            Console.WriteLine("Module Ref not supported!");
                            classs    = "<Module Ref>";
                            Namespace = "<Module Ref>";
                        }
                        //Unknown
                        else
                        {
                            classs    = "<unknown>";
                            Namespace = "<unknown>";
                        }
                        #endregion
                        var inst = new ILInstruction()
                        {
                            OpCode = OpCodes.Call,
                            DecompilerExtraData = numb
                        };
                        inst.Operand = new CallMethodDataHolder()
                        {
                            ClassName = classs, NameSpace = Namespace, FunctionName = funcName
                        };


                        inr.Add(inst);
                    }
                    catch { }
                }
                else
                {
                    inr.Add(new ILInstruction()
                    {
                        OpCode = opCode
                    });
                }
            }
            //After decoding, start the method
            DoStartMethod(inr, args);
        }