How can I protect my private funcs against reflection executing?
Asked Answered
S

11

16

After seeing this: Do access modifiers affect reflection also?

I tried using this, but it doesn't work: enter image description here

How can I prevent reflection from executing my private methods?

Selfconfessed answered 2/12, 2011 at 14:0 Comment(14)
Access modifiers are to prevent you from making errors, no security feature.Lifeordeath
Reflection is the honey badger of .NET.Dullard
You kinda can't. Why do you want to?Belen
@Vash after seeing the link they gave me - ive changed the question . so i asked a new one. thanks.Selfconfessed
@AndrewBarber my private method is being called from inside after many calculation from the outside prop. I dont want that someone will activate the func and bypass the regular flow of my programSelfconfessed
This questions provides more informations: #2084853 Note: Access modifiers are not a security feature.Sexlimited
Check out the ReflectionPermissionAttribute class.Peipus
All you can do is make it harder. Run your code through an obfuscator maybe.Reduplicative
@HansPassant: Definitely should be an answer.Reduplicative
@Hans in reality, most code in regular .NET runs with full trust, so that isn't even checked IIRCReorganization
Private modifier a sign saying “Don't trespass”, rather than a lock. If you want true security, you might not want to deal with managed code at all—and even in that case, anyone can disassemble your program and step through it or jump to arbitrary instructions.Editorial
@Dan this is nothing to do with managed code; think about things like the games industry - most games are hacked (be it for DRM or cheating purposes) within days.Reorganization
Even though it has been asked several times already, I have to ask why do you want to do this? I don't mean to imply that you don't have a good reason, but if you'd tell us wh you want to prevent your method to be called from outside there might be other alternatives to accomplish what you want.Vanda
@RoyiNamir That's a late comment, but have you ever tried using [assembly: DisablePrivateReflection] in AssemblyInfo.cs : msdn.microsoft.com/en-us/library/…Terzetto
R
34

If someone can currently use reflection on your private methods, then they already have enough access to sidestep anything else you place in their way. Running with less trust may be an option, but that is only to prevent things like plugins from having too much access - it won't stop a user with (say) admin access to the box, who can simply elevate the access.

If you don't want code running, don't put it in physical reach of the malicious user; keep it at a web-service or similar. Any code available to a user can be used directly, or indirectly by decompiling it (and deobfuscating it if needed). You can use some tricks to get in their way (checking the caller via the stacktrace etc), but that will not stop someone determined.

Reorganization answered 2/12, 2011 at 14:7 Comment(0)
T
26

This is a late answer, but I consider it an update since all the answers were written before the release of .NET 4.6 in mid of 2015 which introduces a new assembly attribute called DisablePrivateReflection.

With that attribute tagged in your AssemblyInfo.cs, you can disable reflection over private members of that assembly.

Example:

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

        }
    }
}

And in your AssemblyInfo.cs add this line:

[assembly: DisablePrivateReflection]

Then in your client assembly that is referencing the above assembly, this code would fail at run-time:

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

The exception thrown is of type MethodAccessException with message:

Attempt by method 'Program.Main(System.String[])' to access method 'DisablingPrivateReflection.Singleton..ctor()' failed.

Terzetto answered 16/11, 2016 at 11:6 Comment(2)
This for some reason crashes my exe, throwing System.MethodAccessException when I use this with ConfuserExOuidaouija
Great to know about this, and I think it could be part of an obfuscation strategy, but as noted in the documentation, it is not to be relied upon 100% learn.microsoft.com/en-us/dotnet/api/…Munt
M
23

How can I protect my private funcs against reflection executing?

You can change your security policy so that the code does not have permission to do "private reflection" when you run it.

Of course, that will only affect your machine. If you want to affect someone else's machine, send an email to their machine administrator and ask the administrator to change the user's security policy so that it does not have permission to do "private reflection". That's the person who owns the machine and the network it runs on; obviously you do not have the ability to change the security settings on a network you don't own.

Note of course that rights more powerful than private reflection also have to be restricted. It does no good to set a policy that says, for example "private reflection rights are denied, but the right to change security policy is granted". The user could then just change security policy to re-grant private reflection to themselves.

You'll also have to restrict ability to access the disk. Someone who can access the disk can simply read the code out of the assembly, change the private metadata to public, and load the assembly normally.

So, your mission is to convince all of the machine administrators of the world to not allow their users to access their own disks. I suspect you will be unsuccessful; I suggest that you find a different way to protect your functions from abuse.

Merodach answered 2/12, 2011 at 14:49 Comment(0)
S
9

Access modifiers are not a security mechanism.

If if you could prevent your function from being called via reflection, the user can just decompile your program, extract that function, put it in a new assembly and execute it.

Sachs answered 2/12, 2011 at 14:7 Comment(0)
C
2
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's 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);
    }
}
}
Conlan answered 14/12, 2013 at 17:54 Comment(0)
C
1

There is no way to do that. Why do you want to prevent execution of your private funcs? Usually, if someone uses reflection, he knows what he's doing.

