public IlDecompiler(DotNetMethod method) { if (method == null) { throw new ArgumentException("method"); } m = method; mainFile = m.File; code = m.GetBody(); AddReference(m.Parent.File); }
/// <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); }