05 Dec 2015

Since you asked.. How to obtain value of a field using WinDbg?

My friends occasionally ask me tricky questions - about PE file format, about .NET internals, usage of dnlib or WinDbg and what not. Even if I'm not an expert in some areas, I usually can figure out stuff pretty fast.

So, here's a question that li0nsar3c00l asked me few days ago:

How to get the value of a static field using WinDbg?

To put the question in context - he is trying to debug a .NET assembly which is obfuscated and all names are unprintable. When all names look like "□", it's quite hard to find out which is which - and I doubt you can use those names when setting breakpoints.. So, we need to figure out a way that avoids using object names.

I will assume that you have very basic knowledge of using WinDbg with .NET applications. If you don't, I suggest that you start by reading introductory tutorials, for example, Getting started with Windbg - part I and part II. You could also check WinDbg tutorial by netmatze. Or just go through the entire amazing collection of .NET Debugging Demos by Tess Ferrandez.

Quick answer

You can use !mx command to locate the class and field you need. Then you can use !mdt -e command to display values you need.

But if you have no idea how those commands work, please continue reading..

Long answer

Dealing with static classes and static fields is easier. After the corresponding .cctor is executed, you can get the values you need. But for non-static classes and fields you need to stop debugger at a place where an instance of the object is already created and values initialized.

So, we'll take a scenic route from the very beginning till the end. Here's a demo app you can test your skills with: https://www.mediafire.com/?wavmalk6sqhdcy6

  1. Load sos and sosex extensions. I'm using this one-liner for .NET 4.0 - you can use separate commands, if you prefer.
  2. Examine domain, find module
  3. Find the type you want
  4. Find the method you need
  5. Put breakpoint on the method and run
  6. Disassemble code, locate place where the interesting object will be already initialized.
  7. You need to put a breakpoint after the object is created and initialized.

    Unfortunately !U doesn't show IL code. So, let's use !mu output to confirm our findings:

    Command !mu doesn't show call targets but interleaves IL code with x86 code. Combining both outputs we know that we should get to address 003f00cd.

  8. Execute code to the place where data are already initialized
  9. Use command !mx
  10. This command is little known but it's bloody awesome!

    Usage: !sosex.mx <Filter String>

    Displays any matching type, method or field for <Filter String>, where <Filter String> is a string in module!metadataname format. If module! is not specified, all modules are searched for the specified metadata. Searched info includes types, methods and fields.

    In order to search globals, do not precede the field or method filter with a ".". To enumerate all globals for a given module filter, use "globals" as the type filter. eg: "globals" "*!globals" "mymod!globals", etc...

    So, let's ask to show us all objects from our test application:

  11. Get the address of class
  12. Class Bla contains static field key1 which we're interested in. Click on Bla hyperlink. You actually don't care about the output, just the address of class.

  13. Use !mdt command to get address of the field
  14. Use provided hyperlinks to access data
  15. Clicking on "02722340" and then on "Expand" will get you the good stuff. Or you can enter "!mdt" command manually:

    Congratulations, this is the value of static field. Task #1 done! smile

  16. Locate instance of the class
  17. Remember, we put a breakpoint just after the class initialization. You can either use your x86 knowledge and check the proper register values, or just display managed stack objects:

  18. Use !mdt command to get the stuff just like before
  19. Congrats, this is value of non-static field. Task #2 done!

This concludes our journey. Hopefully you learned something new today!