Protecting C# Applications That Use Friend Assemblies
Published on October 12, 2022 by John Brawner
The internal keyword in C# restricts access of types and members to callers in the same assembly. The InternalsVisibleTo attribute is a special way to grant internals access to a “Friend” assembly. Friend assemblies are used when unit testing, as internal members must be directly invoked by a test DLL. So it is quite common to have several friend assemblies in our project.
Dotfuscator takes friend assemblies into consideration when applying protection settings. It follows a specific process to preserve runtime behavior while performing as much obfuscation as possible. It also notifies us of any potential issues with friend assemblies during the build.
Please consider the following example, a DLL has InternalsVisibleTo an EXE file:
The EXE file directly references an internal class, made possible only by adding the InternalsVisibleTo attribute in the DLL:
When obfuscating only the DLL, one of the following warnings would be shown, depending on the Dotfuscator configuration:
“WARNING: MyAssembly has non-input Friend Assemblies and is in Library Mode; internal members will not be renamed or pruned. Consider adding Friend Assemblies as input for increased obfuscation.”
“WARNING: MyAssembly has non-input Friend Assemblies and is not in Library Mode; internal members may be renamed or pruned. References from non-input Friend Assemblies to the internal members of MyAssembly may no longer be valid.”
The first message occurs when Dotfuscator is run in Library Mode. In Library Mode, Dotfuscator will not rename public and protected members for reusability of obfuscated components (as with APIs). Because of the InternalsVisibleTo attribute, Dotfuscator will also skip the renaming of internals. This will result in less Rename obfuscation than we may have anticipated, but it also will not break any runtime behavior.
The second message warns that Dotfuscator may rename internals in a way that could break calls from the friend assembly. If the friend assembly is deployed with this obfuscated DLL, this could cause a runtime error. If the friend assembly is not deployed (as with a unit testing DLL) then this warning will have no runtime impact and can be disregarded.
In general, obfuscation works best when more parts of the application are obfuscated together. The above warnings will completely disappear if the friend assembly is included as Dotfuscator input. If this is not feasible, we can still process the assemblies in Library mode but with less obfuscation.
The full example can be downloaded here.
Be on the look out for our next Support Corner blog!