NET Debugging: Dump All Strings from a Managed Code Process Running

Introduction

Sometimes, we would like to know which critical information is in our process, like bank accounts or credit card numbers because we need to protect this information from malicious people, or just by simple exploration of which internal strings are there. The task is very simple. In the picture, we revealed the hidden text in the password. The procedure is applicable for every single .NET Running Process including IIS Worker Processes.

Final Output Picture

System.String class is one of the most used classes in .NET World. I cannot imagine a simple or Enterprise Software that does not use this.

We will use Windows Debugger and a simple script to do this task.

Launch Windbg (The favourite tool that Microsoft Support uses) if you do not have this, please download from Microsoft Site.

Copy the file %windir%\Microsoft.NET\Framework\v2.0.XXXXXX\SOS.DLL to %programfiles%\Debugging tools for windows\.

Execute the sampleApp.exe attached to this mail (This is a dummy sample app.)

In the Windbg, put the command: .load sos it allows to load the extension SOS.DLL which is a .NET Debugging helper file. It contains a lot of new commands and facilities to debug .Manager Apps.

SOS.DLL contains a very interesting command, !dumpheap, which allows to dump all classes which are in memory. It traverses the .NET Heap and dumps all the allocated objects. It also can be used to detect high memory usage. We will explain this in other articles.

!dumpheap –type System.StringThis command allow us to dump all the memory addresses for a System.String classes. The output will be:

Please take a look at this output: Address (The pointer to the String class), MT=Method Table, which is the pointer to the list of methods that System.String supports (We are not going to use MT at this time), and Size of this class.

!dumpheap –type System.String –short: This command will show just the memory addresses for the strings currently in memory.

!do[memoryaddress]: This command will dump the object from memory. Let's explore the second string: e.g.:!do 014d11c8

The string is: C:\blog\dumpstrings\SampleAPP\SampleAPP\bin\Debug\. But we are interested just in the chars itself, not in the complete class. Where are the characters located? Looking a little at the class we found that the m_first char is in the STRING MEMORY ADDRESS+c (Hexadecimal values). We can confirm this by exploring the memory address 014d11c8+c=014d11d4.

This is exactly what we are looking for. The first char of the string is located at: String Class Address + c. Please see in memory that every char for C letter is 43 00. What does this mean? Unicode? YES.

Windbg allows to iterate by each memory address that we dump with !dumpheap –type System.String –short.

Yes, you are right, but you can solve the issue by just having the following:
-Download the Windbg for Windows 64 bits.
-Instead of execute the command :
.foreach (obj {!dumpheap -type System.String -short}) {.printf "\n%mu",${obj}+c}

You could probably find/write an add-in for reflector to do this. The only advantage your method seems to have over this is that you will be able to inspect generated strings at runtime. But strings are formed and destroyed over the course of execution of a managed program; how do you decide when to break into your process for the string search?

But in any case to keep your strings secure at runtime use the .Net SecureString class.

The best way to accelerate a Macintosh is at 9.8m/sec-sec - Marcus Dolengo

Thanks for your feedback / suggestion, and yes, we can use Reflector, but the main disadvantage is that we cannot see the dynamic String classes generated and allocated in runtime. As you can see in the picture, the textbox hidden string is a dynamic variable that has been revealed in runtime.

The article has been wrote for the following purposes:
-Show how internally String class is represented in memory.
-How to walk in the Process Heap during runtime to find key information.

Why you would like to know in runtime? memory leaks are a good example. During my work experience memory leaks on string classes has been a headache, then I found a good way to know the content of them. Memory leaks happens because a runtime allocations.