.NET Reflector 7.0 License 机制分析

.NET Reflector免费版只能升级到6.7.0.3. 可下载(http://reflector.red-gate.com/download.aspx?TreatAsUpdate=1)的最新版本为7.0. 运行时会要求Activate。


点击Active 按钮,弹出Activate 对话框

如果选择继续执行, 通过菜单也可以呼出Activate对话框

祭出WinDbg, F6, Attached到Reflector的进程上.
根据WinDbg的输出,得知Reflector是基于.NET2.0的,
*** wait with pending attach
WARNING: Inaccessible path: ‘d:\mypdb’
Symbol search path is: srv*d:\MsSymbols*http://msdl.microsoft.com/download/symbols;
Executable search path is:
ModLoad: 00400000 00848000   D:\_Personal\_DevTools\Reflector7\Reflector.exe

ModLoad: 79e70000 7a400000   C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll

因此执行 .loadby sos mscorwks  加载当前.NET版本对应的sos , 如果debug .NET 4.0, 就要使用命令.load sos clr 来加载sos.!
执行!clrstack查看callstack, 不巧的是当前线程不是Managed Thread.
执行!thread 列出所有Manged线程
0:015> !threads
ThreadCount: 8
UnstartedThread: 0
BackgroundThread: 7
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                      PreEmptive   GC Alloc           Lock
       ID OSID ThreadOBJ    State     GC       Context       Domain                        Count     APT         Exception
   0    1 13dc 0015a2a8      6020 Enabled  09c3ae48:09c3c1b4 00164470            1        STA
   2    2 1548 0015d0f0      b220 Enabled  00000000:00000000 00164470      0       MTA       (Finalizer)
   4    3  e98 001e9bd0   880b220 Enabled  00000000:00000000 00164470   0       MTA       (Threadpool Completion Port)
   6    4 1f84 0021f638    80a220 Enabled  00000000:00000000 00164470     0      MTA       (Threadpool Completion Port)
   8    5 1718 002223f8       220 Enabled  00000000:00000000 00164470        0       Ukn
  11    8 1870 095a8728    80a220 Enabled  00000000:00000000 00164470    0    MTA         (Threadpool Completion Port)
  13    7 1a4c 095a8340   200b220 Enabled  00000000:00000000 00164470   0   MTA
  14    6 179c 095a8b10   200b220 Enabled  00000000:00000000 00164470   0    MTA

执行~0s切换到0号线程
执行!clrstack
0:000> !clrstack
OS Thread Id: 0×1098 (0)
ESP       EIP    
0012e98c 7c90e514 [InlinedCallFrame: 0012e98c] System.Windows.Forms.UnsafeNativeMethods.WaitMessage()
0012e988 7b1d8ea8 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)
0012ea24 7b1d8997 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
0012ea78 7b1d87e1 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
0012eaa8 7b6ede2b System.Windows.Forms.Application.RunDialog(System.Windows.Forms.Form)
0012eabc 7b7225ab System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window)
0012eb48 05ddd3d4 RedGate.Licensing.Client.Licence.’œ (System.Windows.Forms.IWin32Window, Œ.™, System.Object, System.Drawing.Icon)
0012ec00 05ddd167 RedGate.Licensing.Client.Licence.™(System.Windows.Forms.IWin32Window, System.Drawing.Icon)
0012ec74 05ddd040 €..œ–(System.Windows.Forms.IWin32Window)
0012ecc8 05ddcf73 ‘.ž†.Activate()
0012ed04 05ddce17 ‘.ž†.Execute(System.String)
0012edac 05ddc906 ‘.–.Execute(System.String)
0012ee08 05ddc7e6 ‘.ž†.Š(System.Object, System.EventArgs)
0012ee78 01263ab3 DynamicClass.(System.Object, System.Object, System.EventArgs)
0012ee8c 05ddc681 ‘.+..OnClick(System.EventArgs)
0012eec4 05ddc5f2 ‘.+..PerformClick()
0012eef8 05ddc55d ‘.+.+..OnClick(System.EventArgs)
0012ef38 7b88f8f9 System.Windows.Forms.MenuItem+MenuItemData.Execute()
0012ef44 7b7933a8 System.Windows.Forms.Command.Invoke()
0012ef50 7ba195df System.Windows.Forms.Command.DispatchID(Int32)
….

