c# - 跳过对没有 DynamicMethod 的动态生成方法的可见性检查

标签 c# cil code-access-security ilgenerator

这个问题与另外两个问题非常相似,请参阅:first , second 。然而,至少可以说这些已经过时了,我希望 .Net 5 能够改变一切。

现在首先让我澄清一下这个问题。通过一个简单的示例,尝试获取 List<int>. 的底层数组

var method = new DynamicMethod("GetUnderlyingArray", typeof(int[]), new[] { typeof(List<int>) }, typeof(List<int>), true);

var ilGenerator = method.GetILGenerator();

ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldfld, typeof(List<int>).GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance));
ilGenerator.Emit(OpCodes.Ret);

var arrayGetter = (Func<List<int>, int[]>)method.CreateDelegate(typeof(Func<List<int>, int[]>));

这工作得很好,因为我可以告诉 DynamicMethod跳过可见性检查(尽管当 DynamicMethod 构造函数 true 的最后一个参数被删除时它也能工作)。

但是,当我尝试对下面的示例执行相同操作时,它将抛出 FieldAccessException .

var assemblyName = new AssemblyName("Example");
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var dynamicModule = assemblyBuilder.DefineDynamicModule(assemblyName.Name + ".dll");

var type = dynamicModule.DefineType("GetUnderlyingArrayClass");

var method = type.DefineMethod("GetUnderlyingArray", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static, typeof(int[]), new[] { typeof(List<int>) });

var ilGenerator = method.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldfld, typeof(List<int>).GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance));
ilGenerator.Emit(OpCodes.Ret);

type.CreateType();

var arrayGetter = (Func<List<int>, int[]>)type.GetMethod("GetUnderlyingArray").CreateDelegate(typeof(Func<List<int>, int[]>));

System.FieldAccessException: Attempt by method 'GetUnderlyingArrayClass.GetUnderlyingArray(System.Collections.Generic.List'1)' to access field 'System.Collections.Generic.List'1<System.Int32>._items' failed. + GetUnderlyingArrayClass.GetUnderlyingArray(List)

Here is a .Net fiddle link with the code shown above.

现在,我提到的问题之一指向以下属性 ReflectionPermissionAttribute 。然而,正如文档 Code Access Security is not supported or honored by the runtime. 中所述。据我了解,这基本上意味着 .Net Core/.Net 5 do not support CAS .

这就是我感到困惑的地方。设置skipVisibility参数truefalse其实并不重要。我认为这是因为我在 .Net 5 环境中运行代码。但是,如果 .Net 5 不支持 CAS,为什么我仍然能够读出私有(private)字段?

目标显然是使用DefineType从动态生成的方法访问私有(private)字段/方法。/DefineMethod API。

最佳答案

我仍然无法解释为什么将 skipVisibility 参数设置为 true/false 并不重要,但是 PathogenDavid在 GitHub 上,来自 csharp runtime discussion repository向我展示了一个比预期更容易的解决方案。

// Add IgnoresAccessChecksTo attribute
var ignoresAccessChecksTo = new CustomAttributeBuilder
(
    typeof(IgnoresAccessChecksToAttribute).GetConstructor(new Type[] { typeof(string) }),
    new object[] { typeof(List<>).Assembly.GetName().Name }
);

assemblyBuilder.SetCustomAttribute(ignoresAccessChecksTo);

参见this .Net Fiddle 的工作示例。

正如他所说,IgnoresAccessChecksTo 属性用于绕过检查。

The runtime understands the attribute, but it is not defined in the BCL so you have to define it yourself.

关于c# - 跳过对没有 DynamicMethod 的动态生成方法的可见性检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66094780/

相关文章:

c# - WebBrowser 控件和通过 ID 获取元素

c# - 如何测试事件是否包含事件处理程序?

c# - TPL 数据流,BroadcastBlock 到 BatchBlocks

C# (MSIL) 到 native X86 代码?

c# - 如何将 VC++ 2015 可再发行组件与我的 ClickOnce (.NET) 应用程序捆绑在一起?

c# - 为什么不能使用反射获取局部变量名?

.net - 修改现有的 .NET 程序集

asp.net - Web App 在本地主机上工作但在远程连接上失败

asp.net - ASP.NET 4.0 中的信任级别是否已过时?

git - 如何将代码 checkout 仅限于某个用户/机器组合