对于.net程序的调试,首选的工具还是建议使用Reflector或者dnspy,这两款工具结合了静态反编译和动态调试两项功能。如果样本没有进行混淆的话,可以使用这两款工具直接看到程序源码,对于动态调试具有极大的帮助。但是对于一些特殊的情况,必须恶意样本在内存中释放的一段.net程序,这并不是一个完整的.net文件,所有就无法用上述两款工具进行查看,这样的话,就可以使用windbg进行调试。
这里使用自己写的一段简单的.net代码进行演示说明:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FirstNet
{
class Program
{
static void Main(string[] args)
{
int a = 3;
int b = 4;
int c = a + b;
Console.WriteLine("a={0},b={1},c={2}", a, b, c);
Console.ReadLine();
}
}
}
首先使用windbg打开可执行文件,然后加载动态库sos.dll和clr.dll。需要注意的是,版本一定要对应,不然会出现The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll) failed, Win32 error 0n193这样的错误。
这两个动态库的路径一般为C:\Windows\Microsoft.NET\Framework\v4.0.30319。
如果是64位程序,使用64的windbg打开,就需要加载64位下的动态库。加载命令为:
.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll
.load C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
接着输入g运行程序,在程序断下来时加载调试扩展。
.loadby sos clr
然后,使用命令!CLRStack仅为托管代码提供真实的调用栈信息。
0:000> !CLRStack
OS Thread Id: 0x2e94 (0)
Child SP IP Call Site
006fee90 7763e7fc [PrestubMethodFrame: 006fee90] FirstNet.Program.Main(System.String[])
006ff068 7763e7fc [GCFrame: 006ff068]
命令Name2EE用于将给定的类名转换为Method Table或EEClass的地址,或将方法名称转换为MethodDesc。
0:000> !Name2EE FirstNet!FirstNet.Program.Main
Module: 008b3ffc
Assembly: FirstNet.exe
Token: 06000001
MethodDesc: 008b4d0c
Name: FirstNet.Program.Main(System.String[])
Not JITTED yet. Use !bpmd -md 008b4d0c to break on run.
找到MethodDesc的地址之后,就可以使用命令DumpIL显示IL指令
0:000> !DumpIL 008b4d0c
ilAddr = 00332050
IL_0000: nop
IL_0001: ldc.i4.3
IL_0002: stloc.0
IL_0003: ldc.i4.4
IL_0004: stloc.1
IL_0005: ldloc.0
IL_0006: ldloc.1
IL_0007: add
IL_0008: stloc.2
IL_0009: ldstr "a={0},b={1},c={2}"
IL_000e: ldloc.0
IL_000f: box System.Int32
IL_0014: ldloc.1
IL_0015: box System.Int32
IL_001a: ldloc.2
IL_001b: box System.Int32
IL_0020: call System.Console::WriteLine
IL_0025: nop
IL_0026: call System.Console::ReadLine
IL_002b: pop
IL_002c: ret
使用命令!u Address来查看对应的汇编代码
0:000> !u 01684d0c
Normal JIT generated code
FirstNet.Program.Main(System.String[])
Begin 03230448, size c6
H:\test\FirstNet\FirstNet\Program.cs @ 12:
03230448 55 push ebp
03230449 8bec mov ebp,esp
0323044b 57 push edi
0323044c 56 push esi
0323044d 83ec28 sub esp,28h
03230450 8bf1 mov esi,ecx
03230452 8d7dd0 lea edi,[ebp-30h]
03230455 b906000000 mov ecx,6
0323045a 33c0 xor eax,eax
0323045c f3ab rep stos dword ptr es:[edi]
0323045e 8bce mov ecx,esi
03230460 894df4 mov dword ptr [ebp-0Ch],ecx
03230463 833da842680100 cmp dword ptr ds:[16842A8h],0
0323046a 7405 je 03230471
0323046c e83f125a6f call clr!JIT_DbgIsJustMyCode (727d16b0)
03230471 33d2 xor edx,edx
03230473 8955ec mov dword ptr [ebp-14h],edx
03230476 33d2 xor edx,edx
03230478 8955f0 mov dword ptr [ebp-10h],edx
0323047b 33d2 xor edx,edx
0323047d 8955e8 mov dword ptr [ebp-18h],edx
03230480 90 nop
H:\test\FirstNet\FirstNet\Program.cs @ 13:
03230481 c745f003000000 mov dword ptr [ebp-10h],3
H:\test\FirstNet\FirstNet\Program.cs @ 14:
03230488 c745ec04000000 mov dword ptr [ebp-14h],4
H:\test\FirstNet\FirstNet\Program.cs @ 15:
0323048f 8b45f0 mov eax,dword ptr [ebp-10h]
03230492 0345ec add eax,dword ptr [ebp-14h]
03230495 8945e8 mov dword ptr [ebp-18h],eax
H:\test\FirstNet\FirstNet\Program.cs @ 16:
03230498 b9043c1570 mov ecx,offset mscorlib_ni+0x503c04 (70153c04) (MT: System.Int32)
0323049d e8522c44fe call 016730f4 (JitHelp: CORINFO_HELP_NEWSFAST)
032304a2 8945e4 mov dword ptr [ebp-1Ch],eax
032304a5 b9043c1570 mov ecx,offset mscorlib_ni+0x503c04 (70153c04) (MT: System.Int32)
032304aa e8452c44fe call 016730f4 (JitHelp: CORINFO_HELP_NEWSFAST)
032304af 8945e0 mov dword ptr [ebp-20h],eax
032304b2 b9043c1570 mov ecx,offset mscorlib_ni+0x503c04 (70153c04) (MT: System.Int32)
032304b7 e8382c44fe call 016730f4 (JitHelp: CORINFO_HELP_NEWSFAST)
032304bc 8945dc mov dword ptr [ebp-24h],eax
032304bf 8b05bc224b04 mov eax,dword ptr ds:[44B22BCh] ("a={0},b={1},c={2}")
032304c5 8945d4 mov dword ptr [ebp-2Ch],eax
032304c8 8b45e4 mov eax,dword ptr [ebp-1Ch]
032304cb 8b55f0 mov edx,dword ptr [ebp-10h]
032304ce 895004 mov dword ptr [eax+4],edx
032304d1 8b45e4 mov eax,dword ptr [ebp-1Ch]
032304d4 8945d0 mov dword ptr [ebp-30h],eax
032304d7 8b45e0 mov eax,dword ptr [ebp-20h]
032304da 8b55ec mov edx,dword ptr [ebp-14h]
032304dd 895004 mov dword ptr [eax+4],edx
032304e0 8b45e0 mov eax,dword ptr [ebp-20h]
032304e3 50 push eax
032304e4 8b45dc mov eax,dword ptr [ebp-24h]
032304e7 8b55e8 mov edx,dword ptr [ebp-18h]
032304ea 895004 mov dword ptr [eax+4],edx
032304ed 8b45dc mov eax,dword ptr [ebp-24h]
032304f0 50 push eax
032304f1 8b4dd4 mov ecx,dword ptr [ebp-2Ch]
032304f4 8b55d0 mov edx,dword ptr [ebp-30h]
032304f7 e8506ade6c call mscorlib_ni+0x3c6f4c (70016f4c) (System.Console.WriteLine(System.String, System.Object, System.Object, System.Object), mdToken: 06000b51)
032304fc 90 nop
H:\test\FirstNet\FirstNet\Program.cs @ 17:
032304fd e87a71566d call mscorlib_ni+0xb4767c (7079767c) (System.Console.ReadLine(), mdToken: 06000b40)
03230502 8945d8 mov dword ptr [ebp-28h],eax
03230505 90 nop
H:\test\FirstNet\FirstNet\Program.cs @ 18:
03230506 90 nop
03230507 8d65f8 lea esp,[ebp-8]
0323050a 5e pop esi
0323050b 5f pop edi
0323050c 5d pop ebp
0323050d c3 ret
其中的@ 17,@ 18表示源码中的行号。
这种情况下,就可以直接使用bp Address在目标地址出设置断点了。
sos扩展命令如下所示:
Object Inspection Examining code and stacks
----------------------------- -----------------------------
DumpObj (do) Threads
DumpArray (da) ThreadState
DumpStackObjects (dso) IP2MD
DumpHeap U
DumpVC DumpStack
GCRoot EEStack
ObjSize CLRStack
FinalizeQueue GCInfo
PrintException (pe) EHInfo
TraverseHeap BPMD
COMState
Examining CLR data structures Diagnostic Utilities
----------------------------- -----------------------------
DumpDomain VerifyHeap
EEHeap VerifyObj
Name2EE FindRoots
SyncBlk HeapStat
DumpMT GCWhere
DumpClass ListNearObj (lno)
DumpMD GCHandles
Token2EE GCHandleLeaks
EEVersion FinalizeQueue (fq)
DumpModule FindAppDomain
ThreadPool SaveModule
DumpAssembly ProcInfo
DumpSigElem StopOnException (soe)
DumpRuntimeTypes DumpLog
DumpSig VMMap
RCWCleanupList VMStat
DumpIL MinidumpMode
DumpRCW AnalyzeOOM (ao)
DumpCCW
Examining the GC history Other
----------------------------- -----------------------------
HistInit FAQ
HistRoot
HistObj
HistObjFind
HistClear
如果要查看某个命令的详细信息,可以使用!help <functionname>进行查看。