我在淘宝上购买了safenet的超级狗开发套件尝试开发
针对普通的Desktop Application,safenet提供了最方便的加壳方式进行加密功能。
只要定制好特定的特征,往狗里烧进去,就可以达到一般加密效果
然而这一套在Unity上是行不通的。
这里有一个小故事:
有一次我开发的项目给软件实施人员拿到现场安装,他告诉我,我们的程序应该要发布32位版本的
而这之前,我发布的是64位版本,不过这很简单,只要在Build的时候选择32位发布就好了
当我发布完成后,给对方email过去后。
他给我打电话了,说:“这是新发布的32位版本吗?为什么exe文件的修改时间并不是今天呢,依然是上一版本的日期呢?我如何确认你给我的是最新32位版本的呢?”
于是我将发布的目录删除,重新发布,结果还是一样,exe文件的修改日期依然不是今天,如果没有估计错误,那么显示的日期应该是安装Unity那一天。
这就很有意思了。
在这里我劝告一下做Unity加密狗加壳方式加密的同学们,千万不要使用该方式加密,这等于关上了门却不上把锁一样。
只要我右键查看该exe的版本号,得知了该项目由哪一个版本的Unity开发,我再去发布一个空项目出来,将这个exe替换掉
你们的加壳加密就会被轻松破解,什么去壳反编译什么的,都不需要,破解几乎无成本。
那么Unity应该怎么加密?使用加密狗软件供应商提供的LicensingAPI做判断。
由于C#相关的API文档不全面,我联系了对方的技术支持,总算成功了,这里也就抛砖引玉一下。
使用API做加密验证,步骤如下:
1.修改.Net 2.0 Subset 为 .Net 2.0
2.在Unity中导入从开发商下载的DLL,只需要红框标识出来的这一个DLL
3.将上面的5个DLL填入以下两个文件夹(注意,是5个都要)
4.在Unity编写相关验证,这里就只判断是否插入狗了,有兴趣的朋友可以查阅相关API文档,做做相关记录,和博主一起分享加密狗的有趣加密方式。
5.发布!测试!成功!
*6.最后,记得混淆代码,不然还是容易被反编译哦!
新增:读取数据文件
public string ReadFile(int fid) { Dog _dog = new Dog(DogFeature.Default); if (DogStatus.StatusOk == _dog.Login(HVCCode, Scope)) { DogFile file = _dog.GetFile(fid);int size = 0; file.FileSize(ref size); byte[] bytes = new byte[size]; file.Read(bytes, 0, bytes.Length); return System.Text.Encoding.UTF8.GetString(bytes); } _dog.Logout(); _dog = null; return string.Empty; }
新增:判断特征类型
public enum FeatureType { Perpetual, Executions, Expiration, Trial, Unknown } public FeatureType GetFeatureType(int feature) { string queryFormat = "<?xml version="1.0" encoding="UTF-8" ?>" + "<dogformat root="dog_info">" + " <feature>" + " <attribute name="id" />" + " <element name="license" />" + " </feature>" + "</dogformat>"; string info = null; DogStatus status = Dog.GetInfo(Scope, queryFormat, HVCCode, ref info); if(DogStatus.StatusOk == status) { XmlDocument doc = new XmlDocument(); doc.LoadXml(info); XmlNodeList list = doc.SelectNodes("//feature"); foreach(XmlNode node in list) { if (node.Attributes["id"].Value == feature.ToString()) { switch (node.FirstChild.FirstChild.InnerText.ToLower()) { case "executions": return FeatureType.Executions; case "expiration": return FeatureType.Expiration; case "trial": return FeatureType.Trial; case "perpetual": return FeatureType.Perpetual; default: return FeatureType.Unknown; } } } } return FeatureType.Unknown; }