简体   繁体   English

确保c#Assemby是确定性的

[英]Ensure that c# Assemby are deterministic

It is possible to restrict specific classes, such as Random or DateTime , or the use of float in an AppDomain. 可以限制特定的类,例如RandomDateTime ,或在AppDomain中使用float Is it possible to detect it by reflection if you use them? 如果使用它们,是否可以通过反射检测到? or should we look at the IL code? 还是我们应该看看IL代码?

I would like to make a plugin system, but I have to make sure that the executed code is deterministic. 我想制作一个插件系统,但是我必须确保执行的代码是确定性的。 Any other ideas on how to deal with it? 关于如何处理它还有其他想法吗?

Thanks. 谢谢。

You could look at the IL with something like Cecil [*]. 您可以使用Cecil [*]之类的东西查看IL。 But then again, it is possible to get access to those things via reflection. 但是话又说回来,有可能通过反射来访问那些东西。

[*]: Which would take some time, prompting you to cache the results..., which would introduce a vulnerability in which the attacker mimic a valid entry in the cache. [*]:这将花费一些时间,提示您缓存结果...,这将引入一个漏洞,攻击者将在其中模仿缓存中的有效条目。

On the other hand, you could use a sandbox without Reflection . 另一方面,您可以使用没有Reflection沙箱 You will have to combine that with the above approach. 您将不得不将其与上述方法结合起来。

Then, there are ways to mimic the behavior of what you describe... for example, you can create your own Random Number Generator (which is something totally deterministic, by the way) and seed it with the current time or other source of entropy (you probably want to deny access to the file system and the network, and even to peripherals and other system status - for example an script could yield a different result depending on the pointer position). 然后,有一些方法可以模仿您所描述的行为……例如,您可以创建自己的随机数生成器 (顺便说一句,它完全是确定性的)并用当前时间或其他源进行播种(您可能想拒绝访问文件系统和网络,甚至拒绝访问外围设备和其他系统状态-例如,根据指针位置,脚本可能会产生不同的结果)。

Thus, I would suggest to have a whitelist instead of blacklist as Damien_The_Unbeliever suggests . 因此,我建议像Damien_The_Unbeliever建议的那样具有白名单而不是黑名单

Creating Type white list is possible to do that job 创建类型白名单可以做到这一点

 readonly static List<string> WhiteList = new List<string>()
    {
        #region Basics
        typeof(Boolean).FullName,
        typeof(Char).FullName,
        typeof(String).FullName,
        typeof(Byte).FullName,
        typeof(SByte).FullName,
        typeof(UInt16).FullName,
        typeof(Int16).FullName,
        typeof(UInt32).FullName,
        typeof(Int32).FullName,
        typeof(UInt64).FullName,
        typeof(Int64).FullName,
        typeof(Decimal).FullName,
        typeof(Double).FullName,
        typeof(Single).FullName,
        typeof(TimeSpan).FullName,

        typeof(Array).FullName,
        typeof(Enum).FullName,
        #endregion

        #region Exceptions
        typeof(Exception).FullName,
        typeof(NotImplementedException).FullName,
        typeof(IOException).FullName,
        #endregion

        #region Delegates
        typeof(Delegate).FullName,
        #endregion

        #region Parallel
        typeof(Parallel).FullName,
        #endregion

        #region Conversions
        typeof(Convert).FullName,
        typeof(BitConverter).FullName,
        #endregion

        #region Streams
        typeof(Stream).FullName,
        typeof(MemoryStream).FullName,
        typeof(BinaryReader).FullName,
        typeof(BinaryWriter).FullName,
        #endregion

        #region Interfaces
        typeof(IDisposable).FullName,
        typeof(IComparable).FullName,
        typeof(IConvertible).FullName,
        typeof(IFormatProvider).FullName,
        typeof(IFormattable).FullName,
        typeof(IOrderedQueryable).FullName,
        #endregion

        #region Attributes
        typeof(Attribute).FullName,

        // Compilation JIT
        typeof(CompilationRelaxationsAttribute).FullName,
        typeof(RuntimeCompatibilityAttribute).FullName,
        typeof(CompilerGeneratedAttribute).FullName,
        #endregion

        #region Generic Types
        typeof(IDictionary<object,object>).Namespace+"."+typeof(IDictionary<object,object>).Name,
        typeof(Dictionary<object,object>).Namespace+"."+typeof(Dictionary<object,object>).Name,
        typeof(List<object>).Namespace+"."+typeof(List<object>).Name,
        typeof(IList<object>).Namespace+"."+typeof(IList<object>).Name,
        typeof(IEnumerable<object>).Namespace+"."+typeof(IEnumerable<object>).Name,
        typeof(IEnumerator<object>).Namespace+"."+typeof(IEnumerator<object>).Name,
        typeof(IOrderedEnumerable<object>).Namespace+"."+typeof(IOrderedEnumerable<object>).Name,
        typeof(IOrderedQueryable<object>).Namespace+"."+typeof(IOrderedQueryable<object>).Name,
        typeof(ICollection<object>).Namespace+"."+typeof(ICollection<object>).Name,
        typeof(IComparable<object>).Namespace+"."+typeof(IComparable<object>).Name,
        typeof(IEquatable<object>).Namespace+"."+typeof(IEquatable<object>).Name,
        typeof(IObservable<object>).Namespace+"."+typeof(IObservable<object>).Name,
        #endregion
    };

    const string WhiteListedNamespace = "XX.XXXXXXXXXX.";

    /// <summary>
    /// Check white list
    /// </summary>
    /// <param name="binary">Binary</param>
    public static void CheckWhiteList(byte[] binary)
    {
        using (MemoryStream ms = new MemoryStream(binary))
        {
            AssemblyDefinition def = AssemblyDefinition.ReadAssembly(ms, new ReaderParameters(ReadingMode.Immediate));

            List<string> ls = new List<string>();
            foreach (ModuleDefinition mdef in def.Modules)
                foreach (TypeReference tdef in mdef.GetTypeReferences())
                {
                    if (!WhiteList.Contains(tdef.FullName) &&
                        !tdef.FullName.StartsWith(WhiteListedNamespace, StringComparison.InvariantCulture))
                        ls.Add(tdef.FullName);
                }

            if (ls.Count > 0)
                throw (new TypeNotAllowedException(ls.ToArray()));
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM