摘要阐述怎样保护用MicrosoftNet开发的软件代码的安全性本人通过一次实际开发总结出一个有效的方法
众所周知软件产品是智力的成果是具有无形价值而软件又是极其容易复制所以牵涉到版权的问题一个公司或个人辛辛苦苦开发出来的软件突然发现被别人窃用了那是一件非常令人难过的事
微软公司的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 中提供了多种模糊处理程序包
经过一段时间的研究发现目前有几种基于NET的模糊工具
Dotfuscator Community Edition 我最不喜欢的混淆器由于是免费版所以必须混淆所有模块导致部分功能不能使用但我们不关心那些我们一会将展现被混淆的注册代码(因为类和方法都被混淆所以必须要花点时间)
XeonCode 一个相对强大的混淆工具我一直认为他与某着名的反编译工具捆绑导至其它工具能反编译的代码而它不能反编译我们把它的强度开到最大勾上所有能勾的选项(它混淆的Windows Application可以正常运行)
MaxtoCode 这是一个加密器可以与XeonCode叠加使用并且在版中将会加入自混淆功能成为混淆加密一体化的工具(它混淆的 Windows Applicaton 可以正常运行)
由于Dotfuscator Community Edition是微软自带的一个模糊工具而且最主要是免费软件所以决定采用这个工具对我们写的代码进行保护
先了解一下模糊处理的原理及效果
模糊处理是使用一套相关的技术完成的它的目标就是隐藏程序的意图而不更改其运行时行为它并不是加密但在 NET 代码的上下文中它可能会更好您可以加密 NET 程序集以使它们完全不可读但是这种方法会面临进退两难的局面 - 因为运行库必须执行未加密过的代码而加密密钥必须保存在已加密的程序中因此可以创建一个自动的实用工具来恢复密钥解密代码然后将 IL 以其原始的格式写入磁盘只要发生这种情况程序就完全暴露于反编译
作一个比喻加密就像将六道菜锁入了一个带锁的盒子中只有希望进餐的人(在这个例子中是 CLR)才有钥匙我们并不想让其他任何人知道他或她想吃什么东西遗憾的是就餐时食物将会被所有旁观者一览无余模糊处理工作就像是将六道菜放入了搅拌器然后将其放入塑料袋送给进餐者当然每个人都可以看到传递中的食物但是除了幸运的豌豆或者某些牛肉色的糊状物之外他们并不知道原来的菜到底是什么进餐者仍然获得了想要的菜肴并且菜肴仍然提供了与以前相同的营养价值(幸好CLR 并不过分挑剔味道如何)模糊处理程序的诀窍就是使观察者糊涂同时仍然为 CLR 提供相同的产品
当然模糊处理(或者加密)并不是百分之百的安全即使编译的 C++ 也可以被反汇编如果黑客足够有耐力她可以重新生成您的代码
先启动Microsoft Visual Studio NET 〉Visual Studio NET 工具〉Dotfuscator Community Edition我们将得到以下的界面
我们新产生一个模糊处理项目在触发器选项中选择一个要进行模糊处理的dll如图
然后在重命名项中选择要进行模糊处理的类如图所示
然后点击生成按钮生成一个进行了模糊处理的dll
为了查看处理效果将前后代码进行对比我用一个现在流行的MSIL反编译工具进行反编译
模糊处理前
反编译的效果如
public static DataTable DeleteData(DataTable table int templateid ArrayList deletelist ref ArrayList RowIDS)
{
TemplateInfo info = DataTemplateGetTemplate(templateid);
DataTable table = tableCopy();
ArrayList list = (ArrayList) RowIDSClone();
string text = EnvGetIndustryDbConnStr(DataTemplategetIndustry(infoDeptID));
ArrayList list = DataTemplateGetDeleteTables(table infoDeptID);
for (int num = ; num < deletelistCount; num++)
{
int num = ConvertToInt(deletelist[num]);
Hashtable hashtable = (Hashtable) RowIDS[num];
RowIDSRemoveAt(num);
for (int num = ; num < listCount; num++)
{
string text = list[num]ToString();
int num = ConvertToInt(hashtable[text]);
if (((text != Product) && (text != Area)) && (text != Company))
{
for (int num = ; num < RowIDSCount; num++)
{
Hashtable hashtable = (Hashtable) RowIDS[num];
int num = ConvertToInt(hashtable[text]);
if (num == num)
{
tableRowsRemoveAt(num);
RowIDSRemoveAt(num);
}
}
string text = stringConcat(new string[] { Delete from text where DataTemplateGetTableID(text infoDeptID) = numToString() });
int num = ;
try
{
SqlHelperExecuteNonQuery(text CommandTypeText text);
}
catch (Exception exception)
{
string text = exceptionMessage;
}
}
}
}
return table;
}
可以看出和原始代码相差无几
对模糊处理后进行反编译代码如下
public static DataTable DeleteData(DataTable table int templateid ArrayList deletelist ref ArrayList RowIDS)
{
d d = DataTemplatec(templateid);
DataTable table = tableCopy();
ArrayList list = (ArrayList) RowIDSClone();
string text = oa(DataTemplatea(dh));
ArrayList list = DataTemplateb(table dh);
for (int num = ; num < deletelistCount; num++)
{
int num = ConvertToInt(deletelist[num]);
Hashtable hashtable = (Hashtable) RowIDS[num];
RowIDSRemoveAt(num);
for (int num = ; num < listCount; num++)
{
string text = list[num]ToString();
int num = ConvertToInt(hashtable[text]);
if (((text != Product) && (text != Area)) && (text != Company))
{
for (int num = ; num < RowIDSCount; num++)
{
Hashtable hashtable = (Hashtable) RowIDS[num];
int num = ConvertToInt(hashtable[text]);
if (num == num)
{
tableRowsRemoveAt(num);
RowIDSRemoveAt(num);
}
}
string text = stringConcat(new string[] { Delete from text where DataTemplatef(text dh) = numToString() });
int num = ;
try
{
vd(text CommandTypeText text);
}
catch (Exception exception)
{
string text = exceptionMessage;
}
}
}
}
return table;
}
可以看出模糊处理对相应的类方法进行了重命名同时增加了代码机密性
使用该工具对我们公司所有的代码进行了模糊处理保护了我们公司人员的辛苦工作成果极大地维护了本公司的利益希望上述经验能对大家有点帮助