宁海在线

 找回密码
 立即注册

QQ登录

只需一步,快速开始

快捷登录

客服电话:0574-65520000
搜索
查看: 3236|回复: 0

[软件] "怎样保护我程序中的 DLL 不被别人盗用……"

[复制链接]

54

主题

453

帖子

3566

积分

Lv.9 状元

Rank: 9Rank: 9Rank: 9

积分
3566
在线时间
481 小时
发表于 2009-8-6 07:27:54 | 显示全部楼层 |阅读模式 | 来自浙江
当我看到这个问题的第一反应不是保护,而是满脑子的 IL 反编译代码  。说实话,无论你用什么方法,都不能避免被有心人 "破解"。混淆也好,加壳也罢,不过是让别人多费些功夫而已。当然,这会大大缩减 "有心人" 的范围。要保护自己的 DLL 不被别人盗用,最好的办法是把它合并到 Entry EXE 中,然后无论是 public 还是 protected 都统统混淆(再加 n 层壳  ),这样自然没有 DLL 可供盗用了。(很遗憾,还是可以盗用的。使用 脱壳器 + dump 还原程序集,然后将 EXE 作为一个 Assembly 反射 Load 到程序域中调用执行,只不过要花点时间对付那些怪莫怪样的类型名称而已)

"你说的那些太复杂了,而且我不大熟悉混淆工具,听说容易出错…… 有没有简单点的方法…… 阻止普通人就行了…… 破解高手就算了吧……"

OK! 简单是吧?本文教的方法都简单到了极点,权作无聊时玩玩吧。

方法一. 调用验证

所谓调用验证,就是在 DLL 相关类型中验证调用者是不是某个特定的程序集,如果不是则抛出异常进行阻止。

核对 Entry Assembly Name,最好使用强签名,这样就不能简单通过相同程序集名冒充。
public class MyClass
{
  static MyClass()
  {
    if (Assembly.GetEntryAssembly().FullName != "MyExe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
      throw new Exception("报告警长!发现一只耳侵入……");
  }

  public void Test()
  {
    Console.WriteLine("MyClass.Test...");
  }
}

另外一种情况是,这个 DLL 会被公司 n 个已知或未知的程序使用。我们自然不能把所有的 FullName 都写进去。解决方法是:判断 PublicKeyToken。通常一个公司的所有产品都会使用同一个签名密钥文件(snk/pfx),所生成的程序集 PublicKeyToken 都会相同。不要告诉我,你每个程序集的签名文件都是临时生成的……  
public class MyClass
{
  static MyClass()
  {
    var bytes = Assembly.GetEntryAssembly().GetName().GetPublicKeyToken();
    var publicToken = new StringBuilder();
    Array.ForEach(bytes, b => publicToken.Append(b.ToString("x")));

    if (publicToken.ToString() != "fcc8632e2470ea51")
      throw new Exception("报告警长!发现一只耳侵入……");
  }

  public void Test()
  {
    Console.WriteLine("MyClass.Test...");
  }
}

这样,非法调用者无论是通过 "new MyClass()" 还是 "Activator.CreateInstance",都会抛出 TypeInitializeException。

如果你要保护的是整个 DLL,懒得为每个类型添加 .cctor 验证代码,可以将验证代码写到 <Module>.cctor 中,不过这有点麻烦。首先 ILAsm 反编译你的 DLL。
d:\temp> ildasm MyLib.dll /out:MyLib.il

然后用编辑器打开 MyLib.il,添加如下代码 (<Module>.cctor,IL 直接从 MyClass.cctor 中拷过来就行。如果 MyLib.dll 有 PublicKey,注意删除)。
.method private hidebysig specialname rtspecialname static void .cctor()
{
// Code size 102 (0x66)
.maxstack 3
.locals init ([0] uint8[] bytes,
[1] class [mscorlib]System.Text.StringBuilder publicToken,
[2] int32 i,
[3] bool CS$4$0000)
IL_0000: nop
IL_0001: call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::GetEntryAssembly()
IL_0006: callvirt instance class [mscorlib]System.Reflection.AssemblyName [mscorlib]System.Reflection.Assembly::GetName()
IL_000b: callvirt instance uint8[] [mscorlib]System.Reflection.AssemblyName::GetPublicKeyToken()
IL_0010: stloc.0
IL_0011: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
IL_0016: stloc.1
IL_0017: ldc.i4.0
IL_0018: stloc.2
IL_0019: br.s IL_0039

IL_001b: nop
IL_001c: ldloc.1
IL_001d: ldloc.0
IL_001e: ldloc.2
IL_001f: ldelema [mscorlib]System.Byte
IL_0024: ldstr "x"
IL_0029: call instance string [mscorlib]System.Byte::ToString(string)
IL_002e: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
IL_0033: pop
IL_0034: nop
IL_0035: ldloc.2
IL_0036: ldc.i4.1
IL_0037: add
IL_0038: stloc.2
IL_0039: ldloc.2
IL_003a: ldloc.0
IL_003b: ldlen
IL_003c: conv.i4
IL_003d: clt
IL_003f: stloc.3
IL_0040: ldloc.3
IL_0041: brtrue.s IL_001b

IL_0043: ldloc.1
IL_0044: callvirt instance string [mscorlib]System.Object::ToString()
IL_0049: ldstr "fcc8632e2470ea51"
IL_004e: call bool [mscorlib]System.String:p_Inequality(string,
string)
IL_0053: ldc.i4.0
IL_0054: ceq
IL_0056: stloc.3
IL_0057: ldloc.3
IL_0058: brtrue.s IL_0065

IL_005a: ldstr bytearray (A5 62 4A 54 66 8B 7F 95 01 FF D1 53 B0 73 00 4E // .bJTf......S.s.N
EA 53 33 80 B5 4F 65 51 26 20 26 20 ) // .S3..OeQ& &
IL_005f: newobj instance void [mscorlib]System.Exception::.ctor(string)
IL_0064: throw

IL_0065: ret
}

最后编译回去。
d:\temp> ilasm MyLib.il /dll /key=my.snk /optimize /out=MyLib.dll

<Module>.cctor 会在托管模块内任何成员或类型被调用前触发,所以完全能达到我们偷懒的目的。至于测试,就不需要我多说了吧。
下载宁海在线客户端
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|客户端|浙公网安备案 33022602000116|宁海在线 ( 浙B2-20200368

关于我们|电话:0574-65520000 ,GMT+8, 2024-11-24 03:38 , Processed in 0.071746 second(s), 20 queries , Apc On.

Powered by Discuz! X3.4

© 2000-2015 NHZJ Inc.

违法和不良信息举报电话:13819844444  邮箱:admin@nhzj.com
 未成年人保护服务电话:13819844444  邮箱:admin@nhzj.com
快速回复 返回顶部 返回列表