Please enter the text to find and press Search.
Sorry

An error occurred during search results load.

Conditional Obfuscation

Conditional obfuscation is an extension feature to indirect declarative obfuscation. Conditional obfuscation allows to process the types in a bulk according to their natural properties such as visibility (public, internal, protected, private), subtype (class, struct, enum, delegate) and others.

This functionality is achieved by when conditional clause which can be specified in an obfuscation attribute. So the full conditional attribute notation has the following form:

[assembly: Obfuscation(Feature = "Apply to type [name mask] when [condition]: [feature]")]

where [condition] is a string defining the condition for a match.

Condition is defined as a boolean predicate with Pascal syntax. Quick example of an conditional attribute is shown below.

Example 4.8. Indirectly disable renaming of all internal enums and their members

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type * when internal and enum: renaming", Exclude = true, ApplyToMembers = true)]


Please take a closer look at internal and enum predicate in the sample above. What it says is this: the result of predicate is true when internal variable equals to true and enum variable equals to true too; otherwise the result of predicate is false. The values of internal and enum variables are calculated for every type in the assembly, describing the natural properties of a CLR type in boolean form.

The list of available variables is presented in the table below.

Table 4.1. The list of available variables for conditional obfuscation of types

VariableDescription
abstract true if the type is abstract; otherwise, false
anonymous true if the type is anonymous; otherwise, false
class true if the type is a class; otherwise, false
delegate true if the type is a delegate; otherwise, false
enum true if the type is an enumeration; otherwise, false
generic true if the type is generic; otherwise, false
interface true if the type is an interface; otherwise, false
internal true if the type is internal; otherwise, false
nested true if the type is nested; otherwise, false
private true if the type is private; otherwise, false. Applies to nested types only; false if the type is not nested
protected true if the type is protected; otherwise, false. Applies to nested types only; false if the type is not nested
public true if the type is public; otherwise, false
sealed true if the type is sealed; otherwise, false
serializable true if the type is serializable; otherwise, false
static true if the type is static; otherwise, false
struct true if the type is a structure; otherwise, false


Predefined constants can be used in expressions as well. The list of available constants is presented in the table below.

Table 4.2. The list of available constants for conditional obfuscation

ConstantDescription
false false value
true true value


Built-in functions can be used in expressions too. The list of available functions is presented in the table below.

Table 4.3. Built-in functions for conditional obfuscation

FunctionDescription
inherits('type_name')
Returns true if the type inherits another type specified by type_name parameter; otherwise, false. Inherits function considers base and all inherited types including interfaces. Type name parameter can contain either the full type name or a mask for a bulk match
extends('type_name')
Returns true if the type extends another type specified by type_name parameter; otherwise, false. Extends function only checks the base type, but all implemented and inherited interfaces are considered. Type name parameter can contain either the full type name or a mask for a bulk match
has_attribute('type_name')
Returns true if the type or member has a custom attribute specified by type_name parameter; otherwise, false. Type name parameter can contain either the full type name or a mask for a bulk match.
Example:
has_attribute('System.ComponentModel.DisplayNameAttribute')


Variables, functions and constants can be combined by operators. They have the standard Pascal precedence. The list of available operators is presented in the table below.

Table 4.4. The list of available operators for conditional obfuscation

OperatorDescriptionPriority
not Unary operator for boolean negation Highest
and Binary operator for boolean and operation Medium
or Binary operator for boolean or operation Lower
= Binary operator for boolean equal operation Lowest
<> Binary operator for boolean not equal operation Lowest


The precedence of operations can be changed by parentheses.

Let's take a look on examples.

Example 4.9. Disable renaming of all types except enums

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type * when not enum: renaming", Exclude = true)]


Example 4.10. Disable renaming of all internal nested and serializable types together with their members

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type * when internal and (nested or serializable): renaming", Exclude = true, ApplyToMembers = true)]


Example 4.11. Disable renaming of all types except internal nested and serializable types

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type * when not (internal and (nested or serializable)): renaming", Exclude = true)]


