确保c#Assemby是确定性的

时间:2017-11-20 07:44:13

标签: c# deterministic non-deterministic

可以限制特定的类,例如 Random DateTime ,或者在AppDomain中使用 float 。如果使用它们,是否可以通过反射检测它?或者我们应该查看IL代码?

我想创建一个插件系统,但我必须确保执行的代码是确定性的。关于如何处理它的任何其他想法?

感谢。

2 个答案:

答案 0 :(得分:1)

您可以使用类似Cecil [*]的内容查看IL。但话说回来,有可能通过反思来访问这些东西。

[*]:这需要一些时间,提示您缓存结果...,这会引入一个漏洞,攻击者会在其中模仿缓存中的有效条目。

另一方面,您可以使用sandbox without Reflection。你必须将它与上述方法结合起来。

然后,有一些方法可以模仿你所描述的行为...例如,你可以创建你自己的Random Number Generator(顺便提一下,这是完全确定的)并用当前时间播种或entropy的其他来源(您可能希望拒绝访问文件系统和网络,甚至拒绝访问外围设备和其他系统状态 - 例如,脚本可能会产生不同的结果,具体取决于指针位置)。 / p>

因此,我建议使用whitelist代替blacklist作为Damien_The_Unbeliever suggests

答案 1 :(得分:0)

创建类型白名单可以完成该工作

 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()));
        }
    }