列举工作以来遇到的各种类型的软件所采用的代码保护技术,只讲原理不涉及技术细节实现,以避免产生法律问题。有些朋友说直接把代码放在Github开源下载,开源可以促进技术交流与进步,然而值钱的代码都积压在硬盘里面,即使很烂的代码都卖了很多钱,赢得了许多客户与市场。珍惜爱护公司的代码,他们都是宝贵的财富。

以下保护技术主要测重于脱机验证与保护,不涉及联网(连接到许可证服务器)验证。

1、程序集混淆 Asembly obfuscate

CLR代码的运行是即时编译执行的,.NET编译器只是将源代码文件编译成中间语言,中间语言包含丰富的元数据。使用.NET Reflector/ILSpy/JustCode这类的反编译器几乎可以还原整个源代码,所以用.NET开发软件第一个要做的任务是混淆编译后的中间语言代码。这也是我见得最多的.NET代码保护技术。

2、写注册表 Registry

虽然.NET时代强调XCOPY部属,但很多很程序依然依赖于注册表来做保护技术的基础。可以把自己想要隐藏的信息放到很深的注册表键中。

一些程序会将注册表键做一个字符串处理,比如将字符串改成16进制值,或是做一个DES混淆处理,在不知道解密键(KEY)的情况下很难看出它的意思。

3、RSA 签名  RSA Signature

RSA签名技术可以生成二个密匙,私匙用于生成许可文件,公匙用于验证许可。

string publicKey = "<BitStrength>1024</BitStrength><RSAKeyValue><Modulus>wDSWDT4ujpa+B7VkwdXGDvIEDc18O6qSnGtL38prVR18B7sjqbhR2Uq1C7hksADnF

DH+PAHv9BAWiqa1cWeaVgCwC2LNMClaJu4jZg0aFDIzhZUNHV56KS5aaVD+MHH+iEGmPok9XRz7Jd8hyjD38jHl439Uaf6oltxMRdKS5KU=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

string privateKey = "<BitStrength>1024</BitStrength><RSAKeyValue><Modulus>wDSWDT4ujpa+B7VkwdXGDvIEDc18O6qSnGtL38prVR18B7sjqbhR2Uq1C7hksADnFDH+PAHv9B

AWiqa1cWeaVgCwC2LNMClaJu4jZg0aFDIzhZUNHV56KS5aaVD+MHH+iEGmPok9XRz7Jd8hyjD38jHl439Uaf6oltxMRdKS5KU=</Modulus><Exponent>AQAB</Exponent><P>82nuszkXKLx

+NDtQLiruBlDGozAUaJ50PqHKq7jglLV740jz521+v2O6EVA+59gpGSwFrX6E7HnUrkKBQGbY/w==</P><Q>yiTO+1+xaNvmEcAyKdFboNRbP1/toUnakkREKyYCg/KLnjgpkb22gMtu

u5ocbfY2vIdyDZbYYeXmLYSJ9Io+Ww==</Q><DP>ds7Zx3iyKRv3rZ7Vv/MMQuDiU3yAOaA9tORbe/29AFiko4dUJT14hAo1I4Y7bgY/6R1nmAsM7i9486VaWQjaGQ==</DP><DQ>sRU

1zbiy7i1Vi09XopKpNmdR2F7tCVJti50KKtKNeZHNBbolkGslqgaM5wPGy/3ZTadKHuV6gaio0E8/m15P6Q==</DQ><InverseQ>YsZNcptrcalrlR5TS+rJ+m9G8+xUIJGGLSB3Czjw

q28rFgXa//avpx05E3FIN0tfAOKJhy84VKElqPNyQyacNA==</InverseQ><D>jaNy3Clxl6QgP3/90xWc0ZCpSh6eKT4GsnwjOrRpKh0DNJNEsaJhtpXmGs/0avsPToOUzVXEJP/iDKTTWtG

1GdkqZp+gaqKbp73RP21Nmd+lZ/S1WvmUTe3Ge5I5FP/7zf9KnTXBm1yLel/9N5UL6o5EncPNjqUt2+oKQ+q7vJU=</D></RSAKeyValue>";

  
因为私匙只存在于自己的电脑中,不会发布到程序中,只要私匙不泄露出去,这种加密方法是相当安全的。

破解RSA签名的唯一方法是替换公匙,用自己生成的私匙生成许可文件。