以上调用栈表明,点击Menu后,RedGate.Licensing.Client.Licence搞了一些事情,然后弹出了Activate Dialog.  我把目标所定在两个class上:
1. RedGate.Licensing.Client.Licence  这个class好像是用来管理License的
2. Activate Dialog  看看怎么能让Activate button可用,从而断到License严证的代码。

从RedGate.Licensing.Client.Licence开刀
0:000> !dumpheap -type RedGate.Licensing.Client.Licence
         Address               MT                                     Size
0000000005d0e9c8 000007ff00d33990      176    
0000000005d0ea78 000007ff00eb2da0       88    
0000000005d0f1c0 000007ff00eb4c18       40    
total 0 objects
Statistics:
              MT    Count    TotalSize Class Name
000007ff00eb4c18        1           40 System.Collections.Generic.List`1[[RedGate.Licensing.Client.Licence+.–, Reflector]]
000007ff00eb2da0        1           88 RedGate.Licensing.Client.Licence+.–
000007ff00d33990        1          176 RedGate.Licensing.Client.Licence
Total 3 objects

从上面的执行结果得出RedGate.Licensing.Client.Licence的Method Table 000007ff00d33990
进一步得到它的地址
0:000> !dumpheap -mt 000007ff00d33990
         Address               MT     Size
000000000592a640 000007ff00d53990      176    
total 0 objects
Statistics:
              MT    Count    TotalSize Class Name
000007ff00d53990        1          176 RedGate.Licensing.Client.Licence
Total 1 objects

再来看看 RedGate.Licensing.Client.Licence的内容:
0:000> !do 000000000592a640
Name:        RedGate.Licensing.Client.Licence
MethodTable: 000007ff00d53990
EEClass:     000007ff00d3d718
Size:        176(0xb0) bytes
File:        D:\_HHuang\_DevTools\Reflector7\Reflector.exe
Fields:
              MT    Field   Offset                 Type VT     Attr            Value Name
000007fee84b9748  40002a7       88      System.DateTime  1 instance 000000000592a6c8
000007fee84b9748  40002a8       90      System.DateTime  1 instance 000000000592a6d0
000007fee84b9748  40002a9       98      System.DateTime  1 instance 000000000592a6d8
000007ff00d536d8  40002aa       70         System.Int32  1 instance                1
000007fee8496970  40002ab        8        System.String  0 instance 000000000592af18
000007fee8496970  40002ac       10        System.String  0 instance 0000000005a64c98
000007fee849c858  40002ad       74         System.Int32  1 instance               24 
000007fee8496970  40002ae       18        System.String  0 instance 000000000592ae80
000007fee8496970  40002af       20        System.String  0 instance 000000000592aeb0
000007fee84b9748  40002b0       a0      System.DateTime  1 instance 000000000592a6e0
000007fee8496970  40002b1       28        System.String  0 instance 0000000002631420
000007fee8496970  40002b2       30        System.String  0 instance 0000000000000000
000007fee849d688  40002b3       84       System.Boolean  1 instance                0
000007fee849d688  40002b4       85       System.Boolean  1 instance                0
000007fee8496970  40002b5       38        System.String  0 instance 000000000591cee0
000007fee849c858  40002b6       78         System.Int32  1 instance                7
000007fee849c858  40002b7       7c         System.Int32  1 instance                0
000007fee8496970  40002b8       40        System.String  0 instance 0000000000000000
000007fee8496970  40002b9       48        System.String  0 instance 0000000000000000
000007ff00d53830  40002ba       80         System.Int32  1 instance                0
000007fee8496970  40002bb       50        System.String  0 instance 00000000059334a0
000007fee8496970  40002bc       58        System.String  0 instance 0000000002631420
000007fee849d688  40002bd       86       System.Boolean  1 instance                0
000007ff00ed2da0  40002be       60 …ent.Licence+.–  0 instance 000000000592a6f0
000007fee3e7d488  40002bf       68 …ent.SqlConnection  0 instance 0000000000000000
000007ff001a70c8  40002a6      478                ˆœ.ˆ  0   static 000000000591e498
System.DateTime无非是用来看是否过期,我只关心字符串,用!do 一个一个看:
000000000592af18   C:\Users\HHuang\AppData\Local\Red Gate\Licenses
0000000005a64c98   5410d7dc-1bec-4a91-94b5-4e63ee1a9e4c
000000000592ae80   evaluation
000000000592aeb0   {17c157ee-b2d1-4bd5-aeae-870f28654c42}
0000000002631420   空串
000000000591cee0    .NET Reflector
00000000059334a0   92A2-B24D-A33C-6B93
0000000002631420   空串
由此看见,RedGate.Licensing.Client.Licence只是一个数据包,并不包含验证机制。
尝试把5410d7dc-1bec-4a91-94b5-4e63ee1a9e4c和92A2-B24D-A33C-6B93 输入到Activate 对话框,没有任何反应
HKEY_CURRENT_USER\Software\Thingummy Software\Licensing\.NET Reflector\7.0下的键值{17c157ee-b2d1-4bd5-aeae-870f28654c42} 记录了Reflector 的License信息,Reflector第一次执行时会生成这个键值,如果Reflector过了14天的试用期,就删除这个键(注意,不是仅仅删除它的值),Reflector就不再提示过期

如果用C#代码调用
RedGate.Licensing.Client.Licence c = new RedGate.Licensing.Client.Licence();
c.get_SerialNumber();  返回null
c.ToString();  返回
         Activated : False
         DaysLeftInTrial : 0
         Edition : evaluation
         SerialNumber :
         TrialStatus :
         License Mode : LOCAL_MACHINE
下面把注意力移到Activate Dialog上。程序会读取Activate Dialog上TextBox的值进行验证,因此对TextBox.get_Text()方法加断点。
执行!dumpheap -type TextBox得到TextBox的Method Table  000007fee6d19100 
执行!dumpmt -md MethodTable  列出TextBox上所有的方法,包括它们的MD
0:000> !dumpmt -md 000007fee6d19100      
EEClass:      000007fee6939738
Module:       000007fee6921000
Name:         System.Windows.Forms.TextBox
mdToken:      000000000200010c
File:         C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll
BaseSize:        0xe8
ComponentSize:   0×0
Slots in VTable: 387
Number of IFaces in IFaceMap: 14
————————————–
MethodDesc Table
           Entry                MethodDesc      JIT Name
000007fee6b8c470 000007fee6a2d530   PreJIT    Windows.Forms.TextBox.get_Text()
在TextBox.get_Text()上下断点:!bpmd -md 000007fee6a2d530  (对于.NET 上的程序而言bp GetWindowTextW 已经是老黄历了)
然后继续执行g
果然,每次向TextBox中输入,都会中断,调用栈为:
0:000> !clrstack
OS Thread Id: 0x1aa0 (0)
Child SP                            IP                                 Call Site
000000000012b698 000007fee6c6d7b0 System.Windows.Forms.TextBox.get_Text()
000000000012b6a0 000007ff010f540f ™ .™ .’š (System.Object, System.EventArgs)     
….
0:000> !ip2md 000007ff010f540f
MethodDesc:   000007ff01113ea0
Method Name:  ™ .™ .’š (System.Object, System.EventArgs)
Class:        000007ff01121468
MethodTable:  000007ff01113f50
mdToken:      0000000006000548
Module:       000007ff000530d8
IsJitted:     yes
CodeAddr:     000007ff010f52c0
反汇编这个函数
0:000> !u 000007ff01113ea0
可以得知这个函数的主要逻辑是(此处引用的代码为32位机代码):
07db8772 ff9064010000 call dword ptr <Unloaded_sspc.dll>+0×163 (00000164)[eax]
     调用Text.getText() , 得到SN

07db878c e88f919871 call mscorlib_ni+0×681920 (79741920) (System.String.ToUpper(), mdToken: 060001b0)
     把SN转成大写07db86ea e891919871 call mscorlib_ni+0×681880 (79741880) (System.String.Trim(), mdToken: 060001b6)
    Trim(SN)
07db86fb ff15b8077f05 call dword ptr [<Unloaded_sspc.dll>+0x57f07b7 (057f07b8)] (Œ .†–[1].š[1](System.String), mdToken: 06000486)
   调用函数( md=057f07b0 )对SN进行处理, 姑且称之为IsSNValid(string SN)

……
        // 重要, [ebp-24h]中记录SN是否合法
07db8714 8b55dc mov edx,dword ptr [ebp-24h]
07db8717 3909 cmp dword ptr [ecx],ecx
       // !do ecx 得到PictureBox
       //设置绿色对号PictrueBox是否可见,由此可以推断函数调用1用于判断SN是否合法07db8719 e8ca2e3973 call System_Windows_Forms_ni+0x17b5e8 (7b14b5e8) (System.Windows.Forms.Control.set_Visible(Boolean), mdToken: 06001455)
……
07db873f 837ddc00 cmp dword ptr [ebp-24h],0
      // 验证失败,跳入失败的分支
07db8743 7416 je <Unloaded_sspc.dll>+0x7db875a (07db875b)

函数IsSNValid(string SN)的逻辑是
如果SN=”I NEED MORE TIME”, 退出, 返回1, 也就是说”I NEED MORE TIME”算是一个有效的SN
否则
调用CheckSN(string SN)
07db8859 ff15c4077f05 call dword ptr [<Unloaded_l32.dll>+0x322dbdf (0322dbe0)] (Œ .†–.š(System.String), mdToken: 06000487) 04b393af 8945d0 mov dword ptr [ebp-30h],eax
04b393b2 0fb645d0 movzx eax,byte ptr [ebp-30h]
//把比较结果存入[ebp-24h]
04b393b6 8945dc mov dword ptr [ebp-24h],eax
//退出
04b393ba eb52 jmp <Unloaded_l32.dll>+0x4b3940d (04b3940e)

CheckSN(string SN)的逻辑是
把SN转大写,Trim,
if(SN 匹配 ^[A-Z]{2}-[0-9A-Z]{1}-[0-9A-Z]{1}-\d{5}-[0-9A-F]{4}$)
{
       //捏造SN :  HH-A-0-12345-abcd  
      调用string.Substring截取前4个部分,SN变为HH-A-0-12345
      调用函数CreateMegicNumber(短SN)生成一个随机数,如00007ed9, 再把这个数字format({0:X4} )成string
      然后return SN.EndWith(“7ed9”)
      为此捏造SN  HH-A-0-12345-7ED9
}
else
{
     if(SN 匹配 ^\d{3}-\d{3}-\d{6}-[0-9A-F]{4}$)
     {
              捏造SN:123-123-111111-abcd
    }
    else
    {
           调用函数CheckSNWithRegex(string SN)判断SN是否合法
          {
             此函数算出一个字符集, 2346789ABCDEFGHJKMNPRTWXYZ
             构造正则表达式^A3[2346789ABCDEFGHJKMNPRTWXYZ]{2}(-([2346789ABCDEFGHJKMNPRTWXYZ]{4})){5}$
             为此捏造SN A3HH-ABCD-ABCD-ABCD-ABCD-ABCD
           }

          调用函数CheckChars(string SN, char c1, char c2)判断SN是否合法
          {
                  检查SN的第2个和第三个字符是否合乎要求
                  把上面的SN修改为 A3KE-ABCD-ABCD-ABCD-ABCD-ABCD
          }
       }
}

目前的成果
1. 删除HKEY_CURRENT_USER\Software\Thingummy Software\Licensing\.NET Reflector\7.0下的键值{17c157ee-b2d1-4bd5-aeae-870f28654c42},重新获得14天的试用期
2. 输入序列号”I NEED MORE TIME”激活Reflector,每次输入都重新获得14天的使用期
3. 得到两个SN


但是点击Activate按钮, 出错

要到http://www.red-gate.com/webactivation/activate进行手动验证. Activation Server上的逻辑就无从知晓了.
Reflector 7.0 的License机制暂时分析到这里.

 

来自:.NET Reflector 7.0 License 机制分析   http://blog.adminzc.info/post-388.html

你可能感兴趣的:(reflect)