是否可以将任意(包括动态创建的)程序集从windbg转储到文件中?

时间:2013-11-12 18:29:04

标签: .net debugging windbg

我有一个.NET应用程序的转储,它创建并加载了太多的动态程序集。我想检查一下这些组件中的内容。

为此,我想将这样的程序集转储到文件中并在Reflector中打开它。

问题 - 我不知道该怎么做。

所以,我的问题是这个 - 给定一个完整的内存转储,如何将一个任意的程序集转储到一个文件中,使新文件是一个有效的.NET模块或程序集本身?

更简单的变化 - 如何从实时调试会话中完成?

我正在使用带有SOS和SOSEX的WinDBG。

编辑1

所以,3年后我再次需要它。以下是!DumpDomain的相关输出:

Assembly:           007f89a0 (Dynamic) []
ClassLoader:        00877998
SecurityDescriptor: 00879410
  Module Name
054d0010    Dynamic Module

从这些信息开始,我如何找到此程序集的开头和结尾?然后我可以使用.writemem命令。

3 个答案:

答案 0 :(得分:3)

测试代码 - http://www.dotnetspider.com/resources/22226-Creating-Dynamic-Assembly-A-Step-Ahead-Series.aspx

0:000> !DumpDomain

Assembly:           00680f48 (Dynamic) []
ClassLoader:        00681010
SecurityDescriptor: 00680eb0
  Module Name
0058386c    Dynamic Module

0:000> !DumpModule -mt 0058386c    
Name:       Unknown Module
Attributes: Reflection SupportsUpdateableMethods
Assembly:   00680f48
LoaderHeap:              00000000
TypeDefToMethodTableMap: 00581b54
TypeRefToMethodTableMap: 00581b68
MethodDefToDescMap:      00581b7c
FieldDefToDescMap:       00581ba4
MemberRefToDescMap:      00000000
FileReferencesMap:       00581bf4
AssemblyReferencesMap:   00581c08

Types defined in this module

      MT  TypeDef Name
------------------------------------------------------------------------------
00583c98 0x02000002 <Unloaded Type>

Types referenced in this module

      MT    TypeRef Name
------------------------------------------------------------------------------
726826a0 0x02000001 System.Object
72647e4c 0x02000002 System.Console
0:000> !DumpMT -md 00583c98 
EEClass:         0060121c
Module:          0058386c
Name:            <Unloaded Type>
mdToken:         02000002
File:            Unknown Module
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 6
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
7258a630 7227801c PreJIT System.Object.ToString()
7257f750 72278024 PreJIT System.Object.Equals(System.Object)
7257f380 72278044 PreJIT System.Object.GetHashCode()
7257f040 72278058 PreJIT System.Object.Finalize()
005f03d0 00583c90    JIT dynamicAssemblyClass..ctor()
005f03e8 00583c84    JIT dynamicAssemblyClass.HelloWorld()
0:000> !DumpIL 00583c84
FindIL failed
0:000> !U 005f03e8 
Normal JIT generated code
dynamicAssemblyClass.HelloWorld()
Begin 005f03e8, size 1a
>>> 005f03e8 55              push    ebp
005f03e9 8bec            mov     ebp,esp
005f03eb e8b856f871      call    mscorlib_ni!System.Console.get_Out() (72575aa8)
005f03f0 8bc8            mov     ecx,eax
005f03f2 8b15a0210703    mov     edx,dword ptr ds:[30721A0h] ("Hello! This is a dynamic assembly.")
005f03f8 8b01            mov     eax,dword ptr [ecx]
005f03fa 8b403c          mov     eax,dword ptr [eax+3Ch]
005f03fd ff5010          call    dword ptr [eax+10h]
005f0400 5d              pop     ebp
005f0401 c3              ret

不如反射器好,但你可以看到类型和方法。

答案 1 :(得分:1)

您可以使用.imgscan扫描整个虚拟内存中的DLL。我在内存中运行动态程序集时执行了此操作,但.imgscan未找到它。它没有典型的MZ标头,因此反射创建的程序集似乎不是可以保存到磁盘的DLL文件。否则,您可以使用.writemem将其保存到磁盘。

答案 2 :(得分:0)

您需要使用SOS中提供的!SaveModule命令。它有两个参数:1)起始地址和2)导出路径。您可以通过使用lmv检查模块详细信息来找到起始地址。

例如,如果要导出clr.dll,请先键入lmv m clr以验证起始地址。可以说它是000007fe`f9b40000。让我们将它保存到c:\ clr.dll。该命令现在变为如下:

!sos.SaveModule 000007fe`f9b40000 c:\clr.dll

现在检查模块的导出路径。 这将从实时调试会话以及完整(/ ma)转储开始。

我不确定动态装配。如果它们出现在lm列表中,那么它应该不是问题。如果没有,那么您将需要找到它加载到内存的位置并将其用作起始地址。