Подтвердить что ты не робот

Как я могу защитить свои личные функции от выполнения рефлексии?

Увидев это: Могут ли модификаторы доступа влиять на отражение?

Я попытался использовать это, но он не работает: enter image description here

Как я могу предотвратить отражение от выполнения моих личных методов?

4b9b3361

Ответ 1

Если кто-то может использовать отражение ваших личных методов, у них уже есть достаточный доступ, чтобы обойти все остальное, что вы помещаете на своем пути. Запуск с меньшим доверием может быть вариантом, но это только для предотвращения слишком большого доступа к плагинам - это не остановит пользователя (скажем) доступ администратора к ящику, который может просто повысить доступ.

Если вы не хотите запускать код, не помещайте его в физический охват злоумышленника; хранить его на веб-сервисе или аналогично. Любой код, доступный пользователю, может использоваться напрямую или косвенно путем декомпиляции его (и деобскаживания его, если необходимо). Вы можете использовать некоторые трюки, чтобы мешать им (проверка звонящего через стек и т.д.), Но это не остановит кого-то определенного.

Ответ 2

Как я могу защитить свои личные функции от выполнения отражения?

Вы можете изменить свою политику безопасности, чтобы у кода не было разрешения делать "частное отражение" при его запуске.

Конечно, это повлияет только на вашу машину. Если вы хотите повлиять на какую-либо другую машину, отправьте электронное письмо администратору своего компьютера и попросите администратора изменить политику безопасности пользователя, чтобы у нее не было разрешения на "частное отражение". Это тот, кто владеет машиной и сетью, на которой он работает; очевидно, что у вас нет возможности изменять параметры безопасности в сети, которой вы не являетесь.

Обратите внимание, что права, более мощные, чем частные, также должны быть ограничены. Не имеет смысла устанавливать политику, которая гласит: например, "права частной рефлексии отрицаются, но предоставляется право на изменение политики безопасности". Затем пользователь может просто изменить политику безопасности, чтобы повторно предоставить частное отражение себе.

Вам также придется ограничить доступ к диску. Тот, кто может получить доступ к диску, может просто прочитать код из сборки, сменить частные метаданные на общедоступные и загрузить сборку в обычном режиме.

Итак, ваша миссия состоит в том, чтобы убедить всех системных администраторов мира не разрешать своим пользователям получать доступ к своим собственным дискам. Я подозреваю, что вы не добьетесь успеха; Я предлагаю вам найти другой способ защитить свои функции от злоупотреблений.

Ответ 3

Модификаторы доступа не являются механизмом безопасности.

Если вы могли бы предотвратить функцию вызова через отражение, пользователь может просто декомпилировать вашу программу, извлечь эту функцию, поместить ее в новую сборку и выполнить ее.

Ответ 4

Это поздний ответ, но я считаю это обновлением, так как все ответы были написаны до выпуска .NET 4.6 в середине 2015 года, в котором представлен новый атрибут сборки DisablePrivateReflection.

С этим атрибутом, помеченным в вашем AssemblyInfo.cs, вы можете отключить отражение над частными членами этой сборки.

Пример:

namespace DisablingPrivateReflection
{
    public class Singleton
    {
        private Singleton()
        {

        }
    }
}

И в вашей AssemblyInfo.cs добавьте эту строку:

[assembly: DisablePrivateReflection]

Затем в вашей клиентской сборке, которая ссылается на вышеприведенную сборку, этот код не будет работать во время выполнения:

var singleton = Activator.CreateInstance(typeof(Singleton), true);

Исключение выбрано типа MethodAccessException с сообщением:

Попытка с помощью метода 'Program.Main(System.String [])' для доступа к методу 'DisablingPrivateReflection.Singleton..ctor()' не удалось.

Ответ 5

Нет никакого способа сделать это. Почему вы хотите предотвратить выполнение ваших частных функций? Обычно, если кто-то использует отражение, он знает, что он делает.

Ответ 6

Вы не можете, модификаторы только для разработчиков имеют правильную инкапсуляцию. Во время выполнения может быть грустно, что все находится на одном уровне.

Механика отражения обычно используется приложением, которое требует вызова некоторых предварительно сконфигурированных методов (старше ORM) или их отображения (IDE). Было бы очень сложно, если бы этот механизм не смог этого сделать.

