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 firstname.lastname@example.org or email@example.com and I will be happy to assist you. To proceed with this article, please use the attached file to debug this one.
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).
Let's start the process with
Windbg (File->Open Executable):
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.
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
e (Execute the command)
!clrstack (print the stack given a thread):
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:
Interesting! Looks like the process is trying to read a
string from the user (
System.Console.Readline), and there is a
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:
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:
!dumpmt allows us to get the Method Table and
–MD gives us the method description for each Method contained in this Method Table.
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
0:000> !bpmd -md 00973378
MethodDesc = 00973378
Adding pending breakpoints...
We can continue running our application and use this (press F5):
And press ENTER in my small app.
Please note that if we press enter, our program freezes. What happened? Go back to
Good. Seems like our executable breaks at the expected function, to ensure this run the command
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
!clrstack –p (-p means parameters)
SOS helper has an interesting command (
!do DumpObject) let's use this. Given a Pointer of the
Object address, it prints for us the
Cool, this is the
string that we entered in the Sample.exe console.
!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:
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:
As the picture shows, the first char starts at 0x014e9b90c and the initial address was 0x014e9b90.
.printf "%mu", 0x014e9b90+c
Executing the command:
Cool, we wrote the
string .printf prints an
string on the
Windbg screen given an address terminated in
%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.
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:
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:
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
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.
char to be inside “”
\\n=\n carriage return. Put F5 and continue using the Sample.exe.