How can I identify the version of a managed dll in windbg? - debugging

I have a minidump from a customer. I want to find out the assembly versions of the loaded .NET dlls. I've already searched the internet for hours now, but cannot find a usable way.
I have windbg and have loaded SOS extension an have the needed clr.dll and mscordacwks.
using lm -v only shows the unmanaged dll's. I am sure I am overlooking something very simple.

WinDbg's lm v shows all DLLs, managed and unmanaged. On that level, an assembly is just a DLL, is just a module.
With WinDbg 6.3.9600, lm v even shows information whether a modules has a CLR header or not:
0:008> lmv m MyApp
start end module name
10310000 10574000 MyApp(deferred)
Image path: C:\...\MyApp.exe
Image name: MyApp.exe
Has CLR image header, track-debug-data flag not set
Timestamp: Wed May 21 16:34:02 2014 (537CB95A)
...
ProductVersion: 1.8.0.44
FileVersion: 1.8.0.44
...
However, the FileVersion and ProductVersion is still unmanaged information compiled into the native resource part of the DLL.
I suggest you use !SaveModule <start address> <filename> to save the file on disk and then use a reflection tool like dotPeek to open it and get the assembly information from there, which will give you the name, version, culture and public key token.
To save all modules, Naveen has written a script like this:
!for_each_module .if ($spat ("${##ImageName}","*.exe")) { !SaveModule ${##Base} c:\temp\${##ModuleName}.exe } .else { !SaveModule ${##Base} c:\temp\${##ModuleName}.dll }

Alright, after some more research I came to the conclusion that that kind of information is just not available for those dll's in a minidump. Anyway I was at least able to get some more information about the files, and maybe this is useful for someone else in the future.
You can get at least the metata information of the dll's, and maybe you can find something useful in there. Here's how to do that:
First get the domain:
!dumpdomain
You might end up with a large amount of listed assemblies. Now you can either look them up by hand using:
!dumpassembly ADDRESS
or you can just use the lazy way: Install the python extension for windbg (http://pykd.codeplex.com/) and use the following script for a quick overlook (it's maybe not the nicest script, but it's working and I didn't want to invest more time):
import pykd
def dump_assemblies():
assemblies = 0
addrs = pykd.dbgCommand("!dumpdomain").splitlines()
for x in addrs:
if x[:8] == "Assembly":
assemblies = assemblies + 1
print "### retrieving assembly " + x[-8:]
print pykd.dbgCommand("!dumpassembly " + x[-8:])
print "### found " + str(assemblies) + " assemblies."
dump_assemblies()
You will now be able to do a text search (CTRL + F) for the dll. Once you found it, you can find the offset next to the module name (looks something like 12327C8 C:\Program Files\MyApp\MyDLL.dll).
You can now dump the module using:
!dumpmodule 12327C8
which will lead you to:
Name: C:\Program Files\MyApp\MyDLL.dll
Attributes: PEFile
Assembly: 131a22e2
LoaderHeap: 00000000
TypeDefToMethodTableMap: 19220010
TypeRefToMethodTableMap: 134303e0
MethodDefToDescMap: 13430740
FieldDefToDescMap: 13433964
MemberRefToDescMap: 134350c8
FileReferencesMap: 13435918
AssemblyReferencesMap: 1343591c
MetaData start address: 1c1aaa4c (4248 bytes)
Now you can check the metadata of the dll simply with:
dc 1c1aaa4c 1c1aaa4c + 4248
That's the closest I could get to more information about the DLL. Unfortunately the file version was not written there, just some other more generic info. Anyway, I will try to get in touch with the customer again. Thanks for the answers anyway.

Related

nim: Use a static library

I've tried to get an audio library statically linked to my program. I use this nimble package. To get it run, i had to build the soloud library as described here. For short after download i ran "genie --with-miniaudio-only --platform=x64 vs2017" in the "build" folder and got the source code to generate the dynamic and the static library. For now i can run the following demo program from the nimble package with the generated dll alongside:
import solouddotnim, times, os
var i, spin = 0
var sl : ptr Soloud
sl = Soloud_create()
discard Soloud_init(sl)
Soloud_setGlobalVolume(sl, 1)
var stream = WavStream_create()
discard WavStream_load(cast[ptr Wav](stream), "test.ogg")
let currentTime = epochTime()
let length = WavStream_getLength(stream)
discard Soloud_play(cast[ptr Soloud](sl), cast[ptr Wav](stream))
while epochTime() - currentTime <= length:
sleep(100)
Soloud_deinit(sl)
Soloud_destroy(sl)
Now to the static-link part. In the solouddotnim.nim file of the nimble package i use, i see this part:
when defined(windows):
const
libname* = "libsoloud.dll"
elif ...
So i simple changed the windows part to the following, re-installed the nimble-package and placed the "soloud_static_x64.lib" alongside to the "main.nim" of the testproject:
when defined(windows):
const
libname* = "soloud_static_x64.lib"
elif ...
But this doesent make it. (cant open "soloud_static_x64.lib" error when build)
Evereywhere where the constant "libname" is used there are the pragmas "cdecl", "importc" and "dynlib". For example:
proc Soloud_create*(): ptr Soloud {.cdecl, importc: "Soloud_create", dynlib: libname.}
So "dynlib" is telling nim to use a dll on windows. But was is the pragma for static libraries?
In the nim documentations i only found DynlibOverride to link to static libraries, but i dont understand the example and here is where i stuck. I've tried the followings:
nim c --dynlibOverride:libname --passL:soloud_static_x64.lib "examples\00-ogg\Example00_ogg.nim"
nim c --dynlibOverride:soloudtotnim --passL:soloud_static_x64.lib "examples\00-ogg\Example00_ogg.nim"
Firstly i dont know what parameter dynlibOverride expects and secondly both compiles, but dont work. It expects a dynamic library alongside the exe.
My last try was to remove all dynlib pragmas from the nimble package. But now i cant compile it.
undefined reference to `Soloud_create'
...
Error: execution of an external program failed: 'gcc.exe...
My knowlege ends here. Can someone help me?
Thanks in advance.
Edit:
I could not get any of your solutions work. I break down the problem as small as possible so everybody can reproduce this:
"foo.nim" contains this:
proc add*(a, b: int): int {.cdecl, exportc.} =
a + b
proc sub*(a, b: int): int {.cdecl, exportc.} =
a - b
The .lib is simply generated with this command: "nim c --app:staticlib foo.nim"
Now to use it i created a file "main.nim" with this content:
{.passL:"foo.lib".}
proc add*(a, b: int):int {.cdecl, importc.}
proc sub*(a, b: int):int {.cdecl, importc.}
echo add(10, 5)
echo sub(10, 5)
if i simply build it with "nim c -r main.nim", i get the following output and error:
P:\Nim\LearnCBinding>nim c -r main.nim
Hint: used config file 'C:\nim-1.5.1\config\nim.cfg' [Conf]
Hint: used config file 'C:\nim-1.5.1\config\config.nims' [Conf]
....CC: stdlib_io.nim
CC: stdlib_system.nim
CC: main.nim
Hint: [Link]
foo.lib(#mfoo.nim.c.o):#mfoo.nim.c:(.text+0x1f6): multiple definition of `PreMainInner'
C:\Users\Peter\nimcache\main_d\#mmain.nim.c.o:#mmain.nim.c:(.text+0x120): first defined here
foo.lib(#mfoo.nim.c.o):#mfoo.nim.c:(.text+0x20a): multiple definition of `PreMain'
C:\Users\Peter\nimcache\main_d\#mmain.nim.c.o:#mmain.nim.c:(.text+0x134): first defined here
foo.lib(#mfoo.nim.c.o):#mfoo.nim.c:(.text+0x240): multiple definition of `NimMainInner'
C:\Users\Peter\nimcache\main_d\#mmain.nim.c.o:#mmain.nim.c:(.text+0x16f): first defined here
foo.lib(#mfoo.nim.c.o):#mfoo.nim.c:(.text+0x254): multiple definition of `NimMain'
C:\Users\Peter\nimcache\main_d\#mmain.nim.c.o:#mmain.nim.c:(.text+0x183): first defined here
foo.lib(#mfoo.nim.c.o):#mfoo.nim.c:(.text+0x285): multiple definition of `main'
C:\Users\Peter\nimcache\main_d\#mmain.nim.c.o:#mmain.nim.c:(.text+0x1b4): first defined here
foo.lib(#mfoo.nim.c.o):#mfoo.nim.c:(.text+0x2da): multiple definition of `NimMainModule'
C:\Users\Peter\nimcache\main_d\#mmain.nim.c.o:#mmain.nim.c:(.text+0x209): first defined here
collect2.exe: error: ld returned 1 exit status
Error: execution of an external program failed: 'C:\nim-1.5.1\dist\mingw64\bin\gcc.exe -o P:\Nim\LearnCBinding\main.exe C:\Users\Peter\nimcache\main_d\stdlib_io.nim.c.o C:\Users\Peter\nimcache\main_d\stdlib_system.nim.c.o C:\Users\Peter\nimcache\main_d\#mmain.nim.c.o foo.lib '
Because of the multiple definition error i also tried to build foo.lib with parameter "--noMain:on", but it doesnt make any difference.
Do you have the same problem? By the way i use the current version of Nim "nim-1.5.1" and reinstalled MingW with the finish.exe from nim.
I will try to help you with the following error you have:
undefined reference to `Soloud_create'
but i will assume that you have configured your environment so you can compile your nim programs with visual studio compiler (by adding --cc:vcc to your compile command)
this is because you already seem to have visual studio 2017 and you are compiling soloud static library with it. I think this is the best option when you are compiling with one compiler both: static library and executable that will use it.
open your static library (soloud_static_x64.lib) with some text/hex editor and search for "Soloud_create". i guess you will not find anything. so why is that? because for some reason author decided to not include "C interfacing" in a static library project. so it contains only C++ symbols and not pure C symbols that are needed for our solouddotnim.nim module.
let's try to find out what .cpp file we need for that. i noticed this information on official web site of Soloud - http://sol.gfxile.net/soloud/c_api.html
so i guess we need only one file: soloud_c.cpp
let's try to just include it in SoloudStatic.vcxproj file generated by you with Genie. like this:
..
<ClCompile Include="..\..\src\c_api\soloud_c.cpp">
</ClCompile>
..
and recompile our static library. i use this command in powershell:
& 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin\MSBuild.exe' /p:PlatformToolset=v142`;WindowsTargetPlatformVersion=10`;Configuration=Release`;Platform=x64 .\SoloudStatic.vcxproj
but you can compile how you want. just make sure that it's architecture is really x64. you can check it with this command:
dumpbin /headers soloud_static_x64.lib | more
finally just link it with your nim file. add this line to the top:
{.link:"soloud_static_x64.lib".}
and compile nim file with this command:
nim c --cc:vcc --dynlibOverride:libsoloud.dll -r "examples\00-ogg\Example00_ogg.nim"

Is there a known issue relating to Windows 7 Kernel Symbols?

I have a few Windows 7 machines that I am not able to read their memory dumps. I found something that I suspect may be related, but am not positive:
https://twitter.com/aionescu/status/634028737458114560
I also found this: http://support.microsoft.com/kb/2528507
However, the scenario message regarding wow64exts given in the doc is not seen in any of my dumps. I also cannot apply that hotfix at this time to test it. So I'm just looking for some more information or opinions.
I'm able to open any other OS dump as well as my own system's Windows 7 dump, but there are 2 other machines that run Win 7 and it's telling me I have the wrong kernel symbols.
I have tried clearing out my symbol cache, reinstalled the Windows SDK, and also tried to open the dumps on two other machines with the same result. If it matters, the crash is manually created using the scroll lock method.
Symbol path: SRV*c:\symbols*http://msdl.microsoft.com/download/symbols;
Seeing these errors: followed by "Type referenced: nt!_KPRCB"
Does anyone know about the issue mentioned by Alex in the twitter link and if it's possibly related to what I'm seeing?
Update 2015-10-22:
With the Microsoft patch day (2015-10-13) and KB3088195, symbols are available again.
However, symbols for the broken version have not been provided, so below may still be useful.
Microsoft has already published "good" symbols for ntdll in the past, containing type information like _TEB or _KPRCB. Starting from mid of July 2015, Microsoft has still published symbols for ntdll, but not containing that information.
So it depends on the version of ntdll whether you get type information or not. Old dumps referencing an old version of ntdll will download old PDBs containing type information while new dumps reference new versions of ntdll and WinDbg (or any other debugger) downloads PDBs without type information.
Could Microsoft remove type information of "good" symbols retroactively, thus making them "bad"?
Yes. As described in this answer, there is a tool to remove type information from existing PDBs. Doing that and replacing the PDB would result in such an effect.
Can Microsoft publish the "good" version of those PDBs which are currently "bad"?
That's hard to tell, since we don't know whether Microsoft has kept a copy of the "good" version so they could replace the "bad" version on the symbol server with the "good" one. Rebuilding ntdll from the same source code and thus creating new PDBs sounds possible, but the PDB gets a new time stamp and checksum. This can potentially be corrected manually, especially be Microsoft, since they should have the knowledge about the PDB internal format, but IMHO it's unlikely they'll do that. Things may go wrong and MS will hardly have tests to guarantee the correctness of such a thing.
So what can I do?
IMHO you can do nothing to really correct the situation.
You could assume that the types in ntdll have not changed so much. This would allow you to take an older version of wntdll.pdb and the new version of ntdll.dll and apply ChkMatch -m to it. This will copy the timestamp and checksum from the DLL to the PDB. After you did that (in an empty folder), replace the existing wntdll.pdb in your symbols directory with the hacked one.
WinDbg walkthrough (with output shortened to relevant things). I am using the latest version of wntdll.pdb I could find on my PC.
WARNING: doing the following may fix the type information but will likely destroy the correctness of the callstacks. Since any changes in the implementation (which are likely for security fixes) will change the method offsets.
0:005> dt nt!_PEB
*************************************************************************
*** ***
*** Either you specified an unqualified symbol, or your debugger ***
...
*** Type referenced: nt!_PEB ***
*** ***
*************************************************************************
Symbol nt!_PEB not found.
0:005> lm m ntdll
start end module name
773f0000 77570000 ntdll (pdb symbols) e:\debug\symbols\wntdll.pdb\FA9C48F9C11D4E0894B8970DECD92C972\wntdll.pdb
0:005> .shell cmd /c copy C:\Windows\SysWOW64\ntdll.dll e:\debug\temp\ntdllhack\ntdll.dll
1 file(s) copied.
0:005> .shell cmd /c copy "E:\Windows SDk\8.0\Debuggers\x86\sym\wntdll.pdb\B081677DFC724CC4AC53992627BEEA242\wntdll.pdb" e:\debug\temp\ntdllhack\wntdll.pdb
1 file(s) copied.
0:005> .shell cmd /c E:\debug\temp\ntdllhack\chkmatch.exe -m E:\debug\temp\ntdllhack\ntdll.dll E:\debug\temp\ntdllhack\wntdll.pdb
...
Executable: E:\debug\temp\ntdllhack\ntdll.dll
Debug info file: E:\debug\temp\ntdllhack\wntdll.pdb
Executable:
TimeDateStamp: 55a69e20
Debug info: 2 ( CodeView )
TimeStamp: 55a68c18 Characteristics: 0 MajorVer: 0 MinorVer: 0
Size: 35 RVA: 000e63e0 FileOffset: 000d67e0
CodeView format: RSDS
Signature: {fa9c48f9-c11d-4e08-94b8-970decd92c97} Age: 2
PdbFile: wntdll.pdb
Debug info: 10 ( Unknown )
TimeStamp: 55a68c18 Characteristics: 0 MajorVer: 565 MinorVer: 6526
Size: 4 RVA: 000e63dc FileOffset: 000d67dc
Debug information file:
Format: PDB 7.00
Signature: {b081677d-fc72-4cc4-ac53-992627beea24} Age: 4
Writing to the debug information file...
Result: Success.
0:005> .shell cmd /c copy E:\debug\temp\ntdllhack\wntdll.pdb E:\debug\symbols\wntdll.pdb\FA9C48F9C11D4E0894B8970DECD92C972\wntdll.pdb
1 file(s) copied.
0:005> .reload
Reloading current modules
.............................
0:005> dt nt!_PEB
ntdll!_PEB
+0x000 InheritedAddressSpace : UChar
+0x001 ReadImageFileExecOptions : UChar
...
0:005> !heap -s
LFH Key : 0x219ab08b
Termination on corruption : DISABLED
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-----------------------------------------------------------------------------
Virtual block: 00920000 - 00920000 (size 00000000)
Virtual block: 02c60000 - 02c60000 (size 00000000)
Virtual block: 02e10000 - 02e10000 (size 00000000)
...
Note: using ChkMatch like this has the benefit that you do not need to turn on .symopt- 100, since that option would affect all PDB files, and you would not find potential other symbol issues. If you don't mind using .symopt, you could simply copy an old wntdll.PDB over the new one.
The issue is now fixed according to Microsoft and Microsoft told me that you should clear your symbol cache to get the new PDBs, otherwise Windbg would use the old Symbols which miss the information.

QT 5.2 app cannot start (Bad allocation error) when Qt5Core.dll is in app directory

I have a funny problem on my machine
Windows 7 x64, using QT 5.2 for the GUI
I'm not able to start the app I always receive the error
First I thought I had a broken dll, so through some trial and error I found a solution:
I add the QT5Core.dll via enviroment path, and NOT directly to the app folder. Then the programm works. If I copy the dll back to the app Folder, Same problem as before!?!?!?1
I'm really confused, because the error only occurs on my machine?
Debugging doesn't really help,
In code, the error occures here:
MyApplication::MYApplication(int argc, char** argv, int version)
: QApplication(argc, argv, version) // <<< this call fails!
{ }
somebody can help me?
Why is the location of the qt5core.dll a problem?!?!?
UPDATE
I used the profiling function of depends and found the following behaviour:
Failing
GetProcAddress(0x76800000 [c:\windows\syswow64\KERNEL32.DLL], "CreateSymbolicLinkW") called from > "dirone\xxxx.EXE" at address 0x00FF2877 and returned 0x7688CCE9.
First chance exception 0xE06D7363 (Microsoft C++ Exception) occurred in "c:\windows\syswow64\KERNELBASE.DLL" at address 0x765CC41F.
Exception: "bad allocation"
Working
LoadLibraryW("C:\BuildPackages\QT\plugins\platforms\qwindows.dll") called from "dirtwo\QT5CORE.DLL" at address 0x66AA5154.
Loaded "c:\buildpackages\qt\plugins\platforms\QWINDOWS.DLL" at address
0x0F380000. Successfully hooked module.
somehow the path to the qwindows.dll is hardcoded into the dll (there is no environment path to this directory)
If I rename the qwindows.dll or delete it, startup failes again.
BUT the qwindows.dll is bundeld with our product. It is in a subdirectory ./platforms/
AND the files are the same (diff returns equal)
Somebody have some clue what I should try next?
Check if you already have some qt related environmental variables.
Crashes are usually due to this, remove those envronmental variables first. Check whether you have any other qt installed libraries.
it would be better if you can post the cal stacks.
Some other dlls are needed that reside in the directory of the qt5core.dll. When you add this path to the search path the dlls are found. When you simply copy the dll these dlls can not be found. You can check dependencies with the depends tool.
Candidates for the additional dlls are:
icuin51.dll and icuuc51.dll
Found the Problem:
The enviromentvariable:
QT_QPA_PLATFORM_PLUGIN_PATH=C:\BuildPackages\QT\plugins\platforms
was set to the path. If removing this variable, everything works as it should!

SOS Name2EE only showing Module and Assembly information

I just discovered SOS Extensions and am trying it out with a stupid hello world console app in Visual Studio 2010. I have enabled debugging unmanaged code and executed .load sos on my project properties. However, when I do !Name2EE App.exe!Program I only see the Module and Assembly info. I don't see the MethodTable or anything else:
!Name2EE App.exe!Program
Module: 001c2e9c
Assembly: App.exe
Can anyone shed some light on why I'm not seeing the rest of the info?
Try using actual type name including namespace:
0:000> !Name2EE HelloWorld!MyCompany.HelloWorld.Program
Module: 00182e9c
Assembly: HelloWorld.exe
Token: 02000006
MethodTable: 00183888
EEClass: 00181794
Name: MyCompany.HelloWorld.Program
If you specify a filename with extension, separate the module from the type.
!name2ee app.exe Program
-OR-
!name2ee app!MyApp.Program
Also, as the previous answer indicated, always use the FULL type name.

how windbg determine which OS symbols to download for a dump file

When I do a dump file analysis, I setup symbol path to point to Microsoft symbol server. How does windbg knows that the dump file was generated under what OS and how does it downloads correct symbols for that OS?
To match symbols to binary, WinDbg looks at the thing called Debug Directories. Debug Directories are sections in PE modules (which is a file format used by Windows for all types of executables). Debug Directories simply contain links to types of debug information. If you type command in cmd window link /dump /headers <my_module_name>, it will print out something like this:
...
Debug Directories
Time Type Size RVA Pointer
-------- ------ -------- -------- --------
4CC78FB1 cv 22 00102588 101988 Format: RSDS, {30976E0B-FBF7-45EF-8608-99932F2B791F}, 2, ntdll.pdb
4CC78FB1 ( A) 4 00102584 101984 BB03197E
...
This is output for ntdll.dll. You can see that CV (for CodeView) debug information is contained in ntdll.pdb, and GUID of that PDB has to match the one in the link. That GUID is generated randomly for each module at build time.
Command !lmi in WinDbg will also dump this information, in different format.
What WinDbg does when loading symbols from symbol server is it sends request to symbol server to get file named 'ntdll.pdb' with matching GUID.

Resources