none
基于安全问题,从网络接收到的第三方DLL 程序集能否从内存加载,不保存到硬盘 RRS feed

  • 问题

  • 如题,我会在一个客户端接收另外一个客户端发送的几个DLL数据的BYTE[],正常情况是可以把这保存到硬盘,再通过加载程序集,调用DLL里面的方法。但从安全角度考虑,不希望DLL在接收的机器保存到硬盘,最好能直接从内存加载!DLL是多个,被调用的主方法会需要其他几个DLL,当以文件保存到硬盘时,是需要保存到一个目录里面的。客户端和DLL都是c#的。

    不知道能否实现

    2011年7月20日 16:17

答案

  • 你好

    程序集的加载是有顺序的.你的代码里应当先加载classlibrary2.dll。也就是bytes2。
     另外
     Assembly assembly = Assembly.Load(bytes);
                  Assembly assembly2 = Assembly.Load(bytes2);
                 //assembly.LoadModule(fileName2, bytes2);
                 AppDomain currentDomain = AppDomain.CurrentDomain;
                 currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);
     应该改成
     AppDomain currentDomain = AppDomain.CurrentDomain;
                 currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);
    Assembly assembly = Assembly.Load(bytes);
                  Assembly assembly2 = Assembly.Load(bytes2);
                 //assembly.LoadModule(fileName2, bytes2);
                 
     这样的话,当程序集找不到的时候, currentDomain_AssemblyResolve方法就会被调用到, 这个方法里可以做一些逻辑去指定位置加载被引用的dll。


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 金钱豹 2011年7月22日 7:17
    2011年7月21日 6:12

全部回复

  • 你好!

    即然是这样,为何不把关键 DLL 放在服务端,客户端直接调用服务端的方法,这样更安全。


    知识改变命运,奋斗成就人生!
    2011年7月21日 4:49
    版主
  • 你好

    程序集可以加载byte数组,有重载的方法。

    byte[] byteArray;
            byteArray=....;
            Assembly.Load(byteArray)
    


    类似的:

    var h = File.ReadAllBytes(@"C:\MyAssembly.exe");  
         var g = Assembly.Load(h); 
    

     


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年7月21日 5:01
  • 你好啊!非常感谢你的回复!

    现在如果调用的DLL会引用其他DLL呢,能都从内存加载吗?

     string fileName = @"D:\vs2010_project\net4\FanShe反射加载内存DLL\ClassLibrary1\bin\Debug\ClassLibrary1.dll";
                byte[] bytes = File.ReadAllBytes(fileName);// JqbZipDirHelp.GetBytesFromFileName(fileName);

                string fileName2 = @"D:\vs2010_project\net4\FanShe反射加载内存DLL\ClassLibrary1\bin\Debug\ClassLibrary2.dll";
                byte[] bytes2 = File.ReadAllBytes(fileName2);// JqbZipDirHelp.GetBytesFromFileName(fileName2);
                
                InterFace1 cli; //接口对象
                //Assembly assembly = Assembly.LoadFile(fileName);

                Assembly assembly = Assembly.Load(bytes);
                 Assembly assembly2 = Assembly.Load(bytes2);
                //assembly.LoadModule(fileName2, bytes2);
                AppDomain currentDomain = AppDomain.CurrentDomain;
                currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);


                Type tp = assembly.GetType("ClassLibrary1" + "." + "Class1");
                Object obj = Activator.CreateInstance(tp);
                cli = obj as InterFace1 ;
                Console .WriteLine ( cli.Add(1, 2).ToString ());

     


    namespace ClassLibrary1
    {
        public class Class1: InterFace1
        {
            //public Int32 Add(Int32 x, Int32 y)
            //{
            //    return x + y;
            //}
            #region InterFace1 成员

            public int Add(int x, int y)
            {
                return x + y+ClassLibrary2 .Class1 .Cheng (x,y);
            }

            #endregion
        }

    }


    namespace ClassLibrary2
    {
        public class Class1
        {
            public  static  Int32 Cheng(Int32 x,Int32 y)
            {
                return x * y;
            }
        }
    }

    2011年7月21日 5:33
  • 现在运行时提示找不到第二个DLL
    2011年7月21日 5:34
  • 加载这个程序集前,它引用的 DLL 必须先加载。方式都是一样的
    知识改变命运,奋斗成就人生!
    2011年7月21日 5:58
    版主
  • 你好

    程序集的加载是有顺序的.你的代码里应当先加载classlibrary2.dll。也就是bytes2。
     另外
     Assembly assembly = Assembly.Load(bytes);
                  Assembly assembly2 = Assembly.Load(bytes2);
                 //assembly.LoadModule(fileName2, bytes2);
                 AppDomain currentDomain = AppDomain.CurrentDomain;
                 currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);
     应该改成
     AppDomain currentDomain = AppDomain.CurrentDomain;
                 currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);
    Assembly assembly = Assembly.Load(bytes);
                  Assembly assembly2 = Assembly.Load(bytes2);
                 //assembly.LoadModule(fileName2, bytes2);
                 
     这样的话,当程序集找不到的时候, currentDomain_AssemblyResolve方法就会被调用到, 这个方法里可以做一些逻辑去指定位置加载被引用的dll。


    Cookie Luo[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 金钱豹 2011年7月22日 7:17
    2011年7月21日 6:12
  • 非常感谢啊!

    这样的话,当程序集找不到的时候, currentDomain_AssemblyResolve方法就会被调用到, 这个方法里可以做一些逻辑去指定位置加载被引用的dll。

    这个里面怎么具体写呢?

    上面我调整DLL加载是顺序,但还是一样才错误提示。

    感觉是不是要使用LoadModule才行啊?

    2011年7月21日 7:22
  • static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
            {
                string fileName2 = @"D:\vs2010_project\net4\FanShe反射加载内存DLL\ClassLibrary1\bin\Debug\ClassLibrary2.dll";
                byte[] bytes2 = File.ReadAllBytes(fileName2);// JqbZipDirHelp.GetBytesFromFileName(fileName2);
                Assembly assembly2 = Assembly.Load(bytes2);

                //Console.WriteLine(args .Name .ToString ()+" "+args .RequestingAssembly .FullName .ToString ());
                return assembly2 ;
            }

     

     

    原来是要这样用,好奇怪的函数用法!

    2011年7月22日 7:10