Remoting Sample
The remoting sample demonstrates using Dotfuscator in an application that makes use of .NET Remoting. In a typical remoting application, objects that are to service remote invocations are registered with the runtime before they can be invoked. When an invocation request arrives, the runtime instantiates a server object dynamically using reflection. Since this process happens at runtime, there is no way for Dotfuscator to know at analysis time what types must be excluded. Manual user intervention is required to make sure that Dotfuscator does not rename remoted types.
The remoting sample demonstrates how to configure Dotfuscator to selectively exclude types from renaming. This sample also demonstrates how to configure multiple assemblies in the same Dotfuscator config. Instructions are included for using both the command line and the Dotfuscator Config Editor.
Building the Remoting Sample
The remoting sample assumes that the C# compiler (csc.exe) is reachable from your PATH environment variable. If you are using Visual Studio, you can make sure that it is in your path by executing the Visual Studio Command Prompt shortcut in your start menu.
From the command prompt, change your current directory to the directory containing the remoting sample.
Build the application by executing build.bat. This batch file will invoke the Visual C# compiler to produce the output files – TrigServer.exe, TrigClient.exe, ITrigFunctions.dll.
Running the Remoting Sample
The first step to running the remoting sample is to launch the TrigServer.exe assembly.
This application will register a new HTTP channel listener on port 12345, and register the class Samples.Trig
to handle method invocations on that channel.
The code from TrigServer that does this is:
TrigServer Code:
// create a channel and start listening
HttpChannel serverchannel = new HttpChannel(12345);
ChannelServices.RegisterChannel(serverchannel);
Type trigType = Type.GetType("Samples.Trig");
// register our well-known type
RemotingConfiguration.RegisterWellKnownServiceType(
trigType,
"TrigServer",
WellKnownObjectMode.Singleton );
Once the server is established, the client application, TrigClient.exe, can be run. This application establishes an outgoing HTTP channel and connects it to the TrigServer as can be seen in the following code:
Connect to TrigServer Code:
// create a channel for our client call
HttpChannel clientchannel = new HttpChannel(0);
ChannelServices.RegisterChannel(clientchannel);
// get a reference to the remote Trig server
MarshalByRefObject rawobject =
(MarshalByRefObject)RemotingServices.Connect(
typeof(Samples.ITrigFunctions),
"http://localhost:12345/TrigServer");
After establishing the connection, the client invokes several methods on the remote server object:
Invoked Methods on Remote Server Object:
Console.WriteLine("Cos(0) = {0}", trig.Cos(0.0));
Console.WriteLine("Sin(0) = {0}", trig.Sin(0.0));
Console.WriteLine("Cos(PI) = {0}", trig.Cos(trig.PI()));
Console.WriteLine("Sin(PI/2) = {0}", trig.Sin(trig.PI()/2));
The output of the client application demonstrates correct operation of the application:
Output:
About to make connection to remote server
Cos(0) = 1
Sin(0) = 0
Cos(PI) = -1
Sin(PI/2) = 1
Obfuscating the Remoting Output
The remoting sample contains a sample Dotfuscator config file that demonstrates using multiple input assemblies and using exclusion rules to exclude the type information for the object invoked through remoting.
The multiple input assemblies are indicated in the config file with multiple <file>
entries in the <input>
assemblies list as shown:
Using Multiple Input Assemblies and Exclusion Rules:
<input>
<filelist>
<file dir="${appdir}" name="ITrigFunctions.dll"/>
<file dir="${appdir}" name="TrigServer.exe"/>
<file dir="${appdir}" name="TrigClient.exe"/>
</filelist>
</input>
The other interesting aspect of the config file is the renaming exclusion list:
Renaming Exclusion List:
<renaming>
<excludelist>
<type name="Samples.Trig" excludetype="true"/>
</excludelist>
…
</renaming>
The <renaming>
tag indicates that the exclusion rules contained within pertain specifically to identifier renaming, as opposed to other Dotfuscator features which can also be selectively turned on or off.
The <excludelist>
tag defines a list of items that must be excluded from the renaming process.
The <type name="Samples.Trig">
tag instructs Dotfuscator to exclude the class name Samples.Trig
from the renaming process.
Note that this only refers to the class name itself.
All methods of the “Trig” class are still eligible for renaming.
This is acceptable since we are obfuscating both the client and the server in this case.
If we were creating an interface that was going to be called by clients we did not obfuscate, we would also want to prevent renaming of the interface methods as well.
Since we included all assemblies in the same config, Dotfuscator will be able to rename method call references to the appropriate renamed server method call.
Executing the dotfuscator.bat file will run Dotfuscator with this config file. The outputs of this process are TrigServer.exe, TrigClient.exe and ITrigFunctions.dll assemblies in the "obfuscatedoutput" subdirectory. This location can be controlled by modifying the following section in the config file:
TrigServer:
<output>
<file dir="${appdir}\obfuscatedoutput" />
</output>
Note: the 1:1 relationship between input and output assemblies cannot be changed.**
Running the new assemblies verifies that Dotfuscator correctly excluded the required items from the renaming process. It is also important to note that since we allowed the renaming of interface methods, it is not possible to have an obfuscated client call a non-obfuscated server or vice-versa.
Configuring the Remoting Sample with the Config Editor
The remoting sample makes use of Dotfuscator’s ability to have multiple input assemblies. Multiple input assemblies can be added with the Config Editor easily. Run this by executing dotfuscatorGUI.bat in the command prompt. Simply use the browse facility to locate each assembly individually. All input assemblies will appear in the Input Assemblies: list box:
The type Samples.Trig
which is defined in the TrigServer
assembly must be excluded from renaming since it is registered via reflection.
The following figure shows this item selected for exclusion in the renaming tab of the interface:
After building, the output tab shows the results.
Notice that everything except for the Samples.Trig
class was renamed.
Summary of the Remoting Sample
In order to obfuscate an application which serves objects to clients through remoting, it is important to exclude the type names of the served objects from the renaming process. The power of Dotfuscator is enhanced in a remoting situation if both the client and server are obfuscated together. In these cases, Dotfuscator can be aggressive and rename the external interfaces of the components in addition to the internal methods and fields.