public static void WriteFatSEHHeader(MethodBody mb, BinaryWriter bw) { int n = mb.ExceptionHandlingClauses.Count; int datasize = n * 24 + 4; datasize = datasize * 0x100 + 0x41; bw.Write(datasize); }
private void CopyTryCatch(ILGenerator Gen, int i, MethodBody Body, List<int> ExceptionTrinkets) { // Quick check to see if we want to walk through the list if (!ExceptionTrinkets.Contains(i)) return; foreach (ExceptionHandlingClause Clause in Body.ExceptionHandlingClauses) { if (Clause.Flags != ExceptionHandlingClauseOptions.Clause && Clause.Flags != ExceptionHandlingClauseOptions.Finally) continue; // Look for an ending of an exception block first! if (Clause.HandlerOffset + Clause.HandlerLength == i) Gen.EndExceptionBlock(); // If this marks the beginning of a try block, emit that if (Clause.TryOffset == i) Gen.BeginExceptionBlock(); // Also check for the beginning of a catch block if (Clause.HandlerOffset == i && Clause.Flags == ExceptionHandlingClauseOptions.Clause) Gen.BeginCatchBlock(Clause.CatchType); // Lastly, check for a finally block if (Clause.HandlerOffset == i && Clause.Flags == ExceptionHandlingClauseOptions.Finally) Gen.BeginFinallyBlock(); } }
public void MethodBodyTest() { MethodInfo m = typeof(GenericsUnitTest).GetMethod("MethodTest"); MethodTableCursor cur = f[TableNames.Method].GetCursor() as MethodTableCursor; cur.Goto(m.MetadataToken & 0xFFFFFF); System.Reflection.MethodBody rb = m.GetMethodBody(); CLIFileRW.MethodBody cb = cur.MethodBody; Assert.AreEqual(rb.LocalSignatureMetadataToken & 0xFFFFFF, cb.LocalsSig); LocalsVarSig locals = cb.LocalsSignature; IEnumerator <CLIType> lv = locals.GetVariables().GetEnumerator(); foreach (LocalVariableInfo v in rb.LocalVariables) { Assert.IsTrue(lv.MoveNext()); // Fetch instantiation from local type since we are not driven by CLIFile reflection Assert.AreSame(v.LocalType, lv.Current.GetReflectionType(v.LocalType.GetGenericArguments())); } ILCursor ilc = cb.ILInstructions; while (ilc.Next()) { ILInstruction instr = ilc.Instr; object o = instr.ResolveParameter(f); } }
MethodBodyReader (MethodBase method) { this.method = method; this.body = method.GetMethodBody (); if (this.body == null) throw new ArgumentException ("Method has no body"); var bytes = body.GetILAsByteArray (); if (bytes == null) throw new ArgumentException ("Can not get the body of the method"); if (!(method is ConstructorInfo)) method_arguments = method.GetGenericArguments (); if (method.DeclaringType != null) type_arguments = method.DeclaringType.GetGenericArguments (); if (!method.IsStatic) this_parameter = new ThisParameter(method.DeclaringType); this.parameters = method.GetParameters (); this.locals = body.LocalVariables; this.module = method.Module; this.il = new ByteBuffer (bytes); this.instructions = new List<Instruction> ((bytes.Length + 1) / 2); }
public NaiveMethodNameExtractor(Delegate @delegate) { delegateMethod = @delegate.Method; body = delegateMethod.GetMethodBody(); Debug.Assert(body != null); module = delegateMethod.Module; stream = new MemoryStream(body.GetILAsByteArray()); Read(); }
public MethodBaseAdapter(MethodBase actual) { this.actual = actual; this.bodyOfActual = this.actual.GetMethodBody(); if (bodyOfActual == null) throw new NotSupportedException("Method " + actual + " must have a body to adapted using this class."); this.Context = new MethodBaseModuleContext(actual); }
/// <summary> /// Disassemble the bytecode of the specified method or constructor /// </summary> /// <param name="MethodBase">The method to disassemble</param> /// <param name="Resolver">A resolver class used while disassembling the code. /// Every token resolution and local variable resolution will be made with this resolver</param> /// <returns>The list of intruction contained in the method</returns> static public List <Instruction> ReadMethod(System.Reflection.MethodBase MethodBase, Resolver Resolver) { System.Reflection.MethodBody methodBody = MethodBase.GetMethodBody(); if (methodBody == null) { return(new List <Instruction>()); } return(ReadMethod(methodBody.GetILAsByteArray(), Resolver)); }
public MSIL_MethodResolver(System.Reflection.MethodBase Method) : base(Method.DeclaringType.Module) { System.Reflection.MethodBody body = Method.GetMethodBody(); if (Method.GetMethodBody() != null) { foreach (System.Reflection.LocalVariableInfo localsBody in body.LocalVariables) { System.Reflection.LocalVariableInfo _WAR_local = localsBody; _locals.Add(_WAR_local.LocalIndex, _WAR_local); } } }
// Build a cache of points where we need to look for exception trinkets // An exception trinket is an object denoting the offsets of try, catch and finally blocks private void MineExTrinkets(MethodBody Body, List<int> ExceptionTrinkets) { foreach (ExceptionHandlingClause Clause in Body.ExceptionHandlingClauses) { // Only handle catch and finally. TODO: fault and filter if (Clause.Flags != ExceptionHandlingClauseOptions.Clause && Clause.Flags != ExceptionHandlingClauseOptions.Finally) continue; ExceptionTrinkets.Add(Clause.TryOffset); ExceptionTrinkets.Add(Clause.HandlerOffset); ExceptionTrinkets.Add(Clause.HandlerOffset + Clause.HandlerLength); } }
public static Action <MethodDef> ApplyInject(this MethodBase inject, PatchConfiguration patch) => stub => { CilBody stubBody = stub.Body; MethodBody injectBody = inject.GetMethodBody(); List <Instruction> originalIL = new List <Instruction>(stubBody.Instructions); List <Local> originalLocals = new List <Local>(stubBody.Variables); stubBody.Variables.Clear(); foreach (LocalVariableInfo local in injectBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex)) { stubBody.Variables.Add(stub.Module.ToDNLib(local)); } List <Instruction> mixinIL = new CilParser(inject.Module, stubBody.Variables, injectBody.GetILAsByteArray()).Parse(); mixinIL.SimplifyMacros(stubBody.Variables, stub.Parameters); IList <Instruction> newIL = stubBody.Instructions; newIL.Clear(); foreach (Instruction inst in mixinIL) { switch (inst.Operand) { case FieldInfo field: inst.Operand = patch.ResolveOrImport(stub.Module, field); break; case MethodBase method: if (method.IsDefined(typeof(BaseDependencyAttribute))) { throw new InvalidOperationException("attempt to inject a body with a base dependency call"); } inst.Operand = patch.ResolveOrImport(stub.Module, method); break; case Type type: inst.Operand = patch.ResolveOrImport(stub.Module, type); break; case byte[] blob: throw new NotImplementedException("how do you import this?"); case MemberInfo member: throw new NotImplementedException("how do you import this?"); } newIL.Add(inst); } stubBody.ExceptionHandlers.Clear(); foreach (ExceptionHandlingClause ehc in injectBody.ExceptionHandlingClauses) { stubBody.ExceptionHandlers.Add(ehc.ToDNLib(stub.Module, newIL)); } stubBody.OptimizeMacros(); };
/// <summary> /// Initializes a new instance of the <see cref="ILCode"/> class. /// </summary> /// <param name="method">The method to read the IL code from.</param> public ILCode(MethodBase method) { this.Method = method; this.body = this.Method.GetMethodBody(); if (this.body == null) { this.ilbytes = new byte[0]; } else { this.ilbytes = this.body.GetILAsByteArray(); } this.reader = new BinaryReader(new MemoryStream(this.ilbytes, false)); }
private MethodBodyReader(MethodBase method) { _method = method; _body = method.GetMethodBody(); if (_body == null) throw new ArgumentException("Method has no body"); var iLAsByteArray = _body.GetILAsByteArray(); if (iLAsByteArray == null) throw new ArgumentException("Can not get the body of the method"); if (!(method is ConstructorInfo)) _methodArguments = method.GetGenericArguments(); if (method.DeclaringType != null) _typeArguments = method.DeclaringType.GetGenericArguments(); _parameters = method.GetParameters(); _locals = _body.LocalVariables; _module = method.Module; _il = new ByteBuffer(iLAsByteArray); }
public MethodDebugInfo(MethodBody body, ISymbolMethod pdb) { Body = body; // todo. support multiple locals sharing the same local slot // (but having different Start::End offsets, of course) // so far we just silently ignore them taking into account only the first one var locals = pdb.RootScope.Flatten(ss => ss.GetChildren()).SelectMany(ss => ss.GetLocals()); LocalNames = locals.Select(lv => new {Index = lv.AddressField1, Name = lv.Name}) .Distinct().ToDictionary(lv => lv.Index, lv => lv.Name).ToReadOnly(); var count = pdb.SequencePointCount; var offsets = new int[count]; var documents = new ISymbolDocument[count]; var lines = new int[count]; var columns = new int[count]; var endLines = new int[count]; var endColumns = new int[count]; pdb.GetSequencePoints(offsets, documents, lines, columns, endLines, endColumns); SequencePoints = 0.UpTo(count - 1).Select(i => new SequencePoint(offsets[i], documents[i], lines[i], columns[i], endLines[i], endColumns[i]) ).ToReadOnly(); }
private void _CopyMethodToDefinition() { MethodBase method = OriginalMethod; Module moduleFrom = method.Module; System.Reflection.MethodBody bodyFrom = method.GetMethodBody(); byte[] data = bodyFrom?.GetILAsByteArray(); if (data == null) { throw new NotSupportedException("Body-less method"); } MethodDefinition def = Definition; ModuleDefinition moduleTo = def.Module; Mono.Cecil.Cil.MethodBody bodyTo = def.Body; ILProcessor processor = bodyTo.GetILProcessor(); Type[] typeArguments = null; if (method.DeclaringType.IsGenericType) { typeArguments = method.DeclaringType.GetGenericArguments(); } Type[] methodArguments = null; if (method.IsGenericMethod) { methodArguments = method.GetGenericArguments(); } foreach (LocalVariableInfo info in bodyFrom.LocalVariables) { TypeReference type = moduleTo.ImportReference(info.LocalType); if (info.IsPinned) { type = new PinnedType(type); } bodyTo.Variables.Add(new VariableDefinition(type)); } using (BinaryReader reader = new BinaryReader(new MemoryStream(data))) { for (Instruction instr = null, prev = null; reader.BaseStream.Position < reader.BaseStream.Length; prev = instr) { int offset = (int)reader.BaseStream.Position; instr = Instruction.Create(OpCodes.Nop); byte op = reader.ReadByte(); instr.OpCode = op != 0xfe ? _CecilOpCodes1X[op] : _CecilOpCodes2X[reader.ReadByte()]; instr.Offset = offset; if (prev != null) { prev.Next = instr; } instr.Previous = prev; ReadOperand(reader, instr); bodyTo.Instructions.Add(instr); } } foreach (Instruction instr in bodyTo.Instructions) { switch (instr.OpCode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: instr.Operand = GetInstruction((int)instr.Operand); break; case OperandType.InlineSwitch: int[] offsets = (int[])instr.Operand; Instruction[] targets = new Instruction[offsets.Length]; for (int i = 0; i < offsets.Length; i++) { targets[i] = GetInstruction(offsets[i]); } instr.Operand = targets; break; } } foreach (ExceptionHandlingClause clause in bodyFrom.ExceptionHandlingClauses) { ExceptionHandler handler = new ExceptionHandler((ExceptionHandlerType)clause.Flags); bodyTo.ExceptionHandlers.Add(handler); handler.TryStart = GetInstruction(clause.TryOffset); handler.TryEnd = GetInstruction(clause.TryOffset + clause.TryLength); handler.FilterStart = handler.HandlerType != ExceptionHandlerType.Filter ? null : GetInstruction(clause.FilterOffset); handler.HandlerStart = GetInstruction(clause.HandlerOffset); handler.HandlerEnd = GetInstruction(clause.HandlerOffset + clause.HandlerLength); handler.CatchType = handler.HandlerType != ExceptionHandlerType.Catch ? null : clause.CatchType == null ? null : moduleTo.ImportReference(clause.CatchType); } void ReadOperand(BinaryReader reader, Instruction instr) { int index, offs, length; switch (instr.OpCode.OperandType) { case OperandType.InlineNone: instr.Operand = null; break; case OperandType.InlineSwitch: length = reader.ReadInt32(); offs = (int)reader.BaseStream.Position + (4 * length); int[] targets = new int[length]; for (int i = 0; i < length; i++) { targets[i] = reader.ReadInt32() + offs; } instr.Operand = targets; break; case OperandType.ShortInlineBrTarget: offs = reader.ReadSByte(); instr.Operand = (int)reader.BaseStream.Position + offs; break; case OperandType.InlineBrTarget: offs = reader.ReadInt32(); instr.Operand = (int)reader.BaseStream.Position + offs; break; case OperandType.ShortInlineI: instr.Operand = instr.OpCode == OpCodes.Ldc_I4_S ? reader.ReadSByte() : (object)reader.ReadByte(); break; case OperandType.InlineI: instr.Operand = reader.ReadInt32(); break; case OperandType.ShortInlineR: instr.Operand = reader.ReadSingle(); break; case OperandType.InlineR: instr.Operand = reader.ReadDouble(); break; case OperandType.InlineI8: instr.Operand = reader.ReadInt64(); break; case OperandType.InlineSig: instr.Operand = moduleTo.ImportCallSite(moduleFrom, moduleFrom.ResolveSignature(reader.ReadInt32())); break; case OperandType.InlineString: instr.Operand = moduleFrom.ResolveString(reader.ReadInt32()); break; case OperandType.InlineTok: instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Any); break; case OperandType.InlineType: instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Type); break; case OperandType.InlineMethod: instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Method); break; case OperandType.InlineField: instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Field); break; case OperandType.ShortInlineVar: case OperandType.InlineVar: index = instr.OpCode.OperandType == OperandType.ShortInlineVar ? reader.ReadByte() : reader.ReadInt16(); instr.Operand = bodyTo.Variables[index]; break; case OperandType.InlineArg: case OperandType.ShortInlineArg: index = instr.OpCode.OperandType == OperandType.ShortInlineArg ? reader.ReadByte() : reader.ReadInt16(); instr.Operand = def.Parameters[index]; break; case OperandType.InlinePhi: // No opcode seems to use this default: throw new NotSupportedException($"Unsupported opcode ${instr.OpCode.Name}"); } } MemberReference ResolveTokenAs(int token, TokenResolutionMode resolveMode) { try { switch (resolveMode) { case TokenResolutionMode.Type: return(moduleTo.ImportReference(moduleFrom.ResolveType(token, typeArguments, methodArguments))); case TokenResolutionMode.Method: return(moduleTo.ImportReference(moduleFrom.ResolveMethod(token, typeArguments, methodArguments))); case TokenResolutionMode.Field: return(moduleTo.ImportReference(moduleFrom.ResolveField(token, typeArguments, methodArguments))); case TokenResolutionMode.Any: switch (moduleFrom.ResolveMember(token, typeArguments, methodArguments)) { case Type i: return(moduleTo.ImportReference(i)); case MethodBase i: return(moduleTo.ImportReference(i)); case FieldInfo i: return(moduleTo.ImportReference(i)); case var resolved: throw new NotSupportedException($"Invalid resolved member type {resolved.GetType()}"); } default: throw new NotSupportedException($"Invalid TokenResolutionMode {resolveMode}"); } } catch (MissingMemberException) { // we could not resolve the method normally, so lets read the import table // but we can only do that if the module was loaded from disk // this can still throw if the assembly is a dynamic one, but if that's broken, you have bigger issues string filePath = moduleFrom.Assembly.Location; if (!File.Exists(filePath)) { // in this case, the fallback cannot be followed, and so throwing the original error gives the user information throw; } // TODO: make this cached somehow so its not read and re-opened a bunch using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(filePath, new ReaderParameters { ReadingMode = ReadingMode.Deferred })) { ModuleDefinition module = assembly.Modules.First(m => m.Name == moduleFrom.Name); // this should only fail if the token itself is somehow wrong MemberReference reference = (MemberReference)module.LookupToken(token); // the explicit casts here are to throw if they are incorrect // normally the references would need to be imported, but moduleTo isn't written to anywhere switch (resolveMode) { case TokenResolutionMode.Type: return((TypeReference)reference); case TokenResolutionMode.Method: return((MethodReference)reference); case TokenResolutionMode.Field: return((FieldReference)reference); case TokenResolutionMode.Any: return(reference); default: throw new NotSupportedException($"Invalid TokenResolutionMode {resolveMode}"); } } } } Instruction GetInstruction(int offset) { int last = bodyTo.Instructions.Count - 1; if (offset < 0 || offset > bodyTo.Instructions[last].Offset) { return(null); } int min = 0; int max = last; while (min <= max) { int mid = min + ((max - min) / 2); Instruction instr = bodyTo.Instructions[mid]; if (offset == instr.Offset) { return(instr); } if (offset < instr.Offset) { max = mid - 1; } else { min = mid + 1; } } return(null); } }
public static int PushedValuesCount(this Instruction instruction, MethodInfo analyzedMethod, MethodBody methodBody) { int pushedCount = instruction.PushedValuesCountByOpCode(); if (methodBody.ExceptionHandlingClauses.Any(x => x.BeginsOn(instruction) && x.IsCatch())) { pushedCount++; } return pushedCount; }
MethodBodyReader(MethodBase method) { this.method = method; this.body = method.GetMethodBody(); if (this.body == null) throw new ArgumentNullException(); var bytes = body.GetILAsByteArray(); if (bytes == null) throw new ArgumentNullException(); if (!(method is ConstructorInfo)) method_arguments = method.GetGenericArguments(); if (method.DeclaringType != null) type_arguments = method.DeclaringType.GetGenericArguments(); this.parameters = method.GetParameters(); this.locals = body.LocalVariables; this.module = method.Module; this.il = new ByteBuffer(bytes); }
private void _CopyMethodToDefinition() { MethodBase method = OriginalMethod; Module moduleFrom = method.Module; System.Reflection.MethodBody bodyFrom = method.GetMethodBody(); byte[] data = bodyFrom?.GetILAsByteArray(); if (data == null) { throw new NotSupportedException("Body-less method"); } MethodDefinition def = Definition; ModuleDefinition moduleTo = def.Module; Mono.Cecil.Cil.MethodBody bodyTo = def.Body; ILProcessor processor = bodyTo.GetILProcessor(); Type[] typeArguments = null; if (method.DeclaringType.IsGenericType) { typeArguments = method.DeclaringType.GetGenericArguments(); } Type[] methodArguments = null; if (method.IsGenericMethod) { methodArguments = method.GetGenericArguments(); } foreach (LocalVariableInfo info in bodyFrom.LocalVariables) { TypeReference type = moduleTo.ImportReference(info.LocalType); if (info.IsPinned) { type = new PinnedType(type); } bodyTo.Variables.Add(new VariableDefinition(type)); } using (BinaryReader reader = new BinaryReader(new MemoryStream(data))) { while (reader.BaseStream.Position < reader.BaseStream.Length) { int offset = (int)reader.BaseStream.Position; Instruction instr = Instruction.Create(OpCodes.Nop); byte op = reader.ReadByte(); instr.OpCode = op != 0xfe ? _CecilOpCodes1X[op] : _CecilOpCodes2X[reader.ReadByte()]; instr.Offset = offset; ReadOperand(reader, instr); bodyTo.Instructions.Add(instr); } } foreach (Instruction instr in bodyTo.Instructions) { switch (instr.OpCode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: instr.Operand = GetInstruction((int)instr.Operand); break; case OperandType.InlineSwitch: int[] offsets = (int[])instr.Operand; Instruction[] targets = new Instruction[offsets.Length]; for (int i = 0; i < offsets.Length; i++) { targets[i] = GetInstruction(offsets[i]); } instr.Operand = targets; break; } } foreach (ExceptionHandlingClause clause in bodyFrom.ExceptionHandlingClauses) { ExceptionHandler handler = new ExceptionHandler((ExceptionHandlerType)clause.Flags); bodyTo.ExceptionHandlers.Add(handler); handler.TryStart = GetInstruction(clause.TryOffset); handler.TryEnd = GetInstruction(clause.TryOffset + clause.TryLength); handler.FilterStart = handler.HandlerType != ExceptionHandlerType.Filter ? null : GetInstruction(clause.FilterOffset); handler.HandlerStart = GetInstruction(clause.HandlerOffset); handler.HandlerEnd = GetInstruction(clause.HandlerOffset + clause.HandlerLength); handler.CatchType = handler.HandlerType != ExceptionHandlerType.Catch ? null : clause.CatchType == null ? null : moduleTo.ImportReference(clause.CatchType); } void ReadOperand(BinaryReader reader, Instruction instr) { int index, offs, length; switch (instr.OpCode.OperandType) { case OperandType.InlineNone: instr.Operand = null; break; case OperandType.InlineSwitch: length = reader.ReadInt32(); offs = (int)reader.BaseStream.Position + (4 * length); int[] targets = new int[length]; for (int i = 0; i < length; i++) { targets[i] = reader.ReadInt32() + offs; } instr.Operand = targets; break; case OperandType.ShortInlineBrTarget: offs = reader.ReadSByte(); instr.Operand = (int)reader.BaseStream.Position + offs; break; case OperandType.InlineBrTarget: offs = reader.ReadInt32(); instr.Operand = (int)reader.BaseStream.Position + offs; break; case OperandType.ShortInlineI: instr.Operand = instr.OpCode == OpCodes.Ldc_I4_S ? reader.ReadSByte() : (object)reader.ReadByte(); break; case OperandType.InlineI: instr.Operand = reader.ReadInt32(); break; case OperandType.ShortInlineR: instr.Operand = reader.ReadSingle(); break; case OperandType.InlineR: instr.Operand = reader.ReadDouble(); break; case OperandType.InlineI8: instr.Operand = reader.ReadInt64(); break; case OperandType.InlineSig: throw new NotSupportedException("Parsing CallSites at runtime currently not supported"); case OperandType.InlineString: instr.Operand = moduleFrom.ResolveString(reader.ReadInt32()); break; case OperandType.InlineTok: switch (moduleFrom.ResolveMember(reader.ReadInt32(), typeArguments, methodArguments)) { case Type i: instr.Operand = moduleTo.ImportReference(i); break; case FieldInfo i: instr.Operand = moduleTo.ImportReference(i); break; case MethodBase i: instr.Operand = moduleTo.ImportReference(i); break; } break; case OperandType.InlineType: instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveType(reader.ReadInt32(), typeArguments, methodArguments)); break; case OperandType.InlineMethod: instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveMethod(reader.ReadInt32(), typeArguments, methodArguments)); break; case OperandType.InlineField: instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveField(reader.ReadInt32(), typeArguments, methodArguments)); break; case OperandType.ShortInlineVar: case OperandType.InlineVar: index = instr.OpCode.OperandType == OperandType.ShortInlineVar ? reader.ReadByte() : reader.ReadInt16(); instr.Operand = bodyTo.Variables[index]; break; case OperandType.InlineArg: case OperandType.ShortInlineArg: index = instr.OpCode.OperandType == OperandType.ShortInlineArg ? reader.ReadByte() : reader.ReadInt16(); instr.Operand = def.Parameters[index]; break; case OperandType.InlinePhi: // No opcode seems to use this default: throw new NotSupportedException($"Unsupported opcode ${instr.OpCode.Name}"); } } Instruction GetInstruction(int offset) { int last = bodyTo.Instructions.Count - 1; if (offset < 0 || offset > bodyTo.Instructions[last].Offset) { return(null); } int min = 0; int max = last; while (min <= max) { int mid = min + ((max - min) / 2); Instruction instr = bodyTo.Instructions[mid]; if (offset == instr.Offset) { return(instr); } if (offset < instr.Offset) { max = mid - 1; } else { min = mid + 1; } } return(null); } }
public void MethodBodyAllTest() { Assembly mscorlib = typeof(object).Assembly; CLIFile f = CLIFile.Open(mscorlib.Location); MethodTableCursor cur = f[TableNames.Method].GetCursor() as MethodTableCursor; int instrcnt = 0; int methods = 0; int implmeth = 0; int brcnt = 0; while (cur.Next()) { // The token 0x0600449a is not resolved by ResolveMethod, it is likely a bug in reflection. // With .NET 3.5 SP1 the method has moved into token 0x44df. if (cur.Position == 0x44df) { continue; } MethodBase mb = mscorlib.ManifestModule.ResolveMethod(cur.MetadataToken); System.Reflection.MethodBody rb = mb.GetMethodBody(); methods++; if (rb == null) { Assert.IsTrue(rb == null && cur.RVA == 0); continue; } implmeth++; CLIFileRW.MethodBody cb = cur.MethodBody; Assert.AreEqual(rb.LocalSignatureMetadataToken & 0xFFFFFF, cb.LocalsSig); if (rb.LocalSignatureMetadataToken != 0) { LocalsVarSig locals = cb.LocalsSignature; IEnumerator <CLIType> lv = locals.GetVariables().GetEnumerator(); foreach (LocalVariableInfo v in rb.LocalVariables) { Assert.IsTrue(lv.MoveNext()); // Fetch instantiation from local type since we are not driven by CLIFile reflection Assert.AreSame(v.LocalType, lv.Current.GetReflectionType(mb.DeclaringType.ContainsGenericParameters ? mb.DeclaringType.GetGenericArguments() : null, mb.ContainsGenericParameters ? mb.GetGenericArguments() : null)); } } ILCursor ilc = cb.ILInstructions; while (ilc.Next()) { ILInstruction instr = ilc.Instr; object o = instr.ResolveParameter(f); instrcnt++; if (instr.op == System.Reflection.Emit.OpCodes.Br || instr.op == System.Reflection.Emit.OpCodes.Br_S) { brcnt++; } } } System.Diagnostics.Debug.WriteLine(string.Format("Total methods: {0}", methods)); System.Diagnostics.Debug.WriteLine(string.Format("Impl methods: {0}", implmeth)); System.Diagnostics.Debug.WriteLine(string.Format("Total instructions: {0}", instrcnt)); System.Diagnostics.Debug.WriteLine(string.Format("Total unconditional branch: {0}", brcnt)); System.Diagnostics.Debug.WriteLine(string.Format("Average method len: {0}", (instrcnt / (double)methods))); }
private MethodBodyReader(MethodBase method) { this.method = method; this.body = method.GetMethodBody(); if (this.body == null) { throw new ArgumentException("Method has no body"); } byte[] bytes = this.body.GetILAsByteArray(); if (bytes == null) { throw new ArgumentException("Can not get the body of the method"); } if (!(method is ConstructorInfo)) { method.GetGenericArguments(); } if (method.DeclaringType != null) { method.DeclaringType.GetGenericArguments(); } this.parameters = method.GetParameters(); this.locals = this.body.LocalVariables; this.module = method.Module; this.il = new ByteBuffer(bytes); }
public static Action <MethodDef> ApplyMixin(this MethodBase mixin, PatchConfiguration patch) => original => { CilBody originalBody = original.Body; MethodBody mixinBody = mixin.GetMethodBody(); List <Instruction> originalIL = new List <Instruction>(originalBody.Instructions); List <Local> originalLocals = new List <Local>(originalBody.Variables); originalBody.Variables.Clear(); foreach (LocalVariableInfo local in mixinBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex)) { originalBody.Variables.Add(original.Module.ToDNLib(local)); } List <Instruction> mixinIL = new CilParser(mixin.Module, originalBody.Variables, mixinBody.GetILAsByteArray()).Parse(); mixinIL.SimplifyMacros(originalBody.Variables, original.Parameters); IList <Instruction> newIL = originalBody.Instructions; newIL.Clear(); int ilStart = 0; if (mixin.IsConstructor) { foreach (Instruction inst in mixin.IsDefined(typeof(RewriteBaseAttribute)) ? mixinIL : originalIL) { ilStart++; newIL.Add(inst); if (inst.OpCode.FlowControl == FlowControl.Call) { break; } } RemoveCall(originalIL); RemoveCall(mixinIL); } MethodDef baseCopy = new MethodDefUser(original.DeclaringType.FindUnusedMethodName(original.Name + "<Base>$"), original.MethodSig, original.ImplAttributes, original.Attributes & CopyMask | CopyAttr); bool useBase = false; foreach (Instruction inst in mixinIL) { switch (inst.Operand) { case FieldInfo field: inst.Operand = patch.ResolveOrImport(original.Module, field); break; case MethodBase method: if (method.IsDefined(typeof(BaseDependencyAttribute))) { useBase = true; inst.Operand = baseCopy; break; } inst.Operand = patch.ResolveOrImport(original.Module, method); break; case Type type: inst.Operand = patch.ResolveOrImport(original.Module, type); break; case byte[] blob: throw new NotImplementedException("how do you import this?"); case MemberInfo member: throw new NotImplementedException("how do you import this?"); } newIL.Add(inst); } if (useBase) { baseCopy.Body = new CilBody(originalBody.InitLocals, originalIL, new List <ExceptionHandler>(originalBody.ExceptionHandlers), originalBody.Variables); original.DeclaringType.Methods.Add(baseCopy); } originalBody.ExceptionHandlers.Clear(); foreach (ExceptionHandlingClause ehc in mixinBody.ExceptionHandlingClauses) { originalBody.ExceptionHandlers.Add(ehc.ToDNLib(original.Module, newIL)); } originalBody.OptimizeMacros(); void RemoveCall(List <Instruction> il) { for (int index = 0; index < il.Count; index++) { if (il[index].OpCode.FlowControl != FlowControl.Call) { continue; } il.RemoveRange(0, index + 1); break; } } };
private void Write(BinaryWriter bw, Module module, MethodBody mb) { var locals = mb.LocalVariables; bw.Write(locals.Count); for (int i=0;i< locals.Count;i++) { bw.Write(locals[i].LocalType.FullName); bw.Write(locals[i].IsPinned); } var il = mb.GetILAsByteArray(); for(int i = 0; i < il.Length;) { EArgumentType argType = EArgumentType.None; var opcode = (EOpCode)il[i]; bw.Write(il[i]); i++; if(opcode == EOpCode.Extended) { bw.Write(il[i]); argType = ((EExtendedOpCode)il[i]).ArgFor(); i++; } else argType = opcode.ArgFor(); switch (argType) { case EArgumentType.Field: var fi = module.ResolveField(BitConverter.ToInt32(il, i)); i += 4; bw.Write(Names.Field(fi)); break; case EArgumentType.Float32: bw.Write(BitConverter.ToSingle(il, i)); i += 4; break; case EArgumentType.Float64: bw.Write(BitConverter.ToDouble(il, i)); i += 8; break; case EArgumentType.Token: case EArgumentType.Int32: bw.Write(BitConverter.ToInt32(il, i)); i += 4; break; case EArgumentType.Int64: bw.Write(BitConverter.ToInt64(il, i)); i += 8; break; case EArgumentType.Int8: bw.Write((sbyte)il[i]); i++; break; case EArgumentType.ListOfInt: uint count = BitConverter.ToUInt32(il, i); bw.Write(count); i += 4; while(count > 0) { bw.Write(BitConverter.ToInt32(il, i)); i += 4; } break; case EArgumentType.Method: var mi = module.ResolveMethod(BitConverter.ToInt32(il, i)); i += 4; bw.Write(Names.Method(mi)); break; case EArgumentType.String: var str = module.ResolveString(BitConverter.ToInt32(il, i)); i += 4; bw.Write(str); break; case EArgumentType.Type: var t = module.ResolveType(BitConverter.ToInt32(il, i)); i += 4; bw.Write(t.FullName); break; case EArgumentType.Uint16: bw.Write(BitConverter.ToUInt16(il, i)); i += 2; break; case EArgumentType.Uint32: bw.Write(BitConverter.ToUInt32(il, i)); i += 4; break; case EArgumentType.Uint8: bw.Write(il[i]); i++; break; } } bw.Write((byte)EOpCode.Terminator); /* var handlers = mb.ExceptionHandlingClauses; m_bw.Write(handlers.Count); foreach(var h in handlers) { m_bw.Write(h.TryOffset); m_bw.Write(h.TryLength); m_bw.Write(h.FilterOffset); m_bw.Write(h.HandlerOffset); m_bw.Write(h.HandlerLength); m_bw.Write((uint)h.Flags); //m_bw.Write(h.) }*/ }
// Initialise the variables. TODO: Obey InitLocals void CopyLocals(ILGenerator Gen, MethodBody Body) { foreach(LocalVariableInfo Info in Body.LocalVariables) Gen.DeclareLocal(GrabType(Info.LocalType), Info.IsPinned); }
public EmitFuncObj(Module module, Function function, MethodBody cilMethod, InstructionBuilder instructionBuilder, object argument, Stack<Value> stack, Value[] locals, Value[] parameters) { Module = module; Function = function; CilMethod = cilMethod; Builder = instructionBuilder; Argument = argument; Stack = stack; Locals = locals; Parameters = parameters; }
public static void WriteSEH(MethodBody mb, BinaryWriter bw) { if (mb.ExceptionHandlingClauses.Count == 0) return; bool bTiny = IsSEHTiny(mb); if (bTiny) WriteTinySEHHeader(mb, bw); else WriteFatSEHHeader(mb, bw); foreach (ExceptionHandlingClause ehc in mb.ExceptionHandlingClauses) { if (bTiny) WriteSeHTinyRow(ehc, bw); else WriteSeHFatRow(ehc, bw); } }
MethodBodyReader (MethodBase method) { //wicky.patch.start: check DynamicMethod byte[] bytes; if (DynamicMethodHelper.IsDynamicOrRTDynamicMethod(method)) { DynamicMethod dynamicMethod = DynamicMethodHelper.GetDynamicMethod(method); this.method = dynamicMethod; bytes = DynamicMethodHelper.GetILAsByteArray(dynamicMethod); if (bytes == null) bytes = new byte[0]; if (dynamicMethod.DeclaringType != null) type_arguments = dynamicMethod.DeclaringType.GetGenericArguments(); this.parameters = dynamicMethod.GetParameters(); this.module = dynamicMethod.Module; //this.locals = ?? this.il = new ByteBuffer(bytes); this.tokenResolver = new DynamicScopeTokenResolver(dynamicMethod); } else { this.method = method; this.body = method.GetMethodBody(); if (this.body == null) bytes = new byte[0]; else bytes = body.GetILAsByteArray(); if (bytes == null) bytes = new byte[0]; bytes = body.GetILAsByteArray(); if (!(method is ConstructorInfo)) method_arguments = method.GetGenericArguments(); if (method.DeclaringType != null) type_arguments = method.DeclaringType.GetGenericArguments(); this.parameters = method.GetParameters(); this.locals = body.LocalVariables; this.module = method.Module; this.il = new ByteBuffer(bytes); this.tokenResolver = new ModuleScopeTokenResolver(method); } /* this.method = method; this.body = method.GetMethodBody (); if (this.body == null) throw new ArgumentException ("Method has no body"); var bytes = body.GetILAsByteArray (); if (bytes == null) throw new ArgumentException ("Can not get the body of the method"); if (!(method is ConstructorInfo)) method_arguments = method.GetGenericArguments (); if (method.DeclaringType != null) type_arguments = method.DeclaringType.GetGenericArguments (); this.parameters = method.GetParameters (); this.locals = body.LocalVariables; this.module = method.Module; this.il = new ByteBuffer (bytes); */ //wicky.patch.end }
public ControlFlowGraph(NetMethodBody body, Module module, Type[] genericTypeArguments, Type[] genericMethodArguments) { // Convert the byte code into instruction objects ushort ip = 0; byte[] il = body.GetILAsByteArray(); List <IInstruction> instructions = new List <IInstruction>(); while (ip < il.Length) { instructions.Add(OpCodeTable.GetInstruction(il, ref ip, module, genericTypeArguments, genericMethodArguments)); } // Iterate the instructions building a list of call graph nodes SortedList <ushort, CallGraphNode> nodes = new SortedList <ushort, CallGraphNode>(); CallGraphNode node = new CallGraphNode(0); nodes.Add(0, node); int index = 0; IInstruction instruction = instructions[index]; do { Console.Write(instruction); // Create the nodes that this instruction branches to switch (instruction.OpCode.FlowControl) { case FlowControl.Branch: { if ((instruction.OpCode != OpCodes.Leave) && (instruction.OpCode != OpCodes.Leave_S)) { // Direct branch to a new instruction that is not a leave instruction from a try-catch block. // Create a call graph node for the target of the branch. MakeNode((ushort)instruction.Argument, nodes); Console.Write(" <-- Branch {0:x4}", instruction.Argument); } break; } case FlowControl.Cond_Branch: { if (instruction.OpCode.Value == OpCodes.Switch.Value) { // Conditional branch to n-blocks foreach (ushort switchTargetIp in (ushort[])instruction.Argument) { MakeNode(switchTargetIp, nodes); } } else { // Conditional branch to two blocks MakeNode((ushort)instruction.Argument, nodes); Console.WriteLine("Making " + instruction.Argument); } // Set the next instruction of a branch to also be a target MakeNode(instructions[index + 1].IP, nodes); Console.Write(" <-- If Node {0:x4}", instruction.Argument); break; } case FlowControl.Return: // Set the next instruction of a branch to also be a target Console.Write(" <-- Exit Node"); break; case FlowControl.Throw: // End of graph Console.Write(" <-- Throw Node"); break; case FlowControl.Break: case FlowControl.Call: case FlowControl.Meta: case FlowControl.Next: #pragma warning disable 612,618 case FlowControl.Phi: #pragma warning restore 612,618 // Add the continuation link //node.NodeType = NodeType.FallThrough; //MakeNode(ip, node, nodes); break; } Console.WriteLine(); // Get the next instruction index++; if (index < instructions.Count) { instruction = instructions[index]; // Find the node to add the next instruction to CallGraphNode nextNode; if (nodes.TryGetValue(instruction.IP, out nextNode)) { /*if (node.NodeType == NodeType.FallThrough) * { * Console.Write("added fall through link "); * node.OutEdges.Add(nextNode); * nextNode.InEdges.Add(node); * }*/ node = nextNode; Console.Write("New Node --> "); } } } while (index < instructions.Count); Console.WriteLine(); // Iterate the instructions a second time adding them to the correct nodes //CallGraphNode node; node = nodes[0]; for (index = 0; index < instructions.Count; index++) { instruction = instructions[index]; if (index > 0) { CallGraphNode nextNode; if (nodes.TryGetValue(instruction.IP, out nextNode)) { if (node.OutEdges.Count == 0) { Console.WriteLine("ff"); node.NodeType = NodeType.FallThrough; LinkNode(node, nextNode); } Console.Write("--" + node.OutEdges.Count + "--"); node = nextNode; Console.Write("new node "); } } Console.WriteLine(instruction); node.Instructions.Add(instruction); // Create the nodes that this instruction branches to switch (instruction.OpCode.FlowControl) { case FlowControl.Branch: { if ((instruction.OpCode != OpCodes.Leave) && (instruction.OpCode != OpCodes.Leave_S)) { // Direct branch to a new instruction that is not a leave instruction from a try-catch block. // Create a call graph node for the target of the branch. node.NodeType = NodeType.OneBranch; LinkNode(node, nodes[(ushort)instruction.Argument]); Console.Write(" <-- Branch {0:x4}", instruction.Argument); } break; } case FlowControl.Cond_Branch: { if (instruction.OpCode.Value == OpCodes.Switch.Value) { // Conditional branch to n-blocks node.NodeType = NodeType.MultiBranch; foreach (ushort switchTargetIp in (ushort[])instruction.Argument) { LinkNode(node, nodes[switchTargetIp]); } } else { // Conditional branch to two blocks node.NodeType = NodeType.TwoBranch; LinkNode(node, nodes[(ushort)instruction.Argument]); Console.Write("Linking " + instruction.Argument); } // Set the next instruction of a branch to also be a target LinkNode(node, nodes[instructions[index + 1].IP]); Console.Write(" <-- If Node {0:x4}", instruction.Argument); break; } case FlowControl.Return: // Set the next instruction of a branch to also be a target node.NodeType = NodeType.Exit; Console.Write(" <-- Exit Node"); break; case FlowControl.Throw: // End of graph node.NodeType = NodeType.Throw; Console.Write(" <-- Throw Node"); break; } } // Copy the nodes to a simple list _nodes.AddRange(nodes.Values); Console.WriteLine(); Console.WriteLine(_nodes.Count); foreach (CallGraphNode n in _nodes) { Console.WriteLine(n.StartIP + " " + n.NodeType + " " + n.OutEdges.Count); } CheckGraph(); // Add the exception information - build a sorted tree of clauses SortedList <int, TryHandler> clauses = new SortedList <int, TryHandler>(); foreach (ExceptionHandlingClause clause in body.ExceptionHandlingClauses) { Add(new TryHandler(clause), clauses); } foreach (TryHandler clause in clauses.Values) { TraverseExceptionTree(clause); } // Find the root node -- This fails when there are multiple try statements on the first instruction for (int i = 0; i < _nodes.Count; i++) { if (_nodes[i].StartIP == 0) { _rootNode = _nodes[i]; break; } } if (_rootNode == null) { throw new ApplicationException("Unable to find a root node"); } CheckGraph(); // Remove redundancies and add in-edge information Optimize(); CheckGraph(); // Visit the graph in depth first order and label the nodes _depthFirstSearchLast = new CallGraphNode[_nodes.Count]; int last = _nodes.Count - 1; DepthFirstTraverse(_rootNode, ref last); // Find the immediate dominators of each node FindImmediateDominators(); // Check the graph for reducibility FindDerivedSequence(); // Work out the graphs back edges DetermineBackEdges(); ResetTraversal(); StructureCases(); StructureLoops(); StructureIfs(); ResetTraversal(); }
static void Main(string[] args) { module = ModuleDefMD.Load(args[0]); AssemblyName assemblyName = AssemblyName.GetAssemblyName(args[0]); Assembly assembly = Assembly.Load(assemblyName); Module Module_L = assembly.GetModules()[0]; mod = Module_L; foreach (EmbeddedResource res in module.Resources) { if (res.Name == "Eddy^CZ_") { using (new StreamReader(res.GetResourceStream())) { byte[] ar = new byte[res.GetResourceStream().Length]; res.GetResourceStream().Read(ar, 0, ar.Length); byteArrayResource = ar; } } } byte[] buffer = null; foreach (EmbeddedResource res in module.Resources) { if (res.Name == "Eddy^CZ") { using (new StreamReader(res.GetResourceStream())) { byte[] arr = new byte[res.GetResourceStream().Length]; res.GetResourceStream().Read(arr, 0, arr.Length); buffer = arr; } } } binr = new BinaryReader(new MemoryStream(buffer)); All.val = new ValueStack(); All.val.parameters = new object[1]; All.val.parameters[0] = byteArrayResource; All.val.locals = new object[10]; All.run(binr); bool flag = IntPtr.Size == 4; IntPtr ptr = default(IntPtr); if (flag) { ExtractEmbeddedDlls("NativePRo.dll", File.ReadAllBytes(Directory.GetCurrentDirectory() + "\\X86")); IntPtr intptr = LoadDll("NativePRo.dll"); ptr = Inisialize.e(intptr, "_a@16"); } else { ExtractEmbeddedDlls("NativePRo.dll", File.ReadAllBytes("X64")); IntPtr intptr = LoadDll("NativePRo.dll"); ptr = Inisialize.e(intptr, "a"); } Inisialize.bc = (Inisialize.a)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Inisialize.a)); byteArrayResource = (byte[])All.val.locals[1]; OpCode[] array = new OpCode[256]; OpCode[] array2 = new OpCode[256]; oneByteOpCodes = array; twoByteOpCodes = array2; Type typeFromHandle = typeof(OpCode); Type typeFromHandle2 = typeof(OpCodes); foreach (FieldInfo fieldInfo in typeFromHandle2.GetFields()) { bool flag2 = fieldInfo.FieldType == typeFromHandle; if (flag2) { OpCode opCode = (OpCode)fieldInfo.GetValue(null); ushort num = (ushort)opCode.Value; bool flag3 = opCode.Size == 1; if (flag3) { byte b = (byte)num; oneByteOpCodes[(int)b] = opCode; // Console.WriteLine(opCode.Name); } else { byte b2 = (byte)(num | 65024); twoByteOpCodes[(int)b2] = opCode; //Console.WriteLine(opCode.Name); } } } foreach (var type in module.Types) { try { foreach (var method in type.Methods) { try { if (is_virualized(method)) { List <dnlib.DotNet.Emit.Instruction> real = new List <dnlib.DotNet.Emit.Instruction>(); for (int i = 0; i < method.Body.Instructions.Count; i++) { try { if (method.Body.Instructions[i].OpCode == dnlib.DotNet.Emit.OpCodes.Call) { if (method.Body.Instructions[i].Operand.ToString().Contains("Runner")) { #region Resolve Method int md = (int)((MethodDef)method).MDToken.Raw; MethodBase callingMethod = Module_L.ResolveMethod(md); dnlib.DotNet.Emit.Instruction instr = new dnlib.DotNet.Emit.Instruction(); #endregion #region Параметры int position = method.Body.Instructions[i - 4].GetLdcI4Value(); int size = method.Body.Instructions[i - 3].GetLdcI4Value(); int ID = method.Body.Instructions[i - 2].GetLdcI4Value(); Console.WriteLine("Recovering Method - " + method.FullName + "_Keys --_--" + position.ToString() + "--_--" + size.ToString() + "--_--" + ID.ToString()); #endregion #region асшифровка Опкодов byte[] array4 = byteArrayGrabber(byteArrayResource, position, size); byte[] key = MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(method.Name)); byte[] ilasByteArray = callingMethod.GetMethodBody().GetILAsByteArray(); Inisialize.bc(array4, array4.Length, ilasByteArray, ilasByteArray.Length); byte[] bytes = Decrypt(key, array4); #endregion #region Получение Опкодов из Ресурсов System.Reflection.MethodBody methodBody = callingMethod.GetMethodBody(); BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes)); ParameterInfo[] parameters2 = callingMethod.GetParameters(); List <LocalBuilder> list = new List <LocalBuilder>(); int num = 0; bool isStatic = callingMethod.IsStatic; Type[] array5; if (isStatic) { array5 = new Type[parameters2.Length]; } else { array5 = new Type[parameters2.Length + 1]; array5[0] = callingMethod.DeclaringType; num = 1; } for (int z = 0; z < parameters2.Length; z++) { ParameterInfo parameterInfo = parameters2[z]; array5[num + z] = parameterInfo.ParameterType; } DynamicMethod dynamicMethod = new DynamicMethod("", (callingMethod.MemberType == MemberTypes.Constructor) ? null : ((MethodInfo)callingMethod).ReturnParameter.ParameterType, array5, Module_L, true); ILGenerator ilgenerator = dynamicMethod.GetILGenerator(); IList <LocalVariableInfo> localVariables = methodBody.LocalVariables; foreach (LocalVariableInfo localVariableInfo in localVariables) { list.Add(ilgenerator.DeclareLocal(localVariableInfo.LocalType)); } int count = binaryReader.ReadInt32(); int num2 = binaryReader.ReadInt32(); Dictionary <int, Label> dictionary = new Dictionary <int, Label>(); for (int j = 0; j < num2; j++) { Label value = ilgenerator.DefineLabel(); dictionary.Add(j, value); } for (int k = 0; k < num2; k++) { short num3 = binaryReader.ReadInt16(); bool flags = num3 >= 0 && (int)num3 < oneByteOpCodes.Length; OpCode opcode; if (flags) { opcode = oneByteOpCodes[(int)num3]; } else { byte b = (byte)((int)num3 | 65024); opcode = twoByteOpCodes[(int)b]; } #endregion byte opType = binaryReader.ReadByte(); object a = OperandInitialiser.Initialise(opType, binaryReader, assembly.GetModules()[0], dictionary, list); try { real.Add(OpcodeConverter.converter(opcode, a, binaryReader, assembly.GetModules()[0])); } catch { } } } } } catch (Exception ex) { } } method.Body.Instructions.Clear(); foreach (var fes in real) { method.Body.Instructions.Add(fes); } } } catch (Exception ex) { } } } catch { } } module.Write("lsd.exe", new ModuleWriterOptions(module) { MetaDataOptions = { Flags = MetaDataFlags.PreserveAll }, Logger = DummyLogger.NoThrowInstance }); Console.WriteLine("================================="); Console.ReadLine(); }
private static void AnalizeMore(MethodBody methodBody, byte[] il, Action<string[]> self) { Console.ReadLine(); // 分岐ターゲットが正しく取得できたので、分岐フローを元に構造認識が可能になります // 構造認識では、制御フローに関するステートメントに着目したいため、制御フロー影響 // の無い命令群をまとめてそれらと制御フローの関連付けができる単位が必要になります。 var exceptionHandlingClauses = methodBody.ExceptionHandlingClauses.ToArray(); GettingControlFlowElement(il, exceptionHandlingClauses); Console.ReadLine(); // 制御構造の認識ができると、IL上でプログラムがどのように進行するかという動作パスを // 考える事ができるようになります。動作パスを意識する事で、IL命令がどの順に実行され // えるのかが分かります。 var controlFlow = Msil.PopulateControlFlowPath(il, exceptionHandlingClauses); Console.WriteLine(controlFlow.Count + " path found"); Console.WriteLine(controlFlow.First().Key); Console.ReadLine(); // 動作パスが列挙されたので、その動作パスを使ってILの評価スタックをシミュレートする // と、どのIL命令がどのIL命令の出力を使うのかというデータ依存関係が得られます。 // このデータ依存関係は、最終的にローカル変数やフィールドに書かれる物がどのように計算 // されるのか、条件分岐命令の条件はいったい何なのかを表現します。 var ilinsts = Msil.ILInstructions(il).ToArray(); var runs = Msil.GetRuns(ilinsts,il.Length, exceptionHandlingClauses).ToArray(); var dataFlowSource = new Dictionary<int, List<Tuple<int, int>>>(); foreach (var flow in controlFlow) { Msil.SimulateEvalStack(runs, flow.Value, dataFlowSource, self.Method.Module); } DisassembleWithDataFlow(runs, dataFlowSource); Console.ReadLine(); // 依存関係グラフを再帰的に追う事でプログラム内のデータ依存関係を式風に表示する事も // できます。 var setlocalOpCodes = new[] { OpCodes.Stloc.Value, OpCodes.Stloc_0.Value, OpCodes.Stloc_1.Value, OpCodes.Stloc_2.Value, OpCodes.Stloc_3.Value, OpCodes.Stloc_S.Value }; foreach (var run in runs) { Console.WriteLine("IL_{0:X4}:",run.StartIndex); foreach (var instruction in run.Instructions) { var opCode = instruction.OpCode; if (setlocalOpCodes.Contains(opCode.Value)) { var localIndex = instruction.GetLocalIndex(); var startIndex = instruction.StartIndex; List<Tuple<int, int>> source; string sourceDesc; if (!dataFlowSource.TryGetValue(startIndex, out source)) { sourceDesc = "/* unknown */"; // 例外による動作フローを追わない為、例外系での処理が認識されません } else { var popCnts = source.Select(t => t.Item1).Distinct().OrderBy(n => n); var sources = popCnts.Select( popCnt => string.Join(" or ", source.Where(t => t.Item1 == popCnt) .Distinct() .Select(t => "(" + Describe(t.Item2, ilinsts, dataFlowSource,self.Method.Module) + ")"))).ToList(); sourceDesc = string.Join(",", sources); } Console.WriteLine(" local_{0} = {1}", localIndex, sourceDesc); } if (opCode.Value == OpCodes.Call.Value || opCode.Value == OpCodes.Calli.Value || opCode.Value == OpCodes.Callvirt.Value) { // 結果がどこにも使われない call は表示 if (dataFlowSource.Values.SelectMany(_ => _).All(t => t.Item2 != instruction.StartIndex)) { Console.WriteLine(" {0}", Describe(instruction.StartIndex, ilinsts, dataFlowSource, self.Method.Module)); } } if (opCode.FlowControl == FlowControl.Cond_Branch ) { if (opCode.Value != OpCodes.Switch.Value) { Console.WriteLine(" {0} goto IL_{1:X4}", Describe(instruction.StartIndex, ilinsts, dataFlowSource, self.Method.Module), instruction.GetBranchLocation()); } else { Console.WriteLine(" {0} {1}", Describe(instruction.StartIndex, ilinsts, dataFlowSource, self.Method.Module), string.Join(", ",instruction.GetBranchLocations().Select(n=> string.Format("IL_{0:X4}",n))) ); } } if (opCode.FlowControl == FlowControl.Branch) { Console.WriteLine(" goto IL_{0:X4}", instruction.GetBranchLocation()); } } } Console.ReadLine(); }
/// <summary> /// Validates an actual method body (the cloned version) against an expected method body (its source). /// </summary> /// <param name="actualMethodBody">Method body to validate.</param> /// <param name="expectedMethodBody">Method body with expeted info.</param> private static void ValidateMethodBody(MethodBody actualMethodBody, MethodBody expectedMethodBody) { Assert.That(actualMethodBody == null, Is.EqualTo(expectedMethodBody == null)); if (actualMethodBody == null) { return; } Assert.That(actualMethodBody.InitLocals, Is.EqualTo(expectedMethodBody.InitLocals)); Assert.That(actualMethodBody.MaxStackSize, Is.EqualTo(expectedMethodBody.MaxStackSize)); Assert.That(actualMethodBody.ExceptionHandlingClauses.Count, Is.EqualTo(expectedMethodBody.ExceptionHandlingClauses.Count)); for (int i = 0; i < actualMethodBody.ExceptionHandlingClauses.Count; i++) { ValidateExceptionHandlingClause(actualMethodBody.ExceptionHandlingClauses[i], expectedMethodBody.ExceptionHandlingClauses[i]); } Assert.That(actualMethodBody.LocalVariables.Count, Is.EqualTo(expectedMethodBody.LocalVariables.Count)); for (int i = 0; i < actualMethodBody.LocalVariables.Count; i++) { ValidateLocalVariable(actualMethodBody.LocalVariables[i], expectedMethodBody.LocalVariables[i]); } }
public static void WriteILCode(MethodBody mb, BinaryWriter writer) { int codesize = mb.GetILAsByteArray().Length; writer.Write(mb.GetILAsByteArray()); // 对齐 4 bytes int ig = codesize & 3; if (ig == 0) return; if (mb.ExceptionHandlingClauses.Count == 0) return;//无SEH; ig = 4 - ig; for(int i=0; i<ig;i++) { writer.Write((byte)0); } }
public ILReader(MethodBase InputMethod, FieldInfo[] FieldsInModule, MethodBase[] MethodsInModule, Assembly currentAssm) { workingAssm = currentAssm; MethodOpcodes = new ArrayList(); InputMeth = InputMethod; ExceptionHandlers = new ArrayList(); if (InputMethod == null) { Console.WriteLine("Error, input method is not specified, can not continue"); return; } methodBody = InputMethod.GetMethodBody(); curModule = InputMethod.DeclaringType.Module; pos = 0; pos1 = 0; IL = methodBody.GetILAsByteArray(); IList<ExceptionHandlingClause> ehClauses = methodBody.ExceptionHandlingClauses; foreach( ExceptionHandlingClause ehclause in ehClauses ) { ExceptionHandlers.Add(new ExceptionInstruction(ehclause.TryOffset,ExceptionHandler.Try,null)); switch (ehclause.Flags) { //case 0: case ExceptionHandlingClauseOptions.Clause: ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.Catch,ehclause.CatchType)); ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null)); break; //case 1: case ExceptionHandlingClauseOptions.Filter: ExceptionHandlers.Add(new ExceptionInstruction(ehclause.FilterOffset,ExceptionHandler.Filter,null)); ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.EndFilter,null)); ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null)); break; //case 2: case ExceptionHandlingClauseOptions.Finally: ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.Finally,null)); ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null)); break; //case 4: case ExceptionHandlingClauseOptions.Fault: ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.Fault,null)); ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null)); break; } } // populate opcode Opcode Op = GetOpcode(); while (Op.Name != "") // This cycles through all the Opcodes { if (Op.Name != "stfld") MethodOpcodes.Add(Op); Op = GetOpcode(); } // sort the stfld opcodes and output // this will make the opcode invalid for run. // but out purpose is simply compare the assemblies. StfldList.Sort(new StringCompare()); foreach (object i in StfldList) { Opcode temp = new Opcode("stfld", i); MakeLabel(temp, false); MethodOpcodes.Add(temp); } }
public static void WriteTinySEHHeader(MethodBody mb, BinaryWriter bw) { int n = mb.ExceptionHandlingClauses.Count; int datasize = n * 12 + 4; bw.Write((byte)1); bw.Write((byte)datasize); bw.Write((byte)0); bw.Write((byte)0); }
private void ExamineLocalVariables(MethodBody body, MethodInfo method = null) { Console.WriteLine("\n\t\t-- Local variables"); body.LocalVariables.ToList().ForEach(x => Console.WriteLine("\t\t| " + x)); Console.WriteLine("\t\t-- End of local variables\n"); }
public MethodBody(System.Reflection.MethodBody body) : this(body, false) { }
public MethodBody(System.Reflection.MethodBody body, bool loadDebugInfo) : this(body.AssertNotNull().Get("m_methodBase").AssertCast <MethodBase>(), loadDebugInfo) { }
private MethodBodyReader(MethodBase method, MethodBody mb) { this.method = method; body = mb; if (body == null) throw new ArgumentException(); var bytes = body.GetILAsByteArray(); if (bytes == null) throw new ArgumentException(); if (!(method is ConstructorInfo)) method_arguments = method.GetGenericArguments(); if (method.DeclaringType != null) generic_type_arguments = method.DeclaringType.GetGenericArguments(); parameters = method.GetParameters(); locals = body.LocalVariables; module = method.Module; il = new ByteBuffer(bytes); }
internal IMethodBody GetBody(MethodBody methodBody) { throw new NotImplementedException(); }