Friday, September 28, 2012

.NET Assembly 32bit or 64bit, Signed or Unsigned?

Sometimes before starting debugging, we need to know whether the .NET assembly is 32bit or 64bit. One simple way of doing it is to use a .NET tool called CorFlags.EXE. In order to use it, open [Visual Studio Command Prompt (2010)] and run CorFlags.exe with an assembly filename. This will show some assembly information as you see below.


To see 32bit, 64bit or any CPU, you check PE and 32BIT lines.

PE: PE32 / 32BIT: 1 = x86
PE: PE32 / 32BIT: 0 = Any CPU
PE: PE32+/ 32BIT: 0 = x64

You can also check whether the assembly is signed or not. Signed at the last line indicates whether it's signed. Signed : 0 in above example means that the assembly is not signed by key and so it's not the strongly named assembly; cannot be put into the GAC.

CorFlags.EXE tool not only shows assembly information but also can be used to change assembly header. For example, if you want to change 32bit to Any CPU, you can run:

C> CorFlags MyApp.exe /32bit-

Thursday, January 26, 2012

Windbg: The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos) failed

When debugging managed code application in Windbg, we have to load sos, correct version of SOS. One of occasional error during SOS loading is LoadLibrary failure as shown below.

0:000> .loadby sos clr
The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos) failed, HRESULT 0x80004005
    "Unspecified error"
Please check your debugger configuration and/or network access.

A simlar error (The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos) failed, Win32 error 0n193) can occur for .loadby sos mscorwks command for .NET 2.0 application (or prior to .NET 4.0 application).

To investigate the issue, we can check CLR.dll information since .loadby command loads sos.dll based on the clr.dll location information (or based on mscorwks.dll for prior to .NET 4.0).

0:000> lmvm clrstart             end                 module name
00000000`69180000 00000000`697ee000   clr        (deferred)            
    Image path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll    Image name: clr.dll
    Timestamp:        Sat Jul 09 02:07:57 2011 (4E181A6D)
    CheckSum:         0067171F
    ImageSize:        0066E000
    File version:     4.0.30319.239
    Product version:  4.0.30319.239
    File flags:       8 (Mask 3F) Private
    File OS:          4 Unknown Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0409.04b0
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft® .NET Framework
    InternalName:     clr.dll
    OriginalFilename: clr.dll
    ProductVersion:   4.0.30319.239
    FileVersion:      4.0.30319.239 (RTMGDR.030319-2300)
    PrivateBuild:     DDBLD234
    FileDescription:  Microsoft .NET Runtime Common Language Runtime - WorkStation
    LegalCopyright:   © Microsoft Corporation.  All rights reserved.
    Comments:         Flavor=Retail

The lmvm clr command shows that clr.dll is located in 32bit Framework directory. If the clr.dll is located in Framework64 directory (C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll), it means clr.dll is loaded from 64bit .NET  Framework.
Since the CLR is loaded from 32bit .NET Framework, SOS.dll will be loaded from 32bit Framework which is why the error message said LoadLibrary(..\Framework\sos).

Now why is LoadLibrary() for 32bit SOS.dll failing, even if the sos.dll is there in the directory? The thing is SOS does not support cross-platform debugging. That is, 64bit debugger can only use 64bit SOS, while 32bit debugger only uses 32bit SOS. So for 32bit .NET application debugging, one has to use 32bit debugger and same goes for 64bit.

So original error occurred when using 64bit Windbg against 32bit .NET application dump. When 32 bit Windbg was used, the problem was gone.

Sunday, January 15, 2012

Windbg : Display parameters whenever specific function is called

Whenever a specific function is called, we might want to know its parameters information for the function. If a function is called once or twice, simple breakpoint (bp) should work well. But, what if the function is called hundreds of time? There is gotta be smarter way and there is.

bp command can be used with "user defined command." So everytime the breakpoint is hit, we can run some commands accordingly.

Let's take an example. Let's say, whenever LoadLibrary() function is called, we want to display its parameter (which is libraray dll name).

(1) First, we have to set breakpoint on LoadLibrary. Whenevery the library is called, we will do something... LoadLibrary() function is in kernel32.dll. One thing to note is that LoadLibrary is actually win32 macro, so there is no actual library in binary DLL level. It is converted to actual function name (LoadLibraryW or LoadLibraryA) depending on ANSI/Unicode.

    0:000> bp kernel32!LoadLibraryW

(2) Now, to do some actions, we add multiple commands separated by semi-colon and have the commands enclosed by double quotations.

     syntax :  "command1; command2; command3"
  
Here is an example of displaying first parameter for LoadLibraray() function.

     0:000> bp kernel32!LoadLibraryW ".echo *****;du dwo(esp+4);k;g;"

  • .echo command display any text.
  • du command display any Unicode string from the specified address.
  • dwo() function returns double word value from the specified address.
  • esp is ESP register that contacts current stack pointer.
  • k is to show callstack to see who is calling this function. This one is just optional.
  • g command make the debugger keep running.
So the command above will keep displaying parameters whenever debugger encounters the specific function.

Let's look at the stack a little further. Whenever a function is called, that is whenever assembly language 'call' command is executed, 'return address' is automatically saved after parameters in the stack. When a breakpoint is occurred at the beginning of the function, stack pointer is pointing to 'return address.' So the first parameter memory address at the breakpoint time is stackpointer (esp) + 4 bytes location.


Stack State when a func is called

If looking at the result of kb command (display call stack with 3 params) at the breakpoint, the address in ChildEBP points the "Saved EBP." even if previous EBP is not saved yet (explained later). RetAddr is the value of 0008eb38+4 memory address. Args to Child are the actual parameter values which are located at 0008eb38+8, 0008eb38+C, 0008eb38+0x10. LoadLibraryW only has one parameter, so actually meaningfyl parameter is first parameter only for this function.
0:000> kb
ChildEBP RetAddr  Args to Child             
0008eb38 76eacf0e 0008eb48 76f10718 003a0043 kernel32!LoadLibraryW
0008ed54 76eab8b3 0008f4dc 0008f420 00000001 USER32!User32InitializeImmEntryTable+0xffa
0008f40c 776f9950 76e90000 00000001 0008f714 USER32!UserClientDllInitialize+0x1c6
0008f42c 776fd8c9 76eab6ed 76e90000 00000001 ntdll!RtlQueryEnvironmentVariable+0x241
0008f520 7770681c 0008f714 7efdd000 7efde000 ntdll!LdrResSearchResource+0xb4d
0008f6a0 777052d6 0008f714 776c0000 77efe3a9 ntdll!RtlGetNtVersionNumbers+0x9b
0008f6f0 776f9e79 0008f714 776c0000 00000000 ntdll!RtlSetUnhandledExceptionFilter+0x50
0008f700 00000000 0008f714 776c0000 00000000 ntdll!LdrInitializeThunk+0x10

When a function is called, the first thing the function does is to save previous EBP and reset stack pointer (ESP) to EBP. This is done by three assembly instructions as you can see below. When this instructions are done, EBP and ESP point to the same address and all local vairables are pushed on top of the stack.
0:000> u .
kernel32!LoadLibraryW:
75a548fb 8bff            mov     edi,edi
75a548fd 55              push    ebp
75a548fe 8bec            mov     ebp,esp