As a powerful development platform, Visual Studio has provided many debugging methods. However, these debugging methods are relatively stuck on the surface. They are nothing more than setting breakpoints, viewing variables, and calling the stack list. In some cases, we want to know more things, especially things hidden behind the scenes and at runtime, such as object running status and memory distribution, these relatively low-level knowledge can make us better understand. net CLR/JIT. Of course, not everyone needs to understand this knowledge. After all, compilation and advanced debugger are very troublesome to use.
SOS. dll is a debugging extension provided by Microsoft. It is called son of strike and can be used for debugging and hosting.Code. SOS. dll has very powerful functions, including common cracker memory shelling and so on. The purpose of this article is not to study how to crack, but to use SOS. DLL to help us learn some of. Net CLR/JIT knowledge. We do not plan to use professional-level windbg, but to load SOS. dll directly into.
1. Preparations
(1) Open vs2005 and add the location of the symbol file in the "Tools> Options> debugging> symbol" dialog box, such as "C: \ Program Files \ Microsoft Visual Studio 8 \ SDK \ V2.0 \ symbols ".
(2) create a leleapplication project and enter the test code. Namespace consoleapplication1
{
Class base
{
Public Virtual void test (){}
}
Class derived: Base
{
Public override void test (){}
}
Public class Program
{
Static void main (string [] ARGs)
{
Derived o = new derived ();
O. Test ();
(O as base). Test ();
Console. writeline ("press any key to exit ...");
Console. readkey (true );
Environment. Exit (0 );
}
}
}
(3) Open the Project Properties dialog box and select "enable unmanaged code debugging" on the "debug" page ".
(4) set a breakpoint in the "console. writeline (" press any key to exit... ");" line.
2. Operation demonstration
Press F5 to startProgramDebug. After the breakpoint is executed, open the "instant window" and enter ". Load SOS" to load the debugging extension.
Enter "! Help "to view all Debugging commands .! Help
PDB symbol for mscorwks. dll not loaded
-------------------------------------------------------------------------------
SOS is a debugger extension DLL designed to aid in the debugging of managedprograms. functions are listed by category, then roughly in order of importance. Shortcut names for popular functions are listed in parenthesis.
Type "! Help <functionname> "for detailed info on that function.
......
Next, let's take a look at how object o implements virtual method calls. (Variable O in main method in the code above)
(1) view the current stack information .! Clrstack-
PDB symbol for mscorwks. dll not loaded
OS thread ID: 0xfc8 (4040)
ESP EIP
0012f434 00f500bc consoleapplication1.program. Main (system. String [])
Parameters:
ARGs = 0x013f1c20
Locals:
<CLR Reg> = 0x013f1c74
0012f69c 79e79dd3 [gcframe: 0012f69c]
Objects in locals are our goals. (How do you see my msil series?Article, You must have a deeper understanding of this .)
(2) view the object information .! Dumpobj 0x013f1c74
Name: leleapplication1.derived
Methodtable: 00a73120
Eeclass: 00a714d4
Size: 12 (0xc) bytes
(Leleapplication1.exe)
Fields:
None
Find the memory address of methodtable. Next, let's see what is in this table.
(3) view the method table information .! Dumpmt-MD 00a73120
Eeclass: 00a714d4
Module: 00a72c3c
Name: leleapplication1.derived
Mdtoken: 02000004 (leleapplication1.exe)
Basesize: 0xc
Componentsize: 0x0
Number of ifaces in ifacemap: 0
Slots in vtable: 6
--------------------------------------
Methoddesc table
Entry methoddesc JIT name
79369154 791474f8 prejit system. Object. tostring ()
79367ec0 79147500 prejit system. Object. Equals (system. Object)
79367eb0 79147518 prejit system. Object. gethashcode ()
7935e4c0 79147520 prejit system. Object. Finalize ()
00a7c0b0 00a73110 JIT consoleapplication1.derived. Test ()
00a7c0c0 00a73118 JIT consoleapplication1.derived .. ctor ()
JIT inserts the Virtual Methods of the base class into the method table of the current type.
if we delete derived test (), the method table will look like the following. Eeclass: 00a714d0
module: 00a72c3c
name: leleapplication1.derived
mdtoken: 02000004 (consoleapplication1.exe)
basesize: 0xc
componentsize: 0x0
Number of ifaces in ifacemap: 0
slots in vtable: 6
------------------------------------
methoddesc table
entry methoddesc JIT name
79369154 791474f8 prejit system. object. tostring ()
79w.ec0 79147500 prejit system. object. equals (system. object)
79367eb0 79147518 prejit system. object. gethashcode ()
7935e4c0 79147520 prejit system. object. finalize ()
00a7c070 00a730a8 JIT consoleapplication1.base. test ()
00a7c0a0 00a73110 JIT consoleapplication1.derived .. ctor ()
The change to "Public new void test ()" is different. Eeclass: 00a714d4
Module: 00a72c3c
Name: leleapplication1.derived
Mdtoken: 02000004 (leleapplication1.exe)
Basesize: 0xc
Componentsize: 0x0
Number of ifaces in ifacemap: 0
Slots in vtable: 7
--------------------------------------
Methoddesc table
Entry methoddesc JIT name
79369154 791474f8 prejit system. Object. tostring ()
79367ec0 79147500 prejit system. Object. Equals (system. Object)
79367eb0 79147518 prejit system. Object. gethashcode ()
7935e4c0 79147520 prejit system. Object. Finalize ()
00a7c070 00a730a8 JIT consoleapplication1.base. Test ()
00a7c0b0 00a73110 JIT consoleapplication1.derived. Test ()
00a7c0c0 00a73118 JIT consoleapplication1.derived .. ctor ()
Comparing these differences can help us better understand polymorphism. Now, let's go back to the topic. Let's take a look at the calling code in main.
(4) view the Il code .! Name2ee leleapplication1.exe leleapplication1.program. Main
Module: 00a72c3c (consoleapplication1.exe)
Token: 0x06000009
Methoddesc: 00a73040
Name: leleapplication1.program. Main (system. String [])
Jitted Code address: 00f50070
This time we use "! Name2ee "to find the address of a type or method. Then use "! Dumpil "to see the Il code generated by the compiler .! Dumpil 00a73040
Iladdr = 004020c0
Il_0000: NOP
Il_0001: newobj leleapplication1.derived:. ctor
Il_0006: stloc.0
Il_0007: ldloc.0
Il_0008: callvirt consoleapplication1.base: Test
Il_000d: NOP
Il_000e: ldloc.0
Il_000f: callvirt consoleapplication1.base: Test
Il_0014: NOP
Il_0015: ldstr "press any key to exit ..."
Il_001a: Call system. Console: writeline
Il_001f: NOP
Il_0020: LDC. i4.1
Il_0021: Call system. Console: readkey
Il_0026: Pop
Il_0027: LDC. i4.0
Il_0028: Call system. Environment: Exit
Il_002d: NOP
Il_002e: Ret
Callvirt has already said this many times in the msil series.
In addition to the above, we can do more.
(5) view the object information .! Clrstack-
OS thread ID: 0xfc8 (4040)
ESP EIP
0012f434 00f500bc consoleapplication1.program. Main (system. String [])
Parameters:
ARGs = 0x013f1c20
Locals:
<CLR Reg> = 0x013f1c74
0012f69c 79e79dd3 [gcframe: 0012f69c]
! Dumpobj 0x013f1c74
Name: leleapplication1.derived
Methodtable: 00a73120
Eeclass: 00a714d4
Size: 12 (0xc) bytes
(Leleapplication1.exe)
Fields:
None
(6) view the managed heap status .! Eeheap
Loader heap:
--------------------------------------
System domain: 7a3c4690
Lowfrequencyheap: Size: 0x0 (0) bytes.
Highfrequencyheap: 00a62000 (8000: 1000) Size: 0x1000 (4096) bytes.
Stubheap: 00a6a000 (2000:1000) Size: 0x1000 (4096) bytes.
Virtual call stub heap:
Indcellheap: Size: 0x0 (0) bytes.
Lookupheap: Size: 0x0 (0) bytes.
Resolveheap: Size: 0x0 (0) bytes.
Dispatchheap: Size: 0x0 (0) bytes.
Cacheentryheap: Size: 0x0 (0) bytes.
Total size: 0x2000 (8192) bytes
--------------------------------------
Shared domain: 7a3c4330
Lowfrequencyheap: 00a90000 (2000:1000) Size: 0x1000 (4096) bytes.
Highfrequencyheap: Size: 0x0 (0) bytes.
Stubheap: Size: 0x0 (0) bytes.
Virtual call stub heap:
Indcellheap: Size: 0x0 (0) bytes.
Lookupheap: Size: 0x0 (0) bytes.
Resolveheap: Size: 0x0 (0) bytes.
Dispatchheap: Size: 0x0 (0) bytes.
Cacheentryheap: Size: 0x0 (0) bytes.
Total size: 0x1000 (4096) bytes
--------------------------------------
Domain 1: 14c2d8
Lowfrequencyheap: 00a70000 (2000:2000) Size: 0x2000 (8192) bytes.
Highfrequencyheap: 00a72000 (8000: 2000) Size: 0x2000 (8192) bytes.
Stubheap: Size: 0x0 (0) bytes.
Virtual call stub heap:
Indcellheap: Size: 0x0 (0) bytes.
Lookupheap: Size: 0x0 (0) bytes.
Resolveheap: Size: 0x0 (0) bytes.
Dispatchheap: Size: 0x0 (0) bytes.
Cacheentryheap: Size: 0x0 (0) bytes.
Total size: 0X4000 (16384) bytes
--------------------------------------
JIT code heap:
Loadercodeheap: 00f50000 () Size: 0x1000 (4096) bytes.
Total size: 0x1000 (4096) bytes
--------------------------------------
Module thunk heaps:
Module 790c2000: Size: 0x0 (0) bytes.
Module 00a72c3c: Size: 0x0 (0) bytes.
Total size: 0x0 (0) bytes
--------------------------------------
Module lookup table heaps:
Module 790c2000: Size: 0x0 (0) bytes.
Module 00a72c3c: Size: 0x0 (0) bytes.
Total size: 0x0 (0) bytes
--------------------------------------
Total loaderheap size: 0x8000 (32768) bytes
========================================================
Number of GC heaps: 1
Generation 0 starts at 0x013f1018
Generation 1 starts at 0x013f100c
Generation 2 starts at 0x013f1000
Ephemeral segment allocation context: None
Segment begin allocated size
001967a0 790d7f90 790f76fc 0x0001f76c (128876)
013f0000 013f1000 013f1ff4 0x00000ff4 (4084)
Large Object heap starts at 0x023f1000
Segment begin allocated size
023f0000 023f1000 023f32 50 0x00002250 (8784)
Total size 0x229b0 (141744)
------------------------------
GC heap size 0x229b0 (141744)
(7) view the application domain status.
Domain address can be used! Obtain the eeheap command .! Dumpdomain 14c2d8
--------------------------------------
Domain 1: 0014c2d8
Lowfrequencyheap: 0014c2fc
Highfrequencyheap: 0014c354
Stubheap: 0014c3ac
Stage: Open
Securitydescriptor: 0014d608
Name: learn.cui.exe
Assembly: 00192db0 [c: \ windows \ Assembly \ gac_32 \ mscorlib \ 2.0.0.0 _ b77a5c561934e089 \ mscorlib. dll]
Classloader: 00192e48
Securitydescriptor: 00193fc0
Module name
790c2000 c: \ windows \ Assembly \ gac_32 \ mscorlib \ 2.0.0.0 _ b77a5c561934e089 \ mscorlib. dll
Assembly: 0019e4c8 [consoleapplication1.exe]
Classloader: 0019e560
Securitydescriptor: 0019e3f8
Module name
00a72c3c consoleapplication1.exe
(8) view the thread pool status .! Threadpool
CPU utilization 0%
Worker thread: Total: 0 running: 0 idle: 0 maxlimit: 0 minlimit: 0
Work request in queue: 0
--------------------------------------
Number of Timers: 0
--------------------------------------
Completion port thread: Total: 0 free: 0 maxfree: 0 Currentlimit: 0 maxlimit: 1000 minlimit: 0
SOS. dll provides a large number of commands! The HELP command is used to view its usage methods. This article will not detail them one by one .! Help dumpclass
-------------------------------------------------------------------------------
! Dumpclass <eeclass address>
The eeclass is a data structure associated with an object type .! Dumpclass will show attributes, as well as list the fields of the type. The output is similar! Dumpobj. Although static field values will be displayed, non-static values won't because you need an instance of an object for that.
You can get an eeclass to look at from! Dumpmt ,! Dumpobj ,! Name2ee, and! Token2ee among others.