Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / MSIL

Advanced .NET Debugging Extracting Information from Memory

4.90/5 (15 votes)
2 Nov 2011CPOL6 min read 55.7K   226  
Advanced .NET Debugging Extracting Information from Memory

Introduction

In real life, for any Software Product we have this in Development and Production. In development, we found issues and having the code it is more easy to detect and fix, which is not the case in QA (sometimes) and production environments.

As Quality Assurance engineer, our work is not just to find issues, the more important part of them is to isolate the problem, in order to give the developer the best information as possible. In QA, we need an environment similar to that the user has, and sometimes we are not able to use the source code for issue isolation.

In this example, we are going to show the most simple case “How to see the input parameters of a simple function in a class” without having the source code in runtime. To do this, we are going to use a very simple function contained inside an executable. Our main tool will be Windows Debugging for Windows and SOS for .NET Debugging. Let's suppose that we do not have a good Logger level from development

The main challenge here is: Find the interesting function to get Input Parameters, and print them directly from Process Memory. The article is a little longer, but the same article is applicable to ASP.NET processes or Windows Processes, I will post more articles in the future. If you need some help, please email me at rpally@reversingsoftware.com or jrpally@hotmail.com and I will be happy to assist you. To proceed with this article, please use the attached file to debug this one.

Let's Start

Install and download Windows Debugger tool from http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx.

Once installed, copy the .NET helper debugging file from %WINDIR%\Microsoft.NET\Framework\v2.X.XXXXX\SOS.dll to %PROGRAMFILES%\Debugging Tools for Windows (x86).

Launch Windbg:

Image 1

Let's start the process with Windbg (File->Open Executable):

Image 2

At this time, the executable file did not start yet and Windbg CMD prompt will be open.

Load the library SOS.DLL to load the .NET debugging helper. .load sos

Just press F5 to get the executable running.

Image 3

Please note that the Sample.exe program is running under the debugger.

We would like to freeze our sample.exe process. To do this, just Click on the debugger and press CTRL+BREAK.

Let's explore the main thread of our executable and the stack trace until this time. To do this, we are going to use ~ (thread) * (all) e (Execute the command) !clrstack (print the stack given a thread):

~*e !clrstack 

We are displaying all threads and their stacks (Note that we are using !clrstack which is included in the SOS.DLL file).

The output will be:

Image 4

Interesting! Looks like the process is trying to read a string from the user (System.Console.Readline), and there is a Main Function.

Now we want to get the methods that encapsulate the class ConsoleApplication12.Program, to do this there are many ways. Let's explore this one:

!ip2md: IP Instruction Pointer to Method Description, given an IP (EIP in this case) address, we want to convert this to method description which is an internal structure of CLR .NET that gives us their method name and IL CODE:

Image 5

We got:

Image 6

Cool, we got the address of the Method Table of this class, Method Table is an internal structure that contains the List of the Methods of a class.

Let's explore the Method Table:

Image 7

!dumpmt allows us to get the Method Table and –MD gives us the method description for each Method contained in this Method Table.

We got:

Image 8

Cool, we have a ConsoleApplication12.Program.NumberOfWords method. What if we decide to set a breakpoint here? On Windbg (Windows Debugger) unmanaged we have the command bp (Breakpoint) but we can observe that the method NumberOfWords was not Jitted yet (The method has not run and we do not have their exact their Entry Point), but SOS allows us to set a breakpoint using Method Desc:

!bpmd –md 0097c011

Image 9

The result:

0:000> !bpmd -md 00973378

MethodDesc = 00973378

Adding pending breakpoints... 

We can continue running our application and use this (press F5):

Image 10

And press ENTER in my small app.

Please note that if we press enter, our program freezes. What happened? Go back to Windbg:

Image 11

Good. Seems like our executable breaks at the expected function, to ensure this run the command !clrstack.

Image 12

Good! Our stack trace shows that the Executable stops on NumberOfWords method, but what if we can show a more detailed stack? ;) Use !clrstack with the flag –p:

!clrstack –p (-p means parameters)

Image 13

SOS helper has an interesting command (!do DumpObject) let's use this. Given a Pointer of the Object address, it prints for us the object:

Image 14

We got:

Image 15

Cool, this is the string that we entered in the Sample.exe console.

Printing the string using !do command could be a problem in display, since it also prints additional elements like name, method table and other ones.

We are interested in printing just the string itself: Let's explore a little the memory for this object.

Click on Windbg View->Memory / on Virtual: write 014e9b90 (the address of the memory which contains the object:

Image 16

Good, we have the string in memory, how can we print this in console? (Please note that every character in the string has a 00 byte) Unicode string? The answer is YES.

But why the real string (“rene pally from <country-region w:st="on"><place w:st="on">Bolivia”) do not starts in 0x014e9b90 address? The answer is: It because 0x014e9b90 is the address of the CLASS and not the address for the FIRST CHAR.

The first char has the bytes 00 72 Unicode Notation and their char is: r.

As the picture shows, the first char starts at 0x014e9b90c and the initial address was 0x014e9b90.

Let's use:

.printf "%mu", 0x014e9b90+c 

Executing the command:

Image 17

Cool, we wrote the string .printf prints an string on the Windbg screen given an address terminated in NULL, %mu is used to print an array of chars given in Unicode format.

We explained why we need to add the 0xc to the initial address of the string, it has a logic, since in the String structure, the OFFSET of the first char shows as 0xc.

The String Object Address can change the next time that the process is executed, what can we do? The object address for input addresses is stored in the stack, and in some processor registers:

Image 18

After running a second time, the object address changed to 0x0155fe28. We used the command r to show the registers, and if we match ECX with the Object address, they are equal, let's use:

.printf "%mu",ecx+c 

Image 19

Setting the breakpoint: Now that we have found the way to print a S<code>tring class directly from memory, we can use BP and with their command:

bp eip ".printf \"\\n%mu\",ecx+c;gc" 

Let's explain this breakpoint.

  • BP = set a breakpoint
  • EIP = the current EIP address (Current Instruction pointer), remember that we stopped the function in the start of the function NumberOfWords

BP supports additional commands when the breakpoint stops, once we stopped in the breakpoint we need to print the ECX+C, once we print this, we need to continue with GC which is a command to continue the execution.

\” escape char to be inside “” string

\\n=\n carriage return. Put F5 and continue using the Sample.exe.

Image 20

Thanks! :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)