.NET languages offer a few keywords for visibility control between assemblies, classes and members.
For example, C# has public
, internal
, protected
, protected internal
and private
access modifiers.
Sometimes you may need a special access level: protected private
.
It exists in C++ but absent in C# and VB.NET.
It corresponds to
FamANDAssem
visibility scope in terms of .NET CLR.
This is indeed a rare requirement. Let's take a look on specific example. Suppose you have a DLL assembly written in C# that does XML serialization for some entities:
Example 5.3. Original code
using System; using System.Xml.Serialization; // This class is used by System.Xml.Serialization.XmlSerializer. public class Card { public string ID { get; set; } protected virtual void Validate() { } } // This class is used by System.Xml.Serialization.XmlSerializer. public class VerticalCard : Card { public int Height { get; set; } protected override void Validate() { if (Height <= 0) throw new Exception("Vertical card height should be a positive number greater than zero."); } }
See that Validate
method?
It won't be renamed after obfuscation despite the wish of developer.
But why?
The answer is: because assembly is DLL, the class is public and Validate
method is protected.
This means that Validate
method can be reached by a third-party assembly and Eazfuscator.NET leaves its name intact.
That's ok for most situations.
Still, let's imagine that one picky developer decides to rename Validate
method whatever it costs. Potential workarounds are:
-
Make
Validate
methods private. Won't work because it wouldn't be possible to overrideValidate
method inVerticalCard
class -
Make
Card
andVerticalCard
classes internal. Won't work becauseXmlSerializer
works on public classes only -
Make
Validate
methods internal. Will work but will break the visibility borders inside the assembly. This may be unfeasible if you work in a team with established responsibility borders between its members -
Make
Validate
methodsprotected private
. Will perfectly work, but only in C++. C# and VB.NET have no corresponding access modifier -
Move validation away to a separate set of classes. Will work, but it requires code refactoring. It may be risky for a large code base and thus not always suitable
So we are stuck if our code is in C# or VB.NET.
Fortunately Eazfuscator.NET can change the visibility of class members to FamANDAssem
level.
This is the exact same thing as protected private
in C++.
Having that, we can now solve the dilemma (C#):
Example 5.4. Modified code to allow family and assembly visibility for specified methods
using System; using System.Xml.Serialization; using System.Reflection; // This class is used by System.Xml.Serialization.XmlSerializer. public class Card { public string ID { get; set; } [Obfuscation(Feature = "family and assembly visibility", Exclude = false)] protected virtual void Validate() { } } // This class is used by System.Xml.Serialization.XmlSerializer. public class VerticalCard : Card { public int Height { get; set; } [Obfuscation(Feature = "family and assembly visibility", Exclude = false)] protected override void Validate() { if (Height <= 0) throw new Exception("Vertical card height should be a positive number greater than zero."); } }
Once that in place, Validate
methods will be renamed and will no longer be visible to other assemblies.
- Open the source code of a class member that should have a visibility change
-
Add a custom attribute as shown below (C#):
using System; using System.Reflection; class YourClass { [Obfuscation(Feature = "family and assembly visibility", Exclude = false)] protected void YourMethod() { ... } }
For Visual Basic .NET:
Imports System Imports System.Reflection Class YourClass <Obfuscation(Feature:="family and assembly visibility", Exclude:=False)> Protected Sub YourMethod() ... End Sub End Class
Tip | |
---|---|
If you change visibility for a virtual method then it is beneficial to ensure that the whole inheritance hierarchy has a corresponding change. This will improve renaming coverage during obfuscation. |
Tip | |
---|---|
It may be a good idea to turn on code verification for your assembly when visibility changes are applied to ensure that generated code conforms to industrial standard. |