Ответ 7

Хотя я абсолютно согласен с идеей модификаторов доступа, которые не являются функцией безопасности, только ради программирования. Я немного об этом подумал, и у меня есть простой, не очень полезный механизм, бой Reflection с отражением: -)

Будьте осторожны, это просто глупое доказательство концепции, я не принимаю во внимание общие методы, для этого нужны изменения...

Идея заключается в том, что в начале каждого частного метода, который вы хотите защитить от "незаконного" вызова, вы просто проверяете через Reflection, что вы вызываетесь из другого метода в этом классе, а не извне. Таким образом, вы будете использовать: новый StackTrace(). GetFrame (1).GetMethod(); чтобы получить MethodBase вашего invoker и сравнить его со списком MethodInfos для вашего класса.

Вы можете добавить его в класс-помощник (в любом случае вам понадобится IEqualityComparer для сравнения BaseBase...

Одна из проблем заключается в том, что вы также предотвращаете некоторые правильные вызовы, например, вызываете их через делегат или через Reflection из другого вашего метода... так что вы должны быть осторожны при использовании.

Вы можете выполнить мою реализацию здесь

Ответ 8

using System;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;

class Person
{
    private string SayInternalSecure()
    {
         if (!PrivacyHelper.IsInvocationAllowed<Person>())
            throw new Exception("you can't invoke this private method");
         return "Internal Secure";
    }

    private string SayInternal()
    {
         return "Internal";
    }

    public string SaySomething()
    {
         return "Hi " + this.SayInternal();
    }

    public string SaySomethingSecure()
    {
        return "Hi " + this.SayInternalSecure();
    }

    public void BeingCalledBy()
    {
            Console.WriteLine("I'm being called by: " + new StackTrace().GetFrame(1).GetMethod().Name);
    }
}

public class MethodBaseComparer : IEqualityComparer<MethodBase> 
{
     private string GetMethodIdentifier(MethodBase mb)
     {
      return mb.Name + ":" + String.Join(";", mb.GetParameters().Select(paramInfo=>paramInfo.Name).ToArray());
     }

     public bool Equals(MethodBase m1, MethodBase m2) 
     {
        //we need something more here, comparing just by name is not enough, need to take parameters into account
        return this.GetMethodIdentifier(m1) == this.GetMethodIdentifier(m2);
     }

     public int GetHashCode(MethodBase mb) 
     {
             return this.GetMethodIdentifier(mb).GetHashCode();
     }
}

class PrivacyHelper
{
static Dictionary<Type, MethodBase[]> cache = new Dictionary<Type, MethodBase[]>();
public static bool IsInvocationAllowed<T>()
{
    Type curType = typeof(T);
    if (!cache.ContainsKey(curType))
    {
        cache[curType] = curType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).ToArray();
    }
    //StackTrace.GetFrame returns a MethodBase, not a MethodInfo, that why we're falling back to MethodBody
    MethodBase invoker = new StackTrace().GetFrame(2).GetMethod();
    return cache[curType].Contains(invoker, new MethodBaseComparer());
}
}

public class App
{
public static void CheckCaller()
{
    Person p = new Person();

    Console.WriteLine("- calling via delegate");
    Action action = p.BeingCalledBy;
    action();

    Console.WriteLine("- calling via reflection");
    MethodInfo method = typeof(Person).GetMethod("BeingCalledBy", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    Console.WriteLine(method.Invoke(p, null));

    Console.WriteLine("- calling via delegate again");
    action = (Action)(Delegate.CreateDelegate(typeof(Action), p, method));
    action();
}

public static void Main()
{
    Console.WriteLine("Press key to run");
    Console.ReadLine();

    CheckCaller();

    Person p = new Person();
    Console.WriteLine(p.SaySomething());
    Console.WriteLine(p.SaySomethingSecure());

    MethodInfo privateMethod = typeof(Person).GetMethod("SayInternal", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    Console.WriteLine("invoking private method via Reflection:");
    Console.WriteLine(privateMethod.Invoke(p, null));

    Console.WriteLine("----------------------");

    privateMethod = typeof(Person).GetMethod("SayInternalSecure", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    Console.WriteLine("invoking secured private method via Reflection:");
    try
    {
        Console.WriteLine(privateMethod.Invoke(p, null));
    }
    catch(Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
}