4、参数保护 Parameter Protection

基于第3条RSA签名技术,签名之后产生的字符串是只读的,在它的基础上我们可以增加许多控制点,比如可使用的用户数,过期时间,最大账套数等。

在我的Enterprise Solution开发框架中,提供基于第3条和第4条为原理的许可保护技术的例子,在一定程度上保护产品不被未授权用户使用。

5、机器硬件识别 Hardware Recognition

为了控制软件不会被客户随意拷贝分发,一方面通过法律合同条文明确禁止,但通常这没有什么卵用,另一方面则必须做硬件识别。在生成许可文件之前,要依赖于客户的机器配置,将客户的机器硬件信息完整的保存到许可文件中,运行时逐条检测,发现有不一致的地方立刻退出应用程序。

.NET 提供了WMI接口用于读取机器相关的信息,参数如下的代码例子:

  private static string GetDiskDriveSize()
        {
            return WmiHelper.GetWmiPropertyValue("Win32_DiskDrive", "Size");
        }

        private static string GetDiskDriveTotalSectors()
        {
            return WmiHelper.GetWmiPropertyValue("Win32_DiskDrive", "TotalSectors");
        }

        private static string GetDiskDriveTotalTracks()
        {
            return WmiHelper.GetWmiPropertyValue("Win32_BaseBoard", "Manufacturer");
        }

三个方法分别读取硬盘大小,硬盘分区,主板制造商,将这些信息组合起来放到一个字符串文件中,即是电脑的硬件信息,再对这个字符串做一个DES对称加密或是RSA签名处理,处理之后,客户的硬件信息看起来是这样的字符串。

lxocnnn7ofk2+Nheb7Qo+cBRDlCbVWHCfVSFG/XnyT3F7q/avyRL3Lj7gotPMtuo41A33AjSryt5a1ydvu7tTOnsOsizy8HJIrP13T5jHbgyHZgZaQk54eGLN3eft5zijKT3hyirZ5w2Mf6mWmv/9F

68jFxsnNh//OUUAVI3lx0=KMw2gRnZ8BqL4lNw4A5j+tuDlvbsj5gp3CGZNbAXlFlGW188uliAZexb6GhcvB0VSwTV37R6NUstT/VT5MJ7wyf/zyyHpa1uHGx4/UziLCAwawnap90BkQWlH1aVz

2lTX3I93iKKYOdAJF0y5TM9njlVvqToj2cBBWLUG+sYXxo=DUjIpSbrp5cl8L//WbIs7ErSX8RBTeVMFO7OCIYoTh7yogVzJNH3D3QZHYKnNfGmJDMSleJSgdLb0GdiWdEgiLTf0uv7lQsoA076

WM5VrtG7O/h0E3DvmisP7OkkuJIMEIpExaM+3GDlIHGvHYRK0nDfzBQM8AXM2k0ue8wj0xY=k5CRv+IkEdB6yZEy65iLXsU0lQT1FbHwSH7LawWBoOZHJt1TwIAajHuqH0AHAWZgRHYDbHCxnlJFv9t

OepsJdNGL6CvjUEnyuNA3RlhKNB6K51rOjIQ1ROKRiy9z+YsbHbJxdbsj3km/kITzfHvoDqQIg4zrTR0XfSn49j0rMkI=C4oBw14/k1OWPzMC1SUe+YxrJtyUqzL2k/cKz/feAhZ0DELbUiCUcbjhHg

+ryg+E7P5Bfy53n3kH5SBud4rVBpRUZGx4xZFPB8eXQ40SUCMxs74cbQRUPh7+zQo6qF/AtrQkXKbzoiZKHCz50n6h/afaa+jwuOplYUx191269w4=RGDYBw6j5VXJO7phILX1zLRcbO3+6SrBuCLEFwk

sitOk/z+OGtFEoIfHD5DZRp9t6GVYtpdI7jPVz7lTV4DL5xfCQ8woJjpqUdB++pYaIw3gx9EL6PD+ucRfLKtiNng6ujKe0r6A51y9eGJRic9p8uAPGSEj8OtNLmO0mVWcwhE=GJg9mdr/YdDMZCVe0WPb3

