逸天阁

击长空、博千里,笑慑鬼魅,坦荡万象。四海皆是可有作为,宇内必有余之归宿。

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  27 随笔 :: 0 文章 :: 201 评论 :: 5 引用

公告

  于在开发DataSetBrowser时需要显示XML文本,所以在网上找了一下相关的XML编辑控件(只要能高亮显示语法就行)。结果发现该类控件少得可怜。我记得CodeLib里对C#和VB.NET代码的支持是通过SharpDevelop里的一个控件来实现。不过我不想用它。最后终于找到一款Smart Components出品的XmlEdit,界面如下:


  这个轻量级控件基本上已经达到了我的要求。不过这么个小控件居然都要收费,19.9美刀。。否则只能使用30天。。那就只好想办法把它Crack掉了。
  由于.NET程序集并不直接编译成二进制代码,而是IL中间语言。这种设计势必造成对代码的安全保护降低。网上也有不少讲解破解.NET程序集的方法。其中最简单的就是反射或反编译工具查看代码。相对应的保护措施就是通过混淆器,把类、方法、变量的名称打乱,给破译者造成困难。

  一、分析
  我们这里使用大众工具Reflector来看看这个XmlEdit.DLL。看到了什么?SmartComponents.Licence和SmartComponents.Xml两个命名空间以及下面的类。说明没有经过混淆器处理,那接下来就容易多了。通过分析代码,我们关注到以下三个类:ExpiringLicense、Globals、XmlEdit。
  bool ExpiringLicense.IsExpired { get; }
  这个方法用来检查是否过期,我们只要让它永远 return false; 那么就永不过期了:)
  bool Globals.HasValidLicense { get; set; }
  这个方法设置或返回是否拥有已验证的身份认证,让它永远 return true; 也可以永不过期^^
  我们再来看看 XmlEdit.FormatXML() 方法。其中检查了Globals.HasValidLicense,如果它已经被我们改成永远为 true,那么
public void FormatXML()
{
      
if (!Globals.HasValidLicense)
      
{
            
this.DisplayInvalidLicenseMessage();
      }
else{
            
      }

}
  再看一下 XmlEdit 的构造函数:
if (Registry.LocalMachine.OpenSubKey(Globals.RegKey) == null)
{
    Registry.LocalMachine.CreateSubKey(Globals.RegKey).SetValue(
"1", DateTime.Now.Ticks);
}

try
{
    LicenseManager.Validate(
typeof(XmlEdit));
    Globals.HasValidLicense 
= true;
}

catch (LicenseException exception1)
{
    Globals.HasValidLicense 
= false;
    
if (exception1.Message.Length > 0)
    
{
      MessageBox.Show(exception1.Message);
      
return;
    }

    MessageBox.Show(
"Please install a valid licence");
}

  在这里我们又发现了一些秘密,这个控件把当前时间保存在注册表的 Globals.RegKey,也就是 LOCAL_MECHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SCD里。这样我们就有了一个不改变 XmlEdit.DLL 而一直使用下去的办法,就是在你自己的程序里,手工改变注册表的这个值。代码如下:
