Is it possible to dump arbitrary (including dynamically created) assembly into a file from windbg?

mar*_*ark 6 .net debugging windbg

I have a dump of a .NET application which creates and loads too many dynamic assemblies. I would like to inspect what is inside one of these assemblies.

For that, I want to dump such an assembly into a file and open it in Reflector.

The problem - I have no idea how to do it.

So, my question is this - given a full memory dump, how do I dump an arbitrary assembly to a file, in such a way that the new file is a valid .NET module or assembly itself?

A simpler variation - how do I do it from a live debugging session?

I am using WinDBG with SOS and SOSEX.

EDIT 1

So, 3 years later I need it again. Here is the relevant output from !DumpDomain:

Assembly:           007f89a0 (Dynamic) []
ClassLoader:        00877998
SecurityDescriptor: 00879410
  Module Name
054d0010    Dynamic Module
Run Code Online (Sandbox Code Playgroud)

Starting with this information, how can I find the start and end of this assembly? Then I could use the .writemem command.

小智 6

测试代码 - 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
Run Code Online (Sandbox Code Playgroud)

不如reflector好看,但是可以看到类型和方法。


Don*_*ono 1

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

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

!sos.SaveModule 000007fe`f9b40000 c:\clr.dll
Run Code Online (Sandbox Code Playgroud)

现在检查模块的导出路径。这将在实时调试会话以及完整 (/ma) 转储中发挥作用。

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

  • `!lmv` 没有列出动态 .NET 程序集,这是这个问题的本质。 (2认同)