Page 52 - MSDN Magazine, November 2017
P. 52
the argument true if debugging was detected and false otherwise. The same thing happens when the app code calls PhoneWindow. UpdatePhones or CreditCardWindow.UpdateData, except that the method called by the Check is defined by PhoneWindow or CreditCardWindow, respectively. These methods are implemented slightly differently, but they’re all named ReportDebugging, take a
single Boolean argument, and return no value.
Action: To make the app close if a debugger is attached, I set the
Action property to Exit. This tells Dotfuscator to inject code that closes the app when the Check detects an unauthorized state. Note that the Check performs this Action after notifying the application, so in this scenario the incident report would be sent before the app closes.
Configuring the Tamper Check
Finally, I added a Tamper Check to address the reverse-engineering scenario. I clicked the Add Tamper Check button to configure a new Tamper Check, as shown in Figure 5.
Locations: Just as with the Query Debugging Check, I chose to give the Tamper Check multiple locations: LoginDialog.ConfirmLogin, CustomerWindow.UpdateData and Utilities.ShowAndHandleDialog.
With a Debugging Check, having multiple locations is important because the debugger could be attached at any time during execu- tion. But a Tamper Check will have only one result over a run of the app—the runtime loaded either an assembly that was modified or not. Shouldn’t one location be sufficient? Actually, because this Check is to deter tampered binaries, I have to consider a scenario where an attacker was able to remove the Tamper Check itself from a location. By having multiple locations, the application is more resilient to tampering.
You might notice that one of the locations, LoginDialog.Con- firmLogin, is the same as the one for the Login Debugging Check. Dotfuscator allows multiple Checks of different types to be injected at the same location. In this case, after the user logs in, both debugging and tampering will be checked.
Application Notification: For the Application Notification Sink, I decided it would be better in this case to have just one Sink for all of the locations. This is because unlike with the Query Debugging Check, I don’t really care on the reporting side which location triggers the Check.
I chose to define the Utilities.ReportTampering method as the Sink. As the context of each location varies, I had to declare the Sink static and ensure it was accessible from each location. The method is defined as such:
// In Utilities static class
internal static void ReportTampering(bool isTampered) {
if (isTampered) {
ClientAppInsights.TelemetryClient.TrackEvent(“Tampering Detected”); ClientAppInsights.Shutdown();
Whenever any of the Check’s locations are called, the Check determines whether it has been modified since Dotfuscator processed it, and then calls the ReportTampering method with a parameter of true if modification was detected and false otherwise.
Action: If the app is modified, it’s dangerous to continue. I con- figured this Check’s Action to Exit, so that the app closes when tampering is discovered.
Injecting the Checks
With the Checks configured, Dotfuscator can now inject them into the app. To do this, from Dotfuscator CE, open the AdventureWorks- SalesClient\\Dotfuscator.xml config file and then click the Build button.
Dotfuscator will process the Client’s assembly, inject the Checks, and write the protected Client out to AdventureWorksSalesClient\\ Dotfuscated\\Release. The unprotected app remains in Adventure- WorksSalesClient\\bin\\Release.
Testing the Checks
As with any security control, it’s important to test the app’s behav- ior when the control is introduced.
Normal Scenarios: The Checks shouldn’t have any impact on legit- imate users of the app. I ran the protected Client normally and saw no unexpected crashes, application exits or Application Insights events.
Unauthorized Scenarios: You should also verify that Checks do what you expect when the app is used in an unauthorized way. The sample code’s README lists detailed instructions for testing the Debugging Checks and the Tamper Check. For instance, to test the Query Debugging Check, I ran the protected Client several times, attaching WinDbg to the process at various points. The app correctly reported and responded to the presence of a debugger per the Check’s configuration.
Layered Protection Strategy
Using just one protection measure is insufficient for most prac- tical cases, and Checks are no exception. Checks should be just one layer of your protection strategy, along with techniques like end-to-end encryption, Authenticode assembly signing, and so on. When you use multiple protection layers, the strengths of one layer can offset a weakness of another layer.
In this article’s example, some Application Notification Sinks used by the Checks have names like isDebugged or ReportTampering. These names remain in compiled .NET assemblies, and an attacker could easily understand the intent of these code elements and work around them. To mitigate this, Dotfuscator can, in addi- tion to injecting Checks, also perform renaming obfuscation on your assemblies. For details, see the PreEmptive Protection – Dotfuscator Community Edition documentation (bit.ly/2y9oxYX).
Wrapping Up
This article introduced Runtime Checks and some of the problems they solve. Using a LOB app, I demonstrated how a data breach can occur in client software and how Runtime Checks can be config- ured to detect, report and respond to such a breach.
While this article covered the free Dotfuscator Community Edition, these same concepts can be transferred to the commer- cially licensed Professional Edition, which has additional features for Checks (bit.ly/2xgEZcs). You can also inject Checks into Java and Android apps with Dotfuscator’s sibling product, PreEmptive Protection - DashO (bit.ly/2ffHTrN). n
Joe Sewell is a software engineer and technical writer on the Dotfuscator team at PreEmptive Solutions.
ThankS to the following Microsoft technical expert for reviewing this article: Dustin Campbell
} }
48 msdn magazine
Security