Windbg隐藏在运行时对象里的秘密

.NET程序包括运行时对象均是自描述的,我们可以从PE文件,以及在Windbg调试时可以得到很多的辅助调试信息,关于运行时对象,1.1版本有一些参考资料。.NET 4.0相关的资料几乎没有找到,如果谁有能发站内的信件告诉我,不胜感激。想了很久,还是把自己最近的调查写出来,留作纪念,待以后补充。错误的地方以后会修改。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace WindbugDemo
 7 {
 8     public class Person
 9     {
10         //认为BMI和21偏差最小的为最健康的
11         private const double BmiHelthConst = 21f;
12 
13         public string Name { get; set; }
14         public int Age { get; set; }
15         public double Height { get; set; }
16         public double Weight { get; set; }
17         public double BmiVariance { get;set;}
18 
19         public Person(string name,int age,double height,double weight)
20         {
21             this.Name = name;
22             this.Age = age;
23             this.Height = height;
24             this.Weight = weight;
25             this.GetBmiVariance();
26         }
27 
28         public void GetBmiVariance()
29         {
30             double bmi = Math.Round(Weight / Math.Pow(Height, 2),2);
31             BmiVariance = Math.Abs(bmi - BmiHelthConst);      
32         }
33     }
34 
35     class Health
36     {
37         [STAThread]
38         static void Main(string[] args)
39         {
40             Person person = new Person ("James",35,1.70,70);
41             string text = string.Format("Name:{0}  Age:{1}  Height:{2}  Weight:{3}  BMI Variance:{4}",
42             person.Name,person.Age, person.Height, person.Weight, person.BmiVariance);
43             System.Console.WriteLine(text);
44             Console.ReadKey();
45             /*
46             Name:Tony  Age:25  Height:1.65  Weight:60  BMI Variance:1.04
47              */
48         }
49     }
50 
51 }

还是前面的程序,略做改造。Windbg启动EXE程序,在41行打上断点。运行!clrstack命令。

0:000> !clrstack -a
OS Thread Id: 0xb70 (0)
Child SP       IP Call Site
001dee3c 005d00fc WindbugDemo.Health.Main(System.String[]) [d:\source\02Health\Health.cs @ 41]
    PARAMETERS:
        args (0x001deebc) = 0x01d72180
    LOCALS:
        0x001dee7c = 0x01d7222c
        0x001dee78 = 0x00000000
        0x001dee74 = 0x01d722ec

001df050 67902552 [GCFrame: 001df050] 
0:000> dd 0x01d7222c
01d7222c  005638e4 33333333 3ffb3333 00000000
01d7223c  40518000 5c28f5c0 4009c28f 01d72190
01d7224c  00000023 00000000 5d8341b8 00000000
01d7225c  00000000 5d83fe70 00000010 00000000
01d7226c  3ff00000 00000000 40240000 00000000
01d7227c  40590000 00000000 408f4000 00000000
01d7228c  40c38800 00000000 40f86a00 00000000
01d7229c  412e8480 00000000 416312d0 00000000
0:000> dd 005638e4 
005638e4  01000000 00000028 00020180 00000004
005638f4  5d8341b8 00562edc 00563920 0056130c
00563904  00000000 00000000 00563910 5d71952c
00563914  5d72ec30 5d72e860 5d72e2a0 00000080
00563924  00000000 00000000 00000000 00000000
00563934  00000000 00000000 00000000 00000000
00563944  00000000 00000000 00000000 00000000
00563954  00000000 00000000 00000000 00000000
0:000> !dumpmt -md 005638e4
EEClass:         0056130c
Module:          00562edc
Name:            WindbugDemo.Person
mdToken:         02000002
File:            D:\bin\Health.exe
BaseSize:        0x28
ComponentSize:   0x0
Slots in VTable: 16
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
   Entry MethodDe    JIT Name