S8YGKfzdPYj3xJTQtRYdFLV9E6GHzQj8FFgIrxjdoD3n9FGthhF82MTpjS3kOdIyQEc7moienSbzqevcUPs4ZmDwmveH/F4DSynS7JAiPqCcnAj7N4EI/PkXZWAtdHSra2yWBkEBw5PlVhLTLbcLGE=FL

+JSw0yGUIpIZUgq8VRt27e5J+D0vRoEw9t5NKPROysnGw=YN1yhy2reEhQPs30aCnOpNDz2

He2E9re26QBwipNgivHM8Z/FcLk0hjALeiC8zY4Dcn+0PKag6DH7tmIBwTpBus2+ZqjLlgIx7uKMPB49+yPC5qOV8vsJGV/s81xVEA+prgNbh9Sa3TSsBV3qMSyZDEyvkHc+1QbBoLd/1h2WUI=p0/G

lIKMQ7XoRom9njDq5XPn3sj4V8P137v6eDDq7uTpRcTXD/qOWi/IZMcNX56LqVb1PJko0BCUYXa8h0zzEvsmTJNXUzggZlpkzk4EOzq4GekTwM6hXcn0Es/6iZ2J5Et1h5kSOOk1MLZS3cmUHeSRn0js

Ed0O/+L8+qBNpYapf6GL2iYf5j/Qfi+2djOwqCspHawZcBZ/e/WtK0b/0F4=lmHD5BVilXA7KIQk8yma7d4dP5mawdNhMEuYG68sN15SJOUMZlGiFT17rh0Y7Z

54itnjVmhaRVXBsc/LDKYPIwsD+TZBTGDbSOebmxvDe+Jdh6ZLsmGUIdREH4/L19y1713PyJ2r6HYi9v/8GobkWWg4chIKggBhSYUJFP8jj4Q=JHNsEDYacXEIwWhR

nDfiQoWZbrZjmCgF7lo9g4BCTYD0KbLLRKdrDERNPTQs+e3kLf0/fhc0x0BsE/yCuYcnj8rh9/iA08ZUxO+TZkz/p5rseWklWboc45o90q/ZXfuu5f+TCVPnfTXCxMjwdH3

F4I7EotPzweUS/P++YDvHHWA=d8l5s9fNa0fUX4eo9LoHVT4Wb8YbHKDvDW7o1P+wTDykIrOCLoCKklrSGdHjOi8EWw=LDrOGw3pq7rv4L7YoGLaZAmXfRdcw1wp2Zi/Hn2

这样既避免了客户隐私信息泄露,也可以解决当前软件氛围环境下软件分发的困扰。

6、序列号/注册码 Serial Key

相当多的软件还是采取这一传统的序列号保护方法,比如Windows Server 2012的注册码:

NB4WH-BBBYV-3MPPC-9RCMV-46XCB

一组看似无序的数字与字母的组合,对软件保护起了很重要的作用。如果是在软件安装时验证序列号,则破解难度会更大。

序列上面的字母数字组合,可以包含很多信息,比如客户名称,过期时间,最大用户数。将这样的序列号分享给同行的其它客户,一旦软件公司追查起来很容易就能识别这个序列号是否合法。

在我的博客下载工具中用到的一个组件aspNetMHT,它就是采用这个方法来分发序列号的,序列号中包含过期时间。aspNetMHT的序列号看起来是这样的:

SM48Z-FMXGZ-25P67-4ZJKF-GS211-AQYA4-7VHUX-KCF1C-RD4RC-RU7XS-XK8JY-6JT54-M9CX

7、强名称 Strong Name

强名称不是一种代码保护技术,而是程序集标识技术。每个经过strong name签名后的程序集都是唯一的,在运行时可以验证这个文件的签名是否被改动过。

验证强名称的关键地方在于调用CLR中的基础方法:

[DllImport("mscoree.dll", CharSet = CharSet.Unicode)]
public static extern bool StrongNameSignatureVerificationEx(string wszFilePath, bool fForceVerification, ref bool pfWasVerified);

所以开发.NET程序,不仅仅要给程序签名,还需要在运行时验证所给的签名是否被改动过。

.NET CLR支持对程序集跳过强名称验证,不过这样做的风险太大,直接修改了CLR的行为,未见有很多实例。

8、内存保护 Memory  Protection

Delphi XE采取了这种方法,运行时会生成一段验证代码,验证结束后代码销毁,因为验证在内存中进行,不会在硬盘上留下痕迹,破解的难度相对困难了很多。

