Please enter the text to find and press Search.
Sorry

An error occurred during search results load.

Nonintrusive Debugging

Introduction

When debugging is on, not only the corresponding .pdb file gets processed during obfuscation but some of code optimizations are turned off to improve the interactive debugging experience for the resulting assembly. This leads to a bit different timing and size characteristics of the resulting code. The micro changes in characteristics may mask or unmask the defects in your code, especially those tied to unpredictable factors such as time. The multithreaded deadlock is a canonical example of such defect.

Sample Scenario

Let's take a look on concrete example. Suppose your obfuscated application suffers from intermittent multithreaded deadlock. You want to fix that. Everything you currenty have is an obfuscated .exe file without debugging information.

The next logical step is to find the source file names and line numbers where deadlock occurs. Being a quick and somewhat lazy person, you temporarily disable obfuscation for your assembly. Then you build it just to find out that deadlock does not occur anymore.

You think: Hm... probably the issue is tied to that exact obfuscated file somehow. You enable obfuscation again for that assembly. Then you build it. The deadlock shows itself again.

You think: Ok, let's try debug directive and then attach debugger to the process. You write:

[assembly: Obfuscation(Feature = "debug", Exclude = false)]

Then you build and run your project again only to find out that deadlock mysteriously does not occur anymore. How is that possible that a debug directive affects the runtime behavior?

The answer is debug directive does not affect the runtime behavior. It just induces slight changes in code speed and size. It turns out that those slight changes are enough to mask the multithreading defect in the code.

No problem, just use the nonintrusive flag:

[assembly: Obfuscation(Feature = "debug [nonintrusive]", Exclude = false)]

It minimizes the amount of changes applied by Eazfuscator.NET to the assembly that are required to provide the debugging functionality. In this way, the assembly characteristics stay the same even when debugging is on. Now you get a reproducible defect together with debug information. So you build your project again and run it. The deadlock is reproduced.

What you do next is attach debugger to your running deadlocked process. Launch Visual Studio and use DebugAttach to Process... (Ctrl+Alt+P) menu item. Then, select your process from the list.

The next step is to freeze all running threads with DebugBreak All (Ctrl+Alt+Break) menu item. Then take a look at DebugWindowsThreads (Ctrl+D,T) window and go through threads one by one while examing their call stacks. Once you find the suspected call stacks please write down the file names and line numbers of possible deadlock locations.

You now have the information to proceed with a fix to your source code.

[Note]Note

Stepping through the code (e.g. interactive debugging) is hugely limited when nonintrusive flag is specified. Essentially you can only attach debugger to a process and freeze the threads as a last resort solution.

Sorry

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