zoukankan      html  css  js  c++  java
  • [转].NET Reflector 7.0 License 机制分析

    .NET Reflector免费版只能升级到6.7.0.3. 可下载(http://reflector.red-gate.com/download.aspx?TreatAsUpdate=1)的最新版本为7.0. 运行时会要求Activate。
    image
    image
    点击Active 按钮,弹出Activate 对话框
    image
    如果选择继续执行, 通过菜单也可以呼出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就不再提示过期
    image

    如果用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

    image
    但是点击Activate按钮, 出错
    image
    要到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

  • 相关阅读:
    C/C++网络编程2——socket函数
    C/C++网络编程1——linux下实现
    nginx_2_nginx进程模型
    nginx_1_初始nginx
    C++11并发编程4------线程间共享数据
    C++11并发编程3------线程传参
    C++11并发编程2------线程管理
    C++11并发编程1------并发介绍
    打造自己的开发环境
    gcc/g++/make/cmake/makefile/cmakelists的恩恩怨怨
  • 原文地址:https://www.cnblogs.com/tukzer/p/2370346.html
Copyright © 2011-2022 走看看