5d71952c 5d43612c PreJIT System.Object.ToString()
5d72ec30 5d436134 PreJIT System.Object.Equals(System.Object)
5d72e860 5d436154 PreJIT System.Object.GetHashCode()
5d72e2a0 5d436168 PreJIT System.Object.Finalize()
0056c02d 00563848   NONE WindbugDemo.Person.get_Name()
005d0310 00563854    JIT WindbugDemo.Person.set_Name(System.String)
0056c035 00563860   NONE WindbugDemo.Person.get_Age()
005d0350 0056386c    JIT WindbugDemo.Person.set_Age(Int32)
005d0518 00563878    JIT WindbugDemo.Person.get_Height()
005d0388 00563884    JIT WindbugDemo.Person.set_Height(Double)
005d04d8 00563890    JIT WindbugDemo.Person.get_Weight()
005d03c0 0056389c    JIT WindbugDemo.Person.set_Weight(Double)
0056c04d 005638a8   NONE WindbugDemo.Person.get_BmiVariance()
005d0558 005638b4    JIT WindbugDemo.Person.set_BmiVariance(Double)
005d0288 005638c0    JIT WindbugDemo.Person..ctor(System.String, Int32, Double, Double)
005d03f8 005638cc    JIT WindbugDemo.Person.GetBmiVariance()0:000> !do 5d8341b8 
<Note: this object has an invalid CLASS field>
Invalid object
0:000> !dumpmodule 5d8341b8 
Fail to fill Module 5d8341b8
0:000> !dumpmt 5d8341b8 
EEClass:         5d4339a4
Module:          5d431000
Name:            System.Object
mdToken:         02000002
File:            C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 12
Number of IFaces in IFaceMap: 00:000> !dumpclass 0056130c
Class Name:      WindbugDemo.Person
mdToken:         02000002
File:            D:\bin\Health.exe
Parent Class:    5d4339a4
Module:          00562edc
Method Table:    005638e4
Vtable Slots:    4
Total Method Slots:  4
Class Attributes:    100001  
Transparency:        Critical
NumInstanceFields:   5
NumStaticFields:     0
      MT    Field   Offset                 Type VT     Attr    Value Name
5d833e18  4000002       1c        System.String  0 instance           <Name>k__BackingField
5d83560c  4000003       20         System.Int32  1 instance           <Age>k__BackingField
5d83fa00  4000004        4        System.Double  1 instance           <Height>k__BackingField
5d83fa00  4000005        c        System.Double  1 instance           <Weight>k__BackingField
5d83fa00  4000006       14        System.Double  1 instance           <BmiVariance>k__BackingField
0x01d7222c这个地址是Person对象,使用dd命令转储出来以后,第一个应该是指向改对象的类型句柄,再次使用dd命令进行转储。把上面标的五颜六色的地方,摘出来单独进行解析。
0:000> dd 005638e4 
005638e4  01000000 00000028 00020180 00000004
005638f4  5d8341b8 00562edc 00563920 0056130c
00563904  00000000 00000000 00563910 5d71952c
00563914  5d72ec30 5d72e860 5d72e2a0 00000080
00563924  00000000 00000000 00000000 00000000
00563934  00000000 00000000 00000000 00000000
00563944  00000000 00000000 00000000 00000000
00563954  00000000 00000000 00000000 00000000

1、01000000 应该是该对象的枚举值,表示为类。

 Windbg隐藏在运行时对象里的秘密

2、00000028应该是描述该对象的元数据所占的尺寸。

3、5d8341b8为父类的方法表。

4、00562edc 为该对象的Module。

5、0056130c为EEClass指针。

6、5d71952c 5d72ec30 5d72e860 5d72e2a0 为预JIT编译的四个方法的入口。

5d71952c 5d43612c PreJIT System.Object.ToString()
5d72ec30 5d436134 PreJIT System.Object.Equals(System.Object)
5d72e860 5d436154 PreJIT System.Object.GetHashCode()
5d72e2a0 5d436168 PreJIT System.Object.Finalize()

如果要做更详尽的解读的话,要详细看一下SSCLI源码,天书一样,看起来也很费劲,只能慢慢研究了。

参考资料:
1、.NET 高级调试
2、https://www.cnblogs.com/awpatp/archive/2009/11/11/1601397.html

Windbg隐藏在运行时对象里的秘密

上一篇:linux环境中使用aspose插件word转pdf 中文乱码解决方案


下一篇:前端表单验证常用的15个JS正则表达式