Microsoft.Win32.Registry.LocalMachine.CreateSubKey
(
@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SCD").SetValue("1", DateTime.Now.Ticks);
  另外,也可以去掉 LicenseManager.Validate(typeof(XmlEdit)) 这句代码,或者整个 try{}catch{} 代码段。

  二、改写DLL
  从前面的分析来看,虽然破解的方法很多,但除了在自己的程序里改写注册表外,其余的都需要改变原来控件的代码。下面我们就来看看如何改写DLL。
  这里我们要用到的工具其实都是微软在.NET SDK里已经提供的,ILASM和ILDASM,前者用于编译IL代码,后者用于将程序集反编译到IL。这样我们就可以先将XmlEdit.DLL变成IL代码,然后改写IL代码,然后重新编译即可:)
  ILDASM 的语法很简单: ILDASM  程序集  /OUT=IL代码文件名
  ILDASM  XmlEdit.DLL   /OUT=XmlEdit.IL
  这样我们就得到了IL代码格式的XmlEdit库。然后可以直接修改这个IL文件。我们以最简单的一个破解方法举例,去掉 XmlEdit 构造函数里的 LicenseManager.Validate(typeof(XmlEdit))  这句代码。
  首先我们找到 XmlEdit 的构造函数。构造函数在IL里都是用.ctor()表示的。

  .class public auto ansi beforefieldinit XmlEdit 
         extends [System.Windows.Forms]System.Windows.Forms.RichTextBox
  {
    .custom instance void [System]System.ComponentModel.LicenseProviderAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 30 53 6D 61 72 74 43 6F 6D 70 6F 6E 65 6E   // ..0SmartComponen
                                                                                                                         74 73 2E 4C 69 63 65 6E 63 65 2E 45 6E 63 72 79   // ts.Licence.Encry
                                                                                                                         70 74 65 64 4C 69 63 65 6E 73 65 50 72 6F 76 69   // ptedLicenseProvi
                                                                                                                         64 65 72 00 00 )                                  // der..
    .field private bool mbolKeyPressHandled
    .field assembly bool mbolColorizeAndIndent
    .field assembly bool mbolInvalidated
    .field static assembly class [System]System.ComponentModel.Container components
    .field static assembly string mstrValidationErr
    .method public hidebysig specialname rtspecialname
            instance void  .ctor() cil managed
    {
      // 代码大小       165 (0xa5)
      .maxstack  4
      .locals init (class [System]System.ComponentModel.LicenseException V_0,
               valuetype [mscorlib]System.DateTime V_1)
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.0
      IL_0002:  stfld      bool SmartComponents.Xml.XmlEdit::mbolKeyPressHandled
      IL_0007:  ldarg.0
      IL_0008:  ldc.i4.1
      IL_0009:  stfld      bool SmartComponents.Xml.XmlEdit::mbolColorizeAndIndent
      IL_000e:  ldarg.0
      IL_000f:  ldc.i4.1
      IL_0010:  stfld      bool SmartComponents.Xml.XmlEdit::mbolInvalidated
      IL_0015:  ldarg.0
      IL_0016:  call       instance void [System.Windows.Forms]System.Windows.Forms.RichTextBox::.ctor()
      IL_001b:  ldarg.0
      IL_001c:  call       instance void SmartComponents.Xml.XmlEdit::InitializeComponent()
      IL_0021:  ldsfld     class [mscorlib]Microsoft.Win32.RegistryKey [mscorlib]Microsoft.Win32.Registry::LocalMachine
      IL_0026:  call       string SmartComponents.Xml.Globals::get_RegKey()
      IL_002b:  callvirt   instance class [mscorlib]Microsoft.Win32.RegistryKey [mscorlib]Microsoft.Win32.RegistryKey::OpenSubKey(string)
      IL_0030:  brtrue.s   IL_005d

      IL_0032:  ldsfld     class [mscorlib]Microsoft.Win32.RegistryKey [mscorlib]Microsoft.Win32.Registry::LocalMachine
      IL_0037:  call       string SmartComponents.Xml.Globals::get_RegKey()
      IL_003c:  callvirt   instance class [mscorlib]Microsoft.Win32.RegistryKey [mscorlib]Microsoft.Win32.RegistryKey::CreateSubKey(string)
      IL_0041:  ldstr      "1"
      IL_0046:  call       valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()
      IL_004b:  stloc.1
      IL_004c:  ldloca.s   V_1
      IL_004e:  call       instance int64 [mscorlib]System.DateTime::get_Ticks()
      IL_0053:  box        [mscorlib]System.Int64
      IL_0058:  callvirt   instance void [mscorlib]Microsoft.Win32.RegistryKey::SetValue(string,
                                                                                         object)
      .try
      {
        IL_005d:  ldtoken    SmartComponents.Xml.XmlEdit
        IL_0062:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
        IL_0067:  call       void [System]System.ComponentModel.LicenseManager::Validate(class [mscorlib]System.Type)
        IL_006c:  ldc.i4.1
        IL_006d:  call       void SmartComponents.Xml.Globals::set_HasValidLicense(bool)
        IL_0072:  leave.s    IL_00a4

      }  // end .try


  我们把这句话删除即可。
  IL_0067:  call       void [System]System.ComponentModel.LicenseManager::Validate(class [mscorlib]System.Type)
  如果你对IL语言很熟的话,你甚至完全可以改变原先代码的逻辑结构。比如我们前面说的让 Globals.HasValidLicense 永远返回 true。只要在IL文件里找到这个方法的定义,然后改一下就可以了。如果你对IL语言不是很熟,这里还有个小技巧,就是自己写一个 bool TestProperty { get { return true; } },然后看看它的IL代码是什么,全部复制过来就可以了:)

  最后我们把IL文件重新产生DLL。ILASM的语法是: ILASM  IL文件名 /OUT=程序集名称
  ILASM  XmlEdit.IL  /OUT=XmlEdit.DLL
  运行这个命令看看,应该会出现一个错误才对,说无法为强名称签名。

  原来这个 XmlEdit.DLL 还使用了强名称(StrongNamed)。如果没有 DLL 的发布者所拥有的密钥,是无法对IL进行再编译的。但强名称真的能保护我们的代码吗?不是的!它也很容易破解,或者说,去掉强名称。
  我们来看一下IL文件的头部:
.assembly XmlEdit
{
  .custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 1B 53 6D 61 72 74 43 6F 6D 70 6F 6E 65 6E   // ...SmartComponen
                                                                                              74 73 2E 58 6D 6C 2E 58 6D 6C 45 64 69 74 00 00 ) // ts.Xml.XmlEdit..
  .custom instance void [mscorlib]System.Reflection.AssemblyKeyFileAttribute::.ctor(string) = ( 01 00 19 2E 2E 5C 2E 2E 5C 2E 2E 5C 43 6F 6D 6D   // .....\..\..\Comm
                                                                                                6F 6E 5C 73 67 4B 65 79 2E 73 6E 6B 00 00 )       // on\sgKey.snk..
  .custom instance void [mscorlib]System.Reflection.AssemblyDelaySignAttribute::.ctor(bool) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyKeyNameAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 07 58 6D 6C 45 64 69 74 00 00 )             // ...XmlEdit..
  .custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 10 53 6D 61 72 74 20 43 6F 6D 70 6F 6E 65   // ...Smart Compone
                                                                                                6E 74 73 00 00 )                                  // nts..
  .custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 )
  .custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 30 45 64 69 74 2C 20 73 79 6E 74 61 78 20   // ..0Edit, syntax
                                                                                                    68 69 67 68 6C 69 67 68 74 69 6E 67 20 61 6E 64   // highlighting and
                                                                                                    20 69 6E 64 65 6E 74 20 58 6D 6C 20 69 6E 20 2E   //  indent Xml in .
                                                                                                    4E 45 54 00 00 )                                  // NET.. 
 .publickey = (00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00   // .$..............
                00 24 00 00 52 53 41 31 00 04 00 00 01 00 01 00   // .$..RSA1........
                AF 21 9E 12 EE 56 09 80 F5 1A 6D 10 D4 AB EF BA   // .!...V....m.....
                1F A7 C0 61 5E 99 2A FF EC F0 28 8A 89 D6 4A 88   // ...a^.*...(...J.
                56 76 D7 18 D6 5A BE A5 4B 5C 29 29 3B 3D 9C B8   // Vv...Z..K\));=..
                74 F4 5F E2 E4 E0 B6 24 BD 6B EB 6E 89 C0 3E 7E   // t._....$.k.n..>~
                DB C5 4A EB B1 E6 9D E0 67 D4 08 C8 6E CC 54 5A   // ..J.....g...n.TZ
                03 31 F0 12 5D A5 E9 12 74 AD AE 50 94 D7 D4 A2   // .1..]...t..P....
                0D 68 05 31 0C 3C FA 9E 0D 4D 47 4B C0 6D 89 91   // .h.1.<...MGK.m..
                0F 8C 72 F2 D2 6A 0C FC E1 4C B6 D1 7D E6 8B E4 ) // ..r..j...L..}...

  .hash algorithm 0x00008004 
  .ver 1:0:0:1
}

  在这里我们可以看到这个程序集的所有描述信息,比如Product、Company等等,甚至可以随意修改。更关键的是我们看到了.publicKey,这就是强名称的公钥。我们把这一段全部删掉。重新用ILASM编译,OK,PASS!

  以下是本文的相关下载:
  XmlEdit 原版安装程序
  XmlEdit.DLL 原版
  XmlEdit.DLL 破解版

  BTW: SourceForge上也有一个不错的开源的并基于.NET的XML编辑器:DINAMIC XML Editor
posted on 2005-01-28 13:03 逸天 阅读(1739) 评论(10) 编辑 收藏