Win32支持动态加载和卸载程序集,所以Win32 API中有接口LoadLibrary和UnloadLibrary供调用,可实现内存保护。

.NET也支持动态加载程序集,但不支持卸载(unload)程序集,程序集的卸载由CLR控制,这一点给破解内存保护技术提供了方便。

在我的Enterprise Solution开发框架中,将第7条和第8条组合一下,简单的解释如下:创建一个类型定义文件,然后将这个文件用强名称签名,之后将这个签名的程序集经过混淆,字符串加密等处理,附加到启动程序的资源文件中去,运行时,我从资源文件中将此程序集解析释放出来,同时强制验证程序集的强名称,运行类型定义文件中指定的验证方法,实现简单的内存保护技术。

破解这种保护需要知道签名程序集的强名称,字符串加密处理的全流程和相应的键,给破解增加了不少难度。要验证什么和怎么验证都是在我设计的类型定义文件中指定的,启动程序只是一个壳,运用反射调用要验证方法。而且这个经过签名后的程序集是附加到主程序中去的,要替换这个资源文件,也需要一些方法和技巧。

9、源代码混淆 Source code obfuscate

经过编译混淆后的.NET程序集,在运行时依旧可以被调试器附加调试。如果我能将源代码中的敏感字符串替换成乱七八糟的字符串,减少明文的出现,虽然降低了性能,但这样可以增加安全性。比如,我运行时检测找不到许可文件时,抛出以下异常:

string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"license.lic");
if (!File.Exists(path))
  throw new LicenseException("License file not found");

经过源代码敏感字符串替换后的程序如下:

string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"license.lic");
if (!File.Exists(path))
  throw new LicenseException(B("/jNloqd4U59LBT64eX1hb9eO8kYDD7tD"));
经过一个B方法的调用,无法看到异常的明文,增加了破解难度。如果代码中这样的B方法有很多,而且B方法的字符串处理方式各不相同,无疑提高了系统的安全性。

现在市场上有很多JavaScript源代码混淆工具,就是把JavaScript代码的格式打乱,让它不容易读取。

C#源代码也可以采用此方法,不过,读强大的Visual Studio有文档格式化功能(Edit-Advanced- Format Document ,Ctrl + E,D) ,瞬间变为可读的格式。

10、本机代码 Native Code

即将发布的Visual Studio 2015提供.NET Native功能,可将.NET代码编译为本机代码。然而经过近一年的等待,.NET Native目前也是仅仅限定于Windows应用程序商店项目,真正的Windows Forms/WPF/ASP.NET要实现编译为本机代码可能不现实。

这种保护方法的核心是许可验证逻辑放在本机代码中,直接编译成机器码。一般采用Visual C++/Delphi/VB6之类的工具,将重要的算法与验证编译成机器码,这样会增加破解难度。本机代码难于处理的一个方面是.NET Any CPU的问题。当我们设定.NET编译为Any CPU时,CLLRU会依据程序运行的平台(x86,x64)编译为本机代码。

在x64的系统中加载32位的本机代码,常常会抛出无效的程序集异常。破解这种保护的方法可直接修改.NET程序中的调用方法,可以忽略本机代码的逻辑。

相对于前面的几种技术,这种保护技术破解难度更大,要懂的知识点也非常多。

 

