随着微软在.NET 3.5 SP1中正式推出Entity Framework,很多数据访问提供者开始支持这一新框架。本文涉及到的 Devart MyDirect.NET 就是目前MySql数据库领域支持EF的数据访问组件(MySql Connector据说要等本月底才推出支持EF的新版本)。MyDirect.NET对EF提供了很好的支持,不过免费版只能试用1个月。以下从技术角度阐述如何绕开其验证,仅供学习研究之用。

1、寻找验证相关的入口函数:

    当到期时,异常信息和调用堆栈如下:
    ----> CoreLab.MySql.MySqlException : Sorry, your trial period has expired.
    --MySqlException
         at CoreLab.MySql.MySqlConnection.Open() 

    在打开MySqlConnection出错,用Reflector分析CoreLab.MySql.dll看一下代码:


u u = license as u;
if ((u != null&& (u.b() != null))
{
    
throw new MySqlException(-1, u.b());
}
绕开 CoreLab.MySql 验证绕开 CoreLab.MySql 验证


可以看到,ac这个类实现LicenseProvider用于产生License,而u这个类继承License对象,同时保存更具体的认证信息。
由于混淆过,我们无从知道u这个类每个字段的含义(a,b,c,d,e,f),这个时候我们需要人为执行一下GetLicense,看里面到底包含什么数据:

(LicenseProvider);
Assembly coreLabMySql = typeof(CoreLab.MySql.MySqlConnection).Assembly;

Type t 
= coreLabMySql.GetType("CoreLab.Common.ac");
Type u 
= coreLabMySql.GetType("CoreLab.Common.u");

// 创建ac对象
var aMethod = t.GetMethod("a", BindingFlags.Static | BindingFlags.Public);
var ac 
= aMethod.Invoke(nullnew object[] { });

// 模拟调用GetLicense
MySqlConnection conn = new MySqlConnection();
var getLicense 
= t.GetMethod("GetLicense");
var license 
= getLicense.Invoke(ac, new object[] { LicenseManager.CurrentContext, typeof(MySqlConnection), conn, false });

// 查看返回的license
var uLicense = Convert.ChangeType(license, u);


调试的时候我们可以看到,u.a包含了LicenseString, u.c则包含了认证失败的错误信息,u.e=3,这个貌似是返回码。
我们把系统时间调前,看一下未到期的时候,产生的license是什么样子:
u.a=LicenseString, u.c=null, u.e=0

2、产生可以使用的License

 MyLicenseProvider : LicenseProvider
{
    public override License GetLicense(LicenseContext context, Type type, object instance, bool allowExceptions)
    {
        Assembly coreLabMySql 
= typeof(CoreLab.MySql.MySqlConnection).GetType().Assembly;
        Type uType 
= coreLabMySql.GetType("CoreLab.Common.u");
        
object u = Activator.CreateInstance(uType, "Here is license string"nullfalse0null);
        
return u as License;
    }
}


自己运行一下,OK,可以产生一个正常的license

3、修改DLL
     首先,将上述MyLicenseProvider编译成一个DLL,我们需要得到上述代码的IL:
     ilasm MyLicenseProvider.dll /out=MyLicenseProvider.il
     找到 GetLicense 方法:


.locals init ([0class [mscorlib]System.Reflection.Assembly coreLabMySql,
       [
1class [mscorlib]System.Type uType,
       [
2object u,
       [
3class [System]System.ComponentModel.License CS$1$0000,
       [
4object[] CS$0$0001)
IL_0000:  nop
IL_0001:  ldarg.
0
IL_0002:  call       instance 
class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_0007:  callvirt   instance 
class [mscorlib]System.Reflection.Assembly [mscorlib]System.Type::get_Assembly()
IL_000c:  stloc.
0
IL_000d:  ldloc.
0
IL_000e:  ldstr      
"CoreLab.Common.u"
IL_0013:  callvirt   instance 
class [mscorlib]System.Type [mscorlib]System.Reflection.Assembly::GetType(string)
IL_0018:  stloc.
1
IL_0019:  ldloc.
1
IL_001a:  ldc.i4.
5
IL_001b:  newarr     [mscorlib]System.Object
IL_0020:  stloc.s    CS$
0$0001
IL_0022:  ldloc.s    CS$
0$0001
IL_0024:  ldc.i4.
0
IL_0025:  ldstr      
"here is license string"
+ "k0WXphh/g4KEcX"
IL_002a:  stelem.
ref
IL_002b:  ldloc.s    CS$
0$0001
IL_002d:  ldc.i4.
2
IL_002e:  ldc.i4.
0
IL_002f:  box        [mscorlib]System.Boolean
IL_0034:  stelem.
ref
IL_0035:  ldloc.s    CS$
0$0001
IL_0037:  ldc.i4.
3
IL_0038:  ldc.i4.
0
IL_0039:  box        [mscorlib]System.Int32
IL_003e:  stelem.
ref
IL_003f:  ldloc.s    CS$
0$0001
IL_0041:  call       
object [mscorlib]System.Activator::CreateInstance(class [mscorlib]System.Type,
                                     
object[])
IL_0046:  stloc.
2
IL_0047:  ldloc.
2
IL_0048:  isinst     [System]System.ComponentModel.License
IL_004d:  stloc.
3
IL_004e:  br.s       IL_0050

IL_0050:  ldloc.
3
IL_0051:  ret


接下来我们要反汇编 CoreLab.MySql.dll
运行 ildasm CoreLab.MySql.dll /out=source.il
这时出现提示信息 "Protected Module",无法反汇编。这是因为这个动态库增加了SuppressIldasmAttribute属性,从而ildasm不允许反汇编。我们可以很容易制造一个hack过的ildasm.exe版本,方法如下:
用二进制编辑器(如WinHex)打开C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\ildasm.exe
查找SuppressIldasmAttribute,将其修改为任意字符串,保存。

现在重新执行ildasm CoreLab.MySql.dll /out=source.il,得到CoreLab.MySql的il代码,查找以下代码:

 [System]System.ComponentModel.License 
          a(class [System]System.ComponentModel.LicenseContext A_0,
            
class [mscorlib]System.Type A_1,
            
object A_2,
            
bool A_3) cil managed

用我们之前得到的MyLicenseProvider里面的il代码替换a()方法,注意保留第一行的.override [System]System.ComponentModel.LicenseProvider::GetLicense

我们在重新编译il之前,还有一些工作要做,其中最重要的就是产生强名称签名。没有强名称签名,这个修改过的dll是无法工作的。

4、产生和修改强名称
    首先产生一对key:
    sn -k key.snk
    然后从中提取公钥
    sn -p key.snk public.key
    然后显示PublicKeyToken
    sn -t public.key
    这个时候会显示Public key token is a603cb3085449c2c
    这个public key token要记下来,我们下面要用到

    这里需要说明一下CoreLab.MySql.dll和CoreLab.MySql.Entity.dll的关系。
    从名称上可以看出,CoreLab.MySql.Entity.dll用于支持Entity Framework,所以其必然会引用强名称版本的CoreLab.MySql.dll,通过Reflector查看Reference可以验证我们的猜想。按照我们的思路,修改CoreLab.MySql.dll的验证部分代码,然后用我们产生的新的key去签名,为了支持EF,有必要同时产生一个配套的修改版CoreLab.MySql.Entity.dll。

    回头看CoreLab.MySql.dll,我们使用EF也好,使用ADO.NET也好,其Data Provider都是指向CoreLab.MySql。通过反射可知,这些功能都是由 CoreLab.MySql.MySqlDirectFactory工厂来支持的,这个类实现了接口DbProviderFactory和IServiceProvider,前者用于支持ADO.NET Data Provider,后者用于支持Entity Framework。我们看到MySqlDirectFactory里有如下方法签名:private object a(Type A_0); 这个方法便实现了IServiceProvider.GetService(Type serviceType)方法。在它的实现里,可以看到如下代码:
) : a.GetType();
    if (type == null)
    {
        Assembly assembly 
= Assembly.Load("CoreLab.MySql.Entity, Version=4.85.35.0, Culture=neutral, PublicKeyToken=09af7300eec23701");
        
if (assembly != null)
        {
            type 
= assembly.GetType("CoreLab.MySql.Entity.MySqlEntityProviderServices");
        }
    }


把这里的PublicKeyToken=09af7300eec23701替换成我们刚才自己产生的KeyToken, a603cb3085449c2c。

好了,现在可以重新编译 CoreLab.MySql.dll 了,运行以下命令:
ilasm source.il /dll /key=key.snk /out=CoreLab.MySql.dll

接下来我们修改CoreLab.MySql.Entity.dll对CoreLab.MySql.dll的引用。
  1) 反汇编IL
   ildasm CoreLab.MySql.Entity.dll /out=entity_source.il
  2) 查找 .assembly extern CoreLab.MySql
   将publickeytoken改成上面产生的新key,每个字节用空格隔开
  3) 重新编译
   ilasm entity_source.il /dll /key=key.snk /out=CoreLab.MySql.Entity.dll

对DLL和强名称的修改完成后,我们可以重新注册这些DLL并且使用了。

5、注册GAC
     gacutil /i CoreLab.MySql.dll
     gacutil /i CoreLab.MySql.Entity.dll
     如果打开C:\Windows\Assembly,我们现在应该可以看到两个版本的DLL,一个是原始版,一个是修改版

6、最后一步,修改machine.config使用修改版Data Provider.
    编辑 C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config
    找到以下这一段配置:
      <add name="MyDirect .NET" invariant="CoreLab.MySql" description="CoreLab MyDirect .NET"
        type="CoreLab.MySql.MySqlDirectFactory, CoreLab.MySql, Version=4.85.35.0, Culture=neutral, PublicKeyToken=09af7300eec23701" />
   将PublicKeyToken改成我们的key

大功告成~!

相关文章:

  • 2021-07-16
  • 2021-12-21
  • 2022-12-23
  • 2021-10-29
  • 2021-04-19
  • 2022-12-23
  • 2021-07-18
  • 2021-07-31
猜你喜欢
  • 2021-05-12
  • 2022-12-23
  • 2021-05-17
  • 2022-03-08
  • 2021-08-18
相关资源
相似解决方案