如何检测和管理加载的DLL执行的磁盘/注册表/网络活动?

问题描述 投票:3回答:2

假设我的应用程序实现了一个允许用户从外部DLL文件动态加载和执行代码的插件/扩展系统,那么我将如何管理磁盘,注册表和网络访问(读/写/删除)方面的安全性?

更具体地说,我希望能够知道插件/扩展即将执行磁盘/注册表/网络操作,拦截该操作并根据一组预定义规则允许或拒绝它,或者只是询问用户,如果他们允许对该特定插件的某种类型的访问。

c# security networking io registry
2个回答
0
投票

对于绝对解决方案,您将不得不使用内核驱动程序来拦截请求。但如果你不需要100%,你可以开发一个类似于API Monitor的工具。

工具挂钩API函数,(很少有这样的库,MSDetour,Mhook等),可以记录通话或中断通话。通过检查堆栈,知道哪个模块也可以调用API。


0
投票

使用AppDomains和代码访问安全性可以实现某些控制。您可以创建沙盒AppDomain并将其权限授予您希望插件访问的目录。如果插件尝试在其外部访问文件,则会获得SecurityException。

例如,如果我们有以下ClassLib.dll插件:

namespace ClassLib
{
    public class Class1
    {
        public static string DoWork(string path)
        {
            return System.IO.File.ReadAllText(path);
        }
    }
}

我们可以使用受限制的权限调用它:

using System;
using System.Collections;
using System.Reflection;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;

namespace ConsoleApplication1
{
    class Program
    {
        //Path to plugin library
        public static string libname = @"C:\PROJECTS\ConsoleApp1\bin\Debug\ClassLib.dll";

        //Invokes plugin library in restricted AppDomain
        //Grants access to the directory specified by allowedPath parameter
        static void InvokeLibrary(string allowedPath="")
        {
            var path = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;

            //create restricted permission set
            Evidence evidence = new Evidence();
            evidence.AddHostEvidence(new Zone(SecurityZone.Internet));
            PermissionSet permissionSet = SecurityManager.GetStandardSandbox(evidence);

            //grant read access to plugin library file, so it can at least load successfully
            permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, libname));
            permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.PathDiscovery, libname));

            //grant read access to
            if (allowedPath != "")
            {
                permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, allowedPath));
            }            

            AppDomainSetup appDomainSetup = new AppDomainSetup();
            appDomainSetup.ApplicationBase = System.IO.Path.GetDirectoryName(path);

            //create AppDomain with specified permissions
            AppDomain domain = AppDomain.CreateDomain(
                "MyDomain",
                evidence,
                appDomainSetup,
                permissionSet
                );

            //create remoting wrapper
            Type type = typeof(Wrapper);
            Wrapper wrapper = (Wrapper)domain.CreateInstanceAndUnwrap(
                type.Assembly.FullName,
                type.FullName);

            //invoke method          
            InvokeResult res = wrapper.Invoke(libname,"c:\\dir\\file.txt");

            if (res.Success) Console.WriteLine("Invoke result: " + res.Result);
            else {
                Console.WriteLine("Invoke error: " + res.Error.GetType().ToString());
                if (res.Error is SecurityException)
                {
                    Console.WriteLine("Demanded permissions:\n" + (res.Error as SecurityException).Demanded);
                }
            }                    

            AppDomain.Unload(domain);
        }

        static void Main(string[] args)
        {
            //invoke plugin without explicit permissions
            Console.WriteLine("First attempt...");
            InvokeLibrary();

            //invoke plugin with specified directory access
            Console.WriteLine("Second attempt...");
            InvokeLibrary("c:\\dir\\");   

            Console.ReadKey();
        }

    }

    //Object to pass between app domains
    public class InvokeResult : MarshalByRefObject
    {
        public bool Success = false;
        public string Result="";
        public Exception Error =null;
    }

    //Wrapper for remoting
    public class Wrapper : MarshalByRefObject
    {
        public Exception lasterror;

        public InvokeResult Invoke(string lib, string arg)
        {
            InvokeResult res = new InvokeResult();

            try
            {
                //load plugin                
                Assembly ass = Assembly.LoadFile(lib);
                Type t = ass.GetType("ClassLib.Class1");
                MethodInfo mi = t.GetMethod("DoWork", BindingFlags.Static | BindingFlags.Public);

                //invoke plugin method
                res.Result = (string)mi.Invoke(null, new object[] { arg });
                res.Success = true;

            }
            catch (TargetInvocationException ex)
            {
                res.Success = false;
                if (ex.InnerException != null) res.Error = ex.InnerException;
                else res.Error = ex;
            }
            return res;
        }
    }
}

/* Output:

First attempt...
Invoke error: System.Security.SecurityException
Demanded permissions:
<IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Read="c:\dir\file.txt"/>

Second attempt...
Invoke result: The content of file.txt 
*/
© www.soinside.com 2019 - 2024. All rights reserved.