[转载].NET商业软件源码保护的更多相关文章

  1. atitit.商业版 源码保护 与 java本地原生代码转换 的方案总结

    atitit.商业版 源码保护 与 java本地原生代码转换 的方案总结 1. 为什么虚拟机语言容易被反编译 1 2. 源码泄露的问题问题 1 3. Excelsior JET 1 4. gcj.的流 ...

  2. [.NET产品源码保护].NET防止反编译(非混淆加密)

    .NET产品源码保护产生的背景: .NET源码加密方案支持C#及VB.NET等语言开发的ASP.NET及WINFORM应用.利用.NET支持托管代码与非托管代码共存的特性,将C#代码经过处理放于非托管 ...

  3. .NET产品源码保护,.NET防止反编译,c#/vb.net 防反编译

    .NET产品源码保护产生的背景: .NET源码加密方案支持C#及VB.NET等语言开发的ASP.NET及WINFORM应用.利用.NET支持托管代码与非托管代码共存的特性,将C#代码经过处理放于非托管 ...

  4. APP加固技术历程及未来级别方案:虚机源码保护

    传统App加固技术,前后经历了四代技术变更,保护级别每一代都有所提升,但其固有的安全缺陷和兼容性问题始终未能得到解决.而下一代加固技术-虚机源码保护,适用代码类型更广泛,App保护级别更高,兼容性更强 ...

  5. 关于HTML、js加密、混淆、源码保护、代码安全,防止解压直接看源码

    一直有人问HTML加密混淆怎么做,其实这在业内是早已很多人研究过的课题.假日期间整理一篇文章分享给大家. 我们先理下需求,加密的目的是什么?加密到什么级别?为此我们可以牺牲什么?我们知道这个世界不存在 ...

  6. [转载]JMeter源码导入Eclipse

    转载自:http://www.cnblogs.com/taoSir/p/5144274.html 由于JMeter纯Java开发,界面也是基于Swing或AWT搞出来的,所以想更深层次的去了解这款工具 ...

  7. js源码保护

    js的不可读化处理分为三个方面:压缩(compression).混淆(obfuscation) 和加密(encryption). (不可读化处理,这是我自己发明的术语,一切会增加代码不可读性的代码转换 ...

  8. [转载]《STL源码剖析》阅读笔记之 迭代器及traits编程技法

    本文从三方面总结迭代器   迭代器的思想   迭代器相应型别及traits思想   __type_traits思想 一 迭代器思想 迭代器的主要思想源于迭代器模式,其定义如下:提供一种方法,使之能够依 ...

  9. 转载-HashMap1.7源码分析

    原文地址-https://www.cnblogs.com/chengxiao/p/6059914.html HashMap实现原理及源码分析   哈希表(hash table)也叫散列表,是一种非常重 ...

随机推荐

  1. SpringMVC前后台数据传递中Json格式的相互转换(前台显示格式、Json-lib日期处理)及Spring中的WebDataBinder浅析

    两个方向: 一.前台至后台: Spring可以自动封装Bean,也就是说可以前台通过SpringMVC传递过来的属性值会自动对应到对象中的属性并封装成javaBean,但是只能是基本数据类型(int, ...

  2. Android5.0新动画之VectorDrawable

    SVG是前端的一套标准,Vector是在Android中使用,他只是实现了SVG语言的Path的标签 Vector的常用语法   M = moveto(M X,Y): 将画笔移动到指定的坐标位置   ...

  3. java算法 蓝桥杯 洗牌

    问题描述 小弱T在闲暇的时候会和室友打扑克,输的人就要负责洗牌.虽然小弱T不怎么会洗牌,但是他却总是输. 渐渐地小弱T发现了一个规律:只要自己洗牌,自己就一定会输.所以小弱T认为自己洗牌不够均匀,就独 ...

  4. 06.Lucen入门程序-Field

    需求: 实现一个歌词搜索系统,通过关键字搜索,凡是文件名或文件内容包括关键字的文件都要找出来. 注意:该入门程序只对文本文件(.txt)搜索. Lucene中包含两个重要的类: IndexWriter ...

  5. 111. Minimum Depth of Binary Tree (Tree; DFS)

    Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...

  6. 推荐一个好用的sql版本控制和美化工具SQLToolbelt

    SQL Toolbelt含Red Gate公司目前出品的所有SQL Server工具和新版本.也就是说,当你使用SQL Server数据库工作时,您可以很方便的获得您所需要的一套强大的工具,包括SQL ...

  7. code1085 数字游戏

    划分dp 把环变链(读入4 3 -1 2变成4 3 -1 2 4 3 -1 2) 设dp[i][j][k]为把i~j分成k份,各部分内的数字相加,相加所得的k个结果对10取模后再相乘,最终得到的一个数 ...

  8. hra控件自动绑定

    1.前台js代码 $.ajax({ type: "post", url: 'AlmMarketScenarioDetailManage.aspx?_method=queryPane ...

  9. c linux ping 实现

    摘自:https://blog.csdn.net/weibo1230123/article/details/79891018 ping的实现和代码分析一.介绍     ping命令是用来查看网络上另一 ...

  10. HBase环境搭建随记

    ====软件版本==== jdk:jdk-8u77-linux-x64.tar.gz zookeeper:zookeeper-3.4.6.tar.gz hadoop:hadoop-2.7.4.tar. ...