给定一个实用程序方法,该方法搜索支持您没有Set访问权限的属性的Field。一旦我让它在我的机器上工作,是否有任何环境条件会导致它失败?对于给定的程序集,无论在何种条件下运行应用程序,GetILAsByteArray返回的IL是否始终相同?
public static class HackUtil
{
public static FieldInfo GetFieldBackingProperty(System.Reflection.PropertyInfo prop)
{
var acc = prop.GetAccessors().Where(x => x.ReturnType != typeof(void)).First();
var mb = acc.GetMethodBody();
var ilb = mb.GetILAsByteArray();
var ldField = ilb.Skip(ilb.Length - 6).ToArray();
// try to match a getter like: get { return myVar; }
if (ldField[0] == 0x7b /*ldfield opcode*/ && ldField[ldField.Length - 1] == 0x2a /*ret opcode*/)
{
var fields = prop.DeclaringType.GetFields(System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.DeclaredOnly);
// so the 4 bytes between those two opcodes should be our metadatatoken
var matchingField = (from f in fields
where f.MetadataToken == BitConverter.ToUInt32(ldField, 1)
select f).FirstOrDefault();
return matchingField;
}
return null;
}
}
如果是这样的话,有什么想法可以弥补这一点吗?
对于给定程序集,无论在何种条件下运行应用程序,从
GetILAsByteArray
返回的IL是否始终相同
是,如果程序集仍然相同。
一旦编译器生成了程序集(以及其中的IL),其内容就不会在正常使用中发生更改。正常使用包括让.NET Framework将程序集加载到内存中,让它JIT将IL代码编译为程序集代码,以及执行方法。
请记住,IL只是一种中间语言。将其视为生成汇编代码的蓝图。因此,运行时不需要更改IL:如果他们想更改方法的实现(例如出于优化原因),他们将调整的是汇编代码,而不是IL。
话虽如此,我可以看到一些可能性,即如何改变程序集中的IL;不过,它们都与在不同的环境中运行程序无关。
-
如果程序集不是强名称(即使用安全证书进行散列和签名),则有人可能在磁盘上篡改/修改它,例如使用Mono-Cecil或Microsoft的通用编译器基础结构(CCI)等库。
如果您希望保证程序集在生成后不会在没有注意到的情况下进行修改,请确保其具有强名称。
-
公共语言运行时(CLR)的非托管评测API提供了用新实现替换方法的功能。
例如参见MSDN杂志的文章";用.NET Framework评测API(.NET内部构件)"动态重写MSIL代码";亚历山大·米库诺夫。
-
当您在Visual Studio中调试程序集并在程序集运行时对其进行更改(即编辑并继续功能)时,我不知道是否可以通过反射看到这些更改。