Page 42 - MSDN Magazine, May 2018
P. 42
Figure 2 The Dotfuscator Checks Page, Showing a Root Check
to include a row for that Check, as seen in Figure 2. I could view the configuration for the Check by doubleclicking that row.
Note that you can configure more than one Root Check for a single Dotfuscator config file, though I didn’t do so for this article. For an example of an app protected by multiple Checks, see the Adventure WorksSalesClient .NET Framework app I wrote about last November.
Adding a Root Check
From the Checks page, I added a Root Check by clicking the Add Root Check button. When I did, Dotfuscator displayed a new win dow for configuring the new Check. Figure 3 shows the finished configuration; this section explains the meaning of each setting and why I chose those settings.
Checks can report the results of their detection to app code. This allows you to have customized reporting and response behaviors ...
Locations: Each Check is associated with one or more methods in the app, called Locations. When the app calls such a method, the Root Check activates, detecting at that moment if the device appears to be rooted. After executing all configured reporting and response functionality, assuming those measures didn’t exit the app, the Check returns control to
the top of the method.
why did I add other methods that occur later in the app’s lifecycle as additional Locations? This is to help the app defend against reverse engineering. If an attacker creates a tampered version of the app that by passes or removes the Root Check code at AuthenticateAsync, these other Locations will still be able to react to a rooted environment.
Some of these additional Locations are defined in TodoAzure.dll. This can be surprising, as that assembly contains logic common to all Xamarin platforms, not just Android. How can Dotfuscator inject a Root Check—which detects rooted Android devices—into a platformagnostic assembly? Recall that this Dotfuscator config file is specific to the TodoAzure.Droid project, which references the TodoAzure project. When Dotfuscator modifies TodoAzure.dll, it will modify only the assembly that Visual Studio or MSBuild copies for use in the current project, TodoAzure.Droid. The original TodoAzure project's assembly remains unchanged.
Application Notification: Checks can report the results of their detection to app code. This allows you to have customized reporting and response behaviors, while having the Checks injected by Dotfuscator handle the detection work. The app code that receives the detection result is called an Application Notification Sink.
To meet the protection strategy in this scenario, I needed to have the app disable itself, so future runs of the app exit with an error message. I chose to add this disabling logic in a method, TodoAzure.App.DisableIfCompromised, and use it as the Check’s Sink by setting the following Check Properties:
• ApplicationNotificationSinkElement: The kind of code element; in this case, a method.
• ApplicationNotificationSinkName: The simple name of the code element; in this case, DisableIfCompromised.
• ApplicationNotificationSinkOwner: The type that contains the code element; in this case, TodoAzure.App.
Any of the Check's Locations can call this Sink method as it’s public and static. To be compatible with a Check, the method is synchronous (nonasync), takes a single bool argument and has a void return type.
For this scenario’s Check, I selected multiple Locations. The Location first used in the app is TodoAzure.Droid.MainActivity. AuthenticateAsync, which coor dinates a login request. Using this location means the Root Check will perform its detection and response whenever the login process begins.
Per the protection strategy, an app running on a rooted device exits when it first reaches the AuthenticateAsync method. So
Figure 3 Configuration of the Root Check—Additional Locations Hidden by the Collapsed TodoAzure.dll Node
38 msdn magazine
Security