您的位置:首页 > 其它

如何建立有效的.Net软件注册保护机制

2009-03-03 18:29 639 查看
这是我在做CodePlus软件的注册模块时遇到的实际问题,现在还没有很好的解决。

.Net程序很容易被反编译出来,也可以通过混淆器来进行一些掩盖,也可以通过强名称来保证不被修改。这真是一个矛与盾的问题。

那么到底怎么最大限度的保证软件不被修改、注册器不容易被编写。可能真是一个头痛的问题。

一般的思路大致是:

一、在注册机制上采用非对称加密结合数字签名的方法(这个过程较为复杂,也是我目前没有弄出来的地方,不过我会努力解决这个问题的,也希望得到高手们的指点)

二、一定要强名称。关于如何使用强名称,这个比较容易:一般的步骤是:

1、在vs.net提供的dos命令窗口里 用 sn.exe -k 来生成一个钥匙对。并将之放在项目根目录下。 如c:/>sn -k c:/YourPrj.snk 然后将YourPrj.snk copy到你的project目录下。

2、修改AssemblyInfo.cs,

[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("..//..//YourPrj.snk")]
[assembly: AssemblyKeyName("..//..//YourPrj.snk")]

3、rebuild it.这个时候就已经被强名称保护了。任何对生成的exe或dll进行的修改(无论是IL,或者二进制),都会导致程序将不再运行。

三、通过混淆器对生成的exe或dll进行混淆。推荐采用http://www.remotesoft.com/salamander/obfuscator/download.html 可以对强名称保护下的exe或dll进行混淆再重签名。也就是说,可以得到混淆和强名称的双重保护。当然,这里也就会提出一个问题。就是既然remotesoft的obfuscator可以对强名称保护下的文件进行修改(混淆就是大修改了)再重签到强名称,虽然它要求YourPrj.snk要保留在project的根目录下。但我想进行一下替换,应该也是有可能的。因此,从另一角度来思考,这二种方式其实到最后,对于高手来说,都不会是什么难以对付的问题。其保护功能也就很有限了。

再说关于非对称加密进行注册验证机制,由于对rsa算法的使用还不是太明白,所以一直没有测试成功。昨天在索克论坛上看到一则东西:

http://www.sorke.com/bbs/Announce/Announce.asp?BoardID=100&ID=6060

里面讲到XC#的验证代码是公开的。(这下子明白了,混淆和强名称直接都不用了。)但是我在想,要破解xc#的那位朋友,为什么不把这个验证代码去掉,然后再编译呢?不解了。或者xc#的程序是已经生成好了的,虽然提供部分源代码,也只是给你看看,而不是让你有重新编译的机会吧。那么,这个里面强名称肯定是用到了的。由于没有下下来的研究,不是太明白。先把那段有用的代码copy过来先,这是xc#进行验证的算法:

const string RsaKey = "qZj4mbr2CONBW+ABCBddSSDTfKFSzDQc9LltZ3Xzl1UrrE0iwrgQQ/NYNr3h760/JsBb5eTV
+owfTAAdjKzayIEjnTu1W2XMiDSfWfPcDaEpnoG3cWY1BhpTsUz8XxapVSHpRYovaaeA/1SY
fb0h7xbku1M4M9LgGdUwlab+iMc=AQAB";

static bool IsValidPair(string name, string key, string rsaKey)
{
try
{
byte[] b = System.Convert.FromBase64String(key);
using (RSA rsa = new RSACryptoServiceProvider())
{
rsa.FromXmlString(rsaKey);
RSAPKCS1SignatureDeformatter f = new RSAPKCS1SignatureDeformatter(rsa);

f.SetHashAlgorithm("SHA1");
return (f.VerifySignature(new SHA1Managed().ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(name)), b));
}
}
catch { return false; }
}

再引用那位强人对这段代码的分析:

我仔细检查代码后才发现,检查的代码关键是RSAPKCS1SignatureDeformatter类,它是System.Security.Cryptography名称空间中的一个类,专门负责验证RSA加密签名的。
RSA就是不对称加密的算法。就是通过私钥加密的只能通过公钥解密。上面的静态变量RsaKey明显就是公钥。就是说必须提供他通过带有私钥的Key生成器生成的验证码,才可以使Hash验证通过。就是说,没有任何办法通过公钥获得验证码。
那么生成注册码的办法没有用,是否可以通过修改IL代码的方式破解呢?只要把返回值直接改成true,那么无论是不是验证通过都可以使用了。经过检查,这个办法还是不行。
因为这个dll程序不是由XC#主程序自己使用,而是要被vs.net调用的,所以只能注册为全局程序集。我发现验证逻辑实现的程序集XHCS.VisualStudio.dll已经被安装到了GAC中。
大家都知道,安装到GAC的所有程序集必须要加入强名称验证。如果我修改了dll的内容,那么这个强名称必须被删除,这个程序集也没有办法在GAC中了,导致vs.net无法使用。

好了,现在我想到的是,基于这个代码,是否可以用在我们自己的系统里面,那么,在加密签名这块要怎么来写,尝试用:

RSACryptoServiceProvider rsp = new RSACryptoServiceProvider();
rsp.FromXmlString(skey); //这里读进了公钥和私钥
bytes=enc.GetBytes(this.rtxtUserGiveSN.Text);
bytes = rsp.SignData(bytes,"sha1");

这样的代码来做,但失败了,还没有找到原因。说是给对象设置了空值。

再想想,如果有谁对这方面有经验,希望指导一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