Example 4.12. Disable renaming of all interfaces in Contoso.Core.Services namespace

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type Contoso.Core.Services.* when interface: renaming", Exclude = true)]


Example 4.13.  Disable renaming of all classes derived from System.IDisposable interface. Renaming of members for matched classes is disabled too

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type * when class and extends('System.IDisposable'): renaming", Exclude = true, ApplyToMembers = true)]


As you can see the conditions can have any complexity and can be freely defined to achieve your specific goals.

Type Members

It was described how to tune the obfuscation of types in a bulk way in the section above. But what about type members such as methods, fields, properties and others? Sometimes it may be beneficial to process them in a bulk way too.

The declarative attribute for conditional obfuscation of type members has the following form:

using System.Reflection;

[Obfuscation(Feature = "Apply to member [name mask] when [condition]: [feature]")]
class Sample1
{
  
}

[name mask] is a pattern which selects the members according to their names. [condition] allows to specify a boolean predicate to select members according to their properties. The rules are all the same as for types; the only difference is a set of variables which can be used in a boolean predicate. The list of available variables is presented below.

Table 4.5. The list of available variables for conditional obfuscation of type members

VariableDescription
abstract true if the member is abstract; otherwise, false
const true if the member defines a literal constant; otherwise, false. Applies to fields only; false if the member is not a field
constructor true if the member is a constructor; otherwise, false
event true if the member is an event; otherwise, false
field true if the member is a field; otherwise, false
generic true if the member is generic; otherwise, false. Applies to methods only; false if the member is not a method
internal true if the member is internal; otherwise, false
method true if the member is a method; otherwise, false
private true if the member is private; otherwise, false
property true if the member is a property; otherwise, false
protected true if the member is protected; otherwise, false
public true if the member is public; otherwise, false
readonly true if the member is read-only; otherwise, false. Applies to fields and properties only; false if the member is neither a field nor a property
static true if the member is static; otherwise, false
virtual true if the member is virtual; otherwise, false


The information on this topic is extremely bare, so let's take a relaxed look on some real-life samples.

Example 4.14. Disable renaming of public properties

using System.Reflection;

[Obfuscation(Feature = "Apply to member * when property and public: renaming", Exclude = true)]
class ImageQualityService
{
  
}


Example 4.15. Disable renaming of all methods

using System.Reflection;

[Obfuscation(Feature = "Apply to member * when method: renaming", Exclude = true)]
class CellCallEngine
{
  
}


Example 4.16. Disable renaming of internal fields

using System.Reflection;

[Obfuscation(Feature = "Apply to member * when field and internal: renaming", Exclude = true)]
class ContosoHeadquarters
{
  
}


Options are Combinable

Conditional obfuscation of types and type members can be easily combined to achieve specific goals in an elegant and powerful way.

Just take a look at the samples below.

Example 4.17.  Disable renaming of property Contoso in type Acme.Services

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type Acme.Services: apply to member Contoso when property: renaming", Exclude = true)]


Example 4.18. Disable renaming of all public properties in all types

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type *: apply to member * when public and property: renaming", Exclude = true)]


Example 4.19.  Disable renaming of all public properties in types defined in MyNamespace

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type MyNamespace.*: apply to member * when public and property: renaming", Exclude = true)]


Example 4.20. Disable renaming of all internal events in all public types

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type * when public: apply to member * when event and internal: renaming", Exclude = true)]


Diagnostics

How do you know which classes or members conditional obfuscation applies to?

Sometimes it may be useful to get the full list of classes and members that are targeted by specific conditional obfuscation statement. To achieve that, you can use log feature as shown below:

Example 4.21. Log all affected members of all public classes

using System.Reflection;

[assembly: Obfuscation(Feature = "Apply to type * when public: apply to member *: log")]


[Note]Note

Logging does not affect obfuscation in any way. It just dumps the list of items at Eazfuscator.NET's console output. To see this list in Visual Studio, please take a look at Output Window with ViewOutput (Ctrl+W,O) right after obfuscation.

Sorry

An error occurred during page load.
You can try again or go back.