摘要:阐述怎样保护用Microsoft.Net开发的软件代码的安全性。本人通过一次实际开发,总结出一个有效的方法。 众所周知,软件产品是智力的成果,是具有无形价值。而软件又是极其容易复制,所以牵涉到版权的问题。一个公司或个人辛辛苦苦开发出来的软件,突然发现被别人窃用了,那是一件非常令人难过的事。 微软公司的.NET开发效率非常高,使用Microsoft Visual Studio .NET 开发工具,参考.NET Framework SDK,你很快能开发出实用的程序,快速而且高效。 最近我公司开发了一个大型网站开发项目,其中包括了一个网站后台管理系统(CMS),是用C#开发,整个项目开发效率很高,使用Microsoft Visual Studio .NET 开发工具,自动生成aspx页面。在项目实施阶段,出现了一个问题,因为对方公司项目款还没完全给付,所以需要对相关代码进行保护,防止被窃用,损害本公司利益。 但是MSIL本身是很容易被反编译的,利用像 ILDASM(.NET Framework SDK 附带的 MSIL 反汇编程序)这样的工具或诸如 Anakrino 和 Reflector for .NET 这样的反编译程序,任何人都可以轻松地研究您的程序集并利用反向工程将它们转换为可读的源代码。黑客可以搜索可利用的安全漏洞、盗取独特的思想,甚至破解程序。 由此,我想到了,应该对这些代码进行某种程度的保护,想过加密,但怕影响程序速度,后来决定采用模糊处理。它将帮助防止反向工程。模糊处理是一种提供程序集中无缝重命名的符号以及阻止反编译程序的其他技巧的技术。正确应用该技术后,模糊处理可以极大地增加免遭反编译的保护,而使应用程序不受任何损害。模糊处理通常用于 Java 环境中,很多年来一直用于公司保护基于 Java 的产品的知识产权。很多第三方根据需要创建了适用于 .NET 代码的模糊处理程序。Microsoft 在与 PreEmptive Solutions 的合作中将 Dotfuscator Community Edition 包括在 Visual Studio®.NET 2003 中,提供了多种模糊处理程序包。 经过一段时间的研究,发现目前有几种基于.NET的模糊工具: 1. Dotfuscator Community Edition 我最不喜欢的混淆器,由于是1.2免费版,所以必须混淆所有模块,导致部分功能不能使用。但我们不关心那些,我们一会将展现被混淆的注册代码(因为类和方法都被混淆,所以必须要花点时间) 2. XeonCode 一个相对强大的混淆工具,我一直认为他与某著名的反编译工具捆绑,导至其它工具能反编译的代码而它不能反编译。我们把它的强度开到最大,勾上所有能勾的选项。(它混淆的Windows Application可以正常运行) 3. MaxtoCode 这是一个加密器,可以与XeonCode叠加使用,并且在2.0版中,将会加入自混淆功能,成为混淆加密一体化的工具。(它混淆的 Windows Applicaton 可以正常运行) 由于Dotfuscator Community Edition是微软自带的一个模糊工具,而且最主要是免费软件,所以决定采用这个工具对我们写的代码进行保护。 先了解一下模糊处理的原理及效果: 模糊处理是使用一套相关的技术完成的。它的目标就是隐藏程序的意图,而不更改其运行时行为。它并不是加密,但在 .NET 代码的上下文中,它可能会更好。您可以加密 .NET 程序集以使它们完全不可读。但是,这种方法会面临进退两难的局面 - 因为运行库必须执行未加密过的代码,而加密密钥必须保存在已加密的程序中。因此,可以创建一个自动的实用工具来恢复密钥、解密代码,然后将 IL 以其原始的格式写入磁盘。只要发生这种情况,程序就完全暴露于反编译。 作一个比喻,加密就像将六道菜锁入了一个带锁的盒子中。只有希望进餐的人(在这个例子中是 CLR)才有钥匙,我们并不想让其他任何人知道他或她想吃什么东西。遗憾的是,就餐时食物将会被所有旁观者一览无余。模糊处理工作就像是将六道菜放入了搅拌器,然后将其放入塑料袋送给进餐者。当然,每个人都可以看到传递中的食物,但是除了幸运的豌豆或者某些牛肉色的糊状物之外,他们并不知道原来的菜到底是什么。进餐者仍然获得了想要的菜肴,并且菜肴仍然提供了与以前相同的营养价值(幸好,CLR 并不过分挑剔味道如何)。模糊处理程序的诀窍就是使观察者糊涂,同时仍然为 CLR 提供相同的产品。 当然,模糊处理(或者加密)并不是百分之百的安全。即使编译的 C++ 也可以被反汇编。如果黑客足够有耐力,她可以重新生成您的代码。 先启动Microsoft Visual Studio .NET 2003-〉Visual Studio .NET 工具-〉Dotfuscator Community Edition,我们将得到以下的界面: 我们新产生一个模糊处理项目,在“触发器”选项中,选择一个要进行模糊处理的dll,如图: 然后在“重命名”项中,选择要进行模糊处理的类,如图所示: 然后点击“生成”按钮,生成一个进行了模糊处理的dll。 为了查看处理效果,将前后代码进行对比。我用一个现在流行的MSIL反编译工具进行反编译。 模糊处理前: 反编译的效果如: public static DataTable DeleteData(DataTable table, int templateid, ArrayList deletelist, ref ArrayList RowIDS) { TemplateInfo info1 = DataTemplate.GetTemplate(templateid); DataTable table1 = table.Copy(); ArrayList list1 = (ArrayList) RowIDS.Clone(); string text1 = Env.GetIndustryDbConnStr(DataTemplate.getIndustry(info1.DeptID)); ArrayList list2 = DataTemplate.GetDeleteTables(table, info1.DeptID); for (int num1 = 0; num1 < deletelist.Count; num1++) { int num2 = Convert.ToInt32(deletelist[num1]); Hashtable hashtable1 = (Hashtable) RowIDS[num2]; RowIDS.RemoveAt(num2); for (int num3 = 0; num3 < list2.Count; num3++) { string text2 = list2[num3].ToString(); int num4 = Convert.ToInt32(hashtable1[text2]); if (((text2 != "Product") && (text2 != "Area")) && (text2 != "Company")) { for (int num5 = 0; num5 < RowIDS.Count; num5++) { Hashtable hashtable2 = (Hashtable) RowIDS[num5]; int num6 = Convert.ToInt32(hashtable2[text2]); if (num6 == num4) { table1.Rows.RemoveAt(num5); RowIDS.RemoveAt(num5); } } string text3 = string.Concat(new string[] { "Delete from ", text2, " where ", DataTemplate.GetTableID(text2, info1.DeptID), " = ", num4.ToString() }); int num7 = 0; try { SqlHelper.ExecuteNonQuery(text1, CommandType.Text, text3); } catch (Exception exception1) { string text4 = exception1.Message; } } } } return table1; } 可以看出,和原始代码相差无几。 对模糊处理后进行反编译,代码如下: public static DataTable DeleteData(DataTable table, int templateid, ArrayList deletelist, ref ArrayList RowIDS) { d d1 = DataTemplate.c(templateid); DataTable table1 = table.Copy(); ArrayList list1 = (ArrayList) RowIDS.Clone(); string text1 = o.a(DataTemplate.a(d1.h)); ArrayList list2 = DataTemplate.b(table, d1.h); for (int num1 = 0; num1 < deletelist.Count; num1++) { int num2 = Convert.ToInt32(deletelist[num1]); Hashtable hashtable1 = (Hashtable) RowIDS[num2]; RowIDS.RemoveAt(num2); for (int num3 = 0; num3 < list2.Count; num3++) { string text2 = list2[num3].ToString(); int num4 = Convert.ToInt32(hashtable1[text2]); if (((text2 != "Product") && (text2 != "Area")) && (text2 != "Company")) { for (int num5 = 0; num5 < RowIDS.Count; num5++) { Hashtable hashtable2 = (Hashtable) RowIDS[num5]; int num6 = Convert.ToInt32(hashtable2[text2]); if (num6 == num4) { table1.Rows.RemoveAt(num5); RowIDS.RemoveAt(num5); } } string text3 = string.Concat(new string[] { "Delete from ", text2, " where ", DataTemplate.f(text2, d1.h), " = ", num4.ToString() }); int num7 = 0; try { v.d(text1, CommandType.Text, text3); } catch (Exception exception1) { string text4 = exception1.Message; } } } } return table1; } 可以看出,模糊处理对相应的类,方法进行了重命名,同时增加了代码机密性。 使用该工具,对我们公司所有的代码进行了模糊处理,保护了我们公司人员的辛苦工作成果,极大地维护了本公司的利益。希望上述经验能对大家有点帮助。 |