技术开发 频道

.NET核心代码保护策略:隐藏核心程序集

  核心代码:

  AssemblyControl

// ***********************************************************************
// Assembly : AssemblyWPFDemo
// Author : 曾意恒
// Created : 09-25-2013
//
// Last Modified By : 曾意恒
// Last Modified On : 09-25-2013
// ***********************************************************************
//
// Copyright 2013(c) . All rights reserved.
//
// 程序集操作类
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace AssemblyWPFDemo
{
///
/// Class AssemblyControl
///
public class AssemblyControl
{
///
/// 把指定程序集转化为二进制流
///
/// 路径程序集
/// 二进制源
public byte[] GetAssemblyToByte(string assemblyFileName)
{
byte[] assemblySource=null;
if (File.Exists(assemblyFileName))
{
FileStream fStream
= new FileStream(assemblyFileName, FileMode.Open);
BinaryReader bReader
= new BinaryReader(fStream);
assemblySource
= bReader.ReadBytes(Convert.ToInt32(fStream.Length));
fStream.Close();
bReader.Close();
}
return assemblySource;
}
///
/// 二进制源转换为C#代码,方便我们新建一个静态类存入数据
///
/// 字段名
/// 二进制源
/// System.String.
public string ByteConverToString(string memberNmae, byte[] assemblySource)
{
string strAssemblySource = "public byte[] " + memberNmae + "={";
foreach (
byte b in assemblySource)
{
strAssemblySource
+= b.ToString() + ",";
}
strAssemblySource
= strAssemblySource.Substring(0, strAssemblySource.Length - 1);
strAssemblySource
+= "};\n";
return strAssemblySource;
}
///
/// 通过二进制数据源转换为程序集
///
/// 二进制源
/// 程序集
/// assembly为空,请检查二进制数据源
public Assembly GetAssemblyBySource(byte[] assemblySource)
{
Assembly assembly = Assembly.Load(assemblySource);
if (assembly == null)
throw new NullReferenceException("assembly为空,请检查二进制数据源");
return assembly;
}
///
/// 获取该程序集里有多少个类
///
/// 程序集
/// 类列表
public Type[] GetTypesByAssembly(Assembly assembly)
{
if (assembly == null)
return null;
Type[] types
= assembly.GetTypes();
return types;
}
///
/// 获取类名
///
///
/// 类名
public string GetTypeName(Type type)
{
if (type == null)
return "";
return type.Name;
}
///
/// 获取类里的所有公开方法的信息
///
/// The type.
/// MemberInfo[][].
public MemberInfo[] GetMemberInfosByType(Type type)
{
if (type == null)
return null;
return type.GetMethods();
}
///
/// 获取当前方法的名称
///
/// The menber info.
/// System.String.
public string GetMemberInfoName(MemberInfo menberInfo)
{
return menberInfo.Name;
}
///
/// 执行无返回值的方法
///
/// 方法体
/// 类实体
public void InvokeMember(MemberInfo menberInfo,object obj)
{
obj.GetType().InvokeMember(menberInfo.Name, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, obj, null);
}
///
/// 执行有返回值的方法
///
/// 方法体
/// 类实体
/// 返回结果
public object InvokeMemberHaveResult(MemberInfo menberInfo, object obj)
{
return obj.GetType().InvokeMember(menberInfo.Name, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, obj, null);
}
}
}

  AssemblyWPFDemo里的AssemblyTestSource类里存放的就是我们AssemblyTest类库的二进制流,这个二进制流是通过我写的这个DEMO转换来的,可看上图,里面有个“转换代码”的按钮,当你打开了一个DLL后就可以把它转换为C#代码,通过加载这个数据流就能获得AssemblyTest的程序集,有了程序集你就能使用程序集里的功能。由于AssemblyTestSource的代码比较多,贴上来会影响排版,大家自行下载DEMO来看。

  其他的就是一些简单的逻辑处理了,不一一贴上来,我这里只是起着抛砖引玉的作用,写得比较粗糙,大家要注意的是,程序集的二进制流要存放的隐蔽,要有艺术,不然别人还是能把二进制流取出来存入文件,这就又变成DLL了,有心研究的可以去研究一下把这些二进制数据进行个加密,尽量增加反编译的难度。

  这里我又要唠叨一下破解者和软件开发者的关系,我们写软件保护就是和破解者斗智斗勇的过程,这两个是良性的竞争关系,如果你输了只能说明你技不如人,回去回炉一下卷土再来,一味的指责并不能使你的技术提高,你得了解破解人的思路是怎么想的才能设计出更好的保护手段,我相信一个高明的破解者,也一定是一个高明的软件开发者,这两个关系并没有什么分明的界限。。。

0
相关文章