Checkpoint answered 2/12, 2011 at 14:3 Comment(3)
my private method is being called from inside after many calculation from the outside prop. I dont want that someone will activate the func and bypass the regular flow of my programSelfconfessed
@RoyiNamir Why do you care about that situation, if some other dev decides to do that and it causes problems then that is his problem not yours. Think of your code like a machine, you give that machine to another person to use. That other person opens up the machine and starts messing with the workings, you can't stop them doing this , all you can do is put sticker on saying that this will void the warranty. If they break it then it is their own fault for ignoring your warning and they bear the consequences not you.Eparch
The primary use case here is not security related, but code maintainability... In a large monolithic system, you need good strong walls on your bounded contexts so that each module can be developed independently of every other module without breaking things... If a developer in another module is using reflection to call a method in my module which I have not made public, and I subsequently remove that method, than the other module is now broken. By putting in these strong/inviolate boundaries, developer teams can move independently of one another without fear of breakages.Gunwale
I
1

You can not, the modifiers are only for developers to have proper encapsulation. At the runtime it could be sad that everything is on the same level.

The reflection mechanics, is used usually by application that need to call some pre-configured methods (older ORM) or display them (IDE). It wold be really hard if this mechanism would not be able to do that.

Innis answered 2/12, 2011 at 14:4 Comment(1)
it depends on the runtime to a small degree; things like Silverlight run in a tighter sandbox than full .NET, and less is available by defaultReorganization
C
1

Though I absolutely agree with the idea of access modifiers not being a security feature, just for the sake of programming I've been thinking a bit about this, and I've got a simple, not much useful mechanism, fight Reflection with Reflection :-)

Be advised, it's just a silly proof of concept, I'm not taking into account Generic methods, it would need changes for that...

The idea is, at the start of every private method that you want to secure from being "illegally" invoked, you just check via Reflection that you're being invoked from another method in that class, not from outside. So you would use: new StackTrace().GetFrame(1).GetMethod(); to get the MethodBase of your invoker and would compare it against the list of MethodInfos for your class.

You can add it to a helper class (anyway you'll need a IEqualityComparer to compare MethodBases...

One problem is that you would also be preventing some correct invocations, like invoking it through a delegate or through Reflection from another of your methods... so you should be careful with when you use it.

You can my implementation here

Cybil answered 23/4, 2012 at 16:16 Comment(0)
D
0

I use eazfuscator and it making methods virtual seems to do a good job hiding the method.

Then in methods, I like to protect I will alter the code in release mode to give null pointer exceptions to start a task that will generate a null pointer and execute it without the code having a callstack.

There are not a lot of developers that can work with your production code without debugging...

#if !DEBUG
    #pragma warning disable CS8618 
    
    [System.Diagnostics.DebuggerStepThrough, System.Diagnostics.DebuggerNonUserCode]
    [System.ComponentModel.Browsable(false)]
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
#endif

namespace MyApp.Infrastructure.LicenseManager
{
    [Obfuscation(Feature = "apply to member * when method or constructor: virtualization", Exclude = false)]
    internal sealed class LicenseManager(ISomeClass parameter, ILoggerFactory? factory = null)
    {
       //hide the name space for reverse engineering the naming scheme
       _logger = factory?.CreateLogger("MyApp.LicenseManager") 

    #if !DEBUG
        if (System.Diagnostics.Debugger.IsAttached)
        {
            //send computer information for license violation and prosecution then crash
            System.Threading.ThreadPool.UnsafeQueueUserWorkItem(SystemCrasher.SendAbuseAndCrash);
            
            //send a log entry, of don't if you wish to give no warning
           _logger?.LogWarning(Walter.BOM.LogEvents.FireWall_Warning, "Debugging will cause the developer to generate null pointer exceptions in administration context");
           return;
           
           //all class initiolizers will stay null
         }
    #endif

        _myClass= parameter;

}

#if !DEBUG
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
#endif

If your code is consumed by other code in a shared DLL (like in NuGet packages) then the above method will prevent you from being popular with your colleagues, you need a "Debug" friendly method, using a method proxy may do the trick for you in combination with obfuscation.

[Obfuscation(Feature = "virtualization", Exclude = false)]
private void MyMethod(int parameter)
{
    MyMethodProxy();
    //do some code
}

private void MyMethodProxy([CallerMemberName] string? calledBy = null)
{
    if (!string.Equals(nameof(MyMethod), calledBy, StringComparison.Ordinal))
    {
        throw new LordOfTheRingsException("You shall not pass!!");
    }
}

By using the NameOf method you are able to survive the non-printable characters from the Obfuscator's renaming scheme.

I use a few other options but this would limit you automate and use Aspect-oriented frameworks like postsharp

Hope it helpsenter code here

Dynamic answered 6/5, 2021 at 17:16 Comment(0)
L
0

I know this is old, but basically to do what you are asking is relatively imposible in .NET, but there are some things you can do to lessen the surface area, and they generally require more work. Ultimately what you are trying to prevent is a handle to a type, right? Consider the following scenario.

public class OuterView
{
   protected internal class HiddenMethods
   {
       public static void DoMoreWork(string msg)
       {
            Console.WriteLine(msg);
       }
   }

   public void DoWork(string msg)
   {
       HiddenMethods.DoMoreWork(msg);
   }
}

Assuming this is in a library that you don't want to grant direct access to the underlying methods - Assembly.GetTypes() won't return the nested class, and there is no reference from the HiddenMethods in the class that you do have access to (OuterView). Save the state in the OuterView, and pass it into the HiddenMethods with each static call. Ultimately, anyone with enough access to create a PEReader can still access your HiddenMethods. But the above works for 9 out of 10 scenarios.

Lector answered 4/6, 2024 at 21:12 Comment(0)
E
-1

I would try to parse stack trace (https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics?redirectedfrom=MSDN&view=netframework-4.7.2) and check for dynamic invocation...

Epizoon answered 26/9, 2018 at 18:44 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.