EnsignKim 发表于 5-10-2010 20:41:22

几招百试不爽的软件防破解技巧,程序员必读

孰不知再好的盾也有茅可以刺破一样,世界上很多nb的软件用了好多nb的防破解技术,结果还是被强大的黑客一一攻破,那对于我们这样的小程序员或小公司来说,既然nb的技术没有用,我们也没有那nb的防破解技术,何不如化有形为无形,不去用技术问题解决软件的防破解。  个人总结:软件防破解其实不是技术问题,而是一个社会工程学问题。
  现在就给大家几条在开发软件的过程中几招百试不爽的软件防破解技巧,这些非技术的技巧实现起来很容易,但是防破解的效果是大大的。以我的软件为例(http://www.boneb.com/)
  1、试用版就是试用版
      我前几年开发过一款叫做网络信息采集专家的软件,分为正式版和试用版,这个软件最主要的目的就是采集网站上的数据到本地数据库中,试用版和正式版的区别就在于试用版不能保存采集下来的数据。在这种情况下,很多做软件产品的程序员,在软件里区别正式版和试用版就仅仅是靠注册码验证而已,这种情况下,只要试用版被破解,那正式版就到手了,而我做思路就是,正式版不提供公开下载,只有用户付费后才提供下载地址,公开发布的试用版里彻底不放提供保存数据的代码,造成的结果是,很多破解者得到试用版后就破解,令他们高兴的是,软件很容易破解(我的加密算法本身就不想写得太复杂),但令他们沮丧的是,破解成功后,试用版还是试用版,改有的功能还是没有。这个招式适合软件使用量不是特别大的用户,依我的看法,95%的软件使用量都不算大,所以这招其实大家皆可用之。
  2、开发“破解版”
  呵呵,大家是不是不理解这一点,以为我打错了呢,对,没错,就是自己制作自己软件的破解版,在软件正式版发布后,你可以同时制作一个假的“破解版”,也就是从软件表面上让大家认为这是个破解版,实际上用了一小段时间后,就发现这个破解版是不可用的,或不好用的,这个时候你的“破解版”再适时弹出“破解失效,请到××处购买正式版”等宣传话语。然后你把这个假的破解版找几个有明的破解站上传,这个时候真的破解版还没出假的破解版就已经满天飞了,这样的情况下大多数用户都不可能下载到真的破解版,并且上了你的当用了假的破解版后,定会对破解版大失所望,认为网上流传的破解版都不可用,这样就更有可能购买你的正式版软件。
  3、让简单的算法不简单
  你可能用来以防止破解的算法比较简单,但这并意味着你就不能有效的阻止破解,我们照样可以用简单的算法把破解者弄崩溃掉,我的软件用了5种破解算法,每种算法都不是很复杂,估计单个破的话也就10来分钟的事情,但我的做法是没有将所有算法全部用于同一时间同一处进行注册码的验证,而是分散到软件的不同功能,不同时间来验证,有的是软件启动,有的是点某个按钮的时候,有的是当时间达到某个条件的时候,破解者往往是把软件启动时候的验证给破掉,但是他在使用过程中又会经常随机的遇到很多验证失败的提示,而且这些过程随机,可能除了作者,没人知道这背后有多少处验证,这些验证又是什么时候触发,所以这种做法能让破解者抓狂的说。另外很多破解者仅仅是为了破解而破解,自己本身又不用被破解的软件,往往是启动阶段的验证一破解掉,就认为大功告成的开始发布“成功”破解版。
  4、联网验证
  如果你的软件是基于互联网提供服务的,你可以在软件中写一段代码到你的网络数据库中取信息,取到这些信息软件才可正常使用,当然这些数据必须是软件必须的,而且是不可伪造的,否则破解者把你联网验证的这段代码给爆破掉照样可以正确破解。
  5、服务为本
  尽量让你的软件提供的是一种服务,而不是某项技术本身,如果仅仅是某项技术,软件一被破解,用户拿到破解版的软件就不再需要你了;如果是服务,即使用户得到了可用的破解版,他可能还是需要转而寻求你获得技术支持,通过这种策略也可以避免破解带来的巨大损失。
  好,就写这么多,这些办法一用上破解者就很难破解你的软件了,而且你完成这些工作也不需要太多时间,更不需要money,以我的网络信息采集专家为例,从2003年发布至今,我还没有遇到过真正的破解版,倒是经常看到一些破解论坛上对于我软件的破解感到非常困惑,无技可施。本文转至http://www.boneb.com/,转载请注明出处,并保持链接,谢谢!

woodheadz 发表于 6-10-2010 17:47:10

我也处理过破解的问题。因为是基于C#做的系统,所以防破解难度更大。当时我的方案是这样:
1.我们的系统有一个组装系统的各个部件的核心,这个核心同时也是我们进行授权控制的地方,用户数,设备数量,设备的种类全都可以进行控制。由于系统抽象得比较充分,所以这个核心相当稳定,基本上不会进行什么修改。
2.这个核心被单独做成一个Dll。当用户购买时我们通过工具直接修改dll的源代码,将授权控制信息写入编译。之后将dll进行数字签名,然后使用一个C++写的加密算法进行加密,将加密后的dll作为key发布给用户。
3.系统启动时调用c++的解密算法解密dll到内存中,验证数字签名之后将解密后的dll镜像直接在内存中加载。
4.将加载核心的程序混淆化。在系统多个地方进行数字签名验证
我们使用C++加密算法是一个大学生的毕业设计,并非标准算法。加密和解密的代码是分离的。加密代码永远不会发布。

关毅仁 发表于 6-10-2010 18:16:30

20年前,我做程序的时候,还没有安装的概念,全都是copy。我为了防拷贝,就在程序第一次运行的时候,将硬盘的最后一个扇区置为bad标志,然后回写5寸源盘,记录当前硬盘的柱面数磁道数。如果用源盘拷贝到新机器,磁道数不对;如果用硬盘数据拷贝到新机器,没有bad标志。不过这个方法给客户造成了不少麻烦。:P

四香油饼 发表于 7-10-2010 16:11:33

原帖由 关毅仁 于 6-10-2010 18:16 发表 http://www.freeoz.org/ibbs/images/common/back.gif
20年前,我做程序的时候,还没有安装的概念,全都是copy。我为了防拷贝,就在程序第一次运行的时候,将硬盘的最后一个扇区置为bad标志,然后回写5寸源盘,记录当前硬盘的柱面数磁道数。如果用源盘拷贝到新机器,磁道 ...

没想到原来关老师也已IT人士啊:o

四香油饼 发表于 7-10-2010 16:23:39

我记得刚刚玩计算机的时候,江湖上流传着各种“硬拷贝”软件,记得有一种将HDCOPY来着,就把软盘按扇区一个一个的复制过去。从APPLE II 到 PC-XT,一直到386时代,有了光盘后,这种加密方式才慢慢不留行了。当时真是觉得像是道和魔两边在斗法一样,各种加密/解密方法层出不穷,让人叹为观止。

我记得有一种号称无法破解的软盘加密方法,是把软盘上特定的磁道用激光打上孔,孔很小,用肉眼看不出来,但写入的数据再读出就会出错,而且每次还不一样,好像就是利用这个原理,再牛的拷贝软件也复制不了了,等等等等

dack 发表于 11-10-2010 15:33:56

油饼也是老it啊!
其实我记得当时应该可以破解的。一种是tsr截获13中断,或者等程序全部读入内存,把内存镜像写盘。以后用镜像来运行。原帖由 四香油饼 于 7-10-2010 16:23 发表 http://www.freeoz.org/ibbs/images/common/back.gif
我记得刚刚玩计算机的时候,江湖上流传着各种“硬拷贝”软件,记得有一种将HDCOPY来着,就把软盘按扇区一个一个的复制过去。从APPLE II 到 PC-XT,一直到386时代,有了光盘后,这种加密方式才慢慢不留行了。当时真是 ...

woodheadz 发表于 11-10-2010 15:37:11

原帖由 dack 于 11-10-2010 15:33 发表 http://www.freeoz.org/ibbs/images/common/back.gif
油饼也是老it啊!
其实我记得当时应该可以破解的。一种是tsr截获13中断,或者等程序全部读入内存,把内存镜像写盘。以后用镜像来运行。
当时有个工具好像叫“Ice”啥的,就是干这个事,把内存里面的程序抓到盘上来做破解:lol

GPS 发表于 11-10-2010 17:00:35

很久以前,用针在5寸盘上扎个洞,这样的话,在一个扇区里有部分可读,部分不行,而且,很难准确重现。
破解那些行业软件,常常用脱壳程序(因为这些软件加密较差),就是把if else的那个地方找到,记得有不少脱壳的软件。
再还有就是存内存了。
那时候好像不少人热衷的。

四香油饼 发表于 11-10-2010 21:57:54

原帖由 dack 于 11-10-2010 15:33 发表 http://www.freeoz.org/ibbs/images/common/back.gif
油饼也是老it啊!
其实我记得当时应该可以破解的。一种是tsr截获13中断,或者等程序全部读入内存,把内存镜像写盘。以后用镜像来运行。

俺不是it,俺现在还不会编程序呢。就是瞎玩

nilei 发表于 17-10-2010 16:18:59

3.系统启动时调用c++的解密算法解密dll到内存中,验证数字签名之后将解密后的dll镜像直接在内存中加载。
4.将加载核心的程序混淆化。在系统多个地方进行数字签名验证
我们使用C++加密算法是一个大学生的毕业设计,并非标准算法。加密和解密的代码是分离的。加密代码永远不会发布。

1. 完全没有必要用c++做这个加码解码的,c#都可以做。项目中多一个语言,维护成本上去很多。
2. 这类加密解密用一个现成库里的非对称的算法,任何中专毕业生1小时就能写完,安全性比本科生玩玩得方法好很多。

“加载核心的程序混淆化”我不是很明白什么意思,难道c#实现的别的部分的代码没有做?把原代码直接送给客户了?

青山 发表于 17-10-2010 18:18:51

现在这年代,最好是做成服务。客户端软件不但容易破解,也不利于营销。

青山 发表于 17-10-2010 18:22:52

记得当时可以靠读软盘每个扇区还是磁道的开始同步字节部分的内容做密钥。

原帖由 GPS 于 11-10-2010 17:00 发表 http://www.freeoz.biz/ibbs/images/common/back.gif
很久以前,用针在5寸盘上扎个洞,这样的话,在一个扇区里有部分可读,部分不行,而且,很难准确重现。
破解那些行业软件,常常用脱壳程序(因为这些软件加密较差),就是把if else的那个地方找到,记得有不少脱壳的 ...

青山 发表于 17-10-2010 18:26:06

读同步字节码的那个加密方法,就是对付HD-COPY的。;P

原帖由 四香油饼 于 7-10-2010 16:23 发表 http://www.freeoz.biz/ibbs/images/common/back.gif
我记得刚刚玩计算机的时候,江湖上流传着各种“硬拷贝”软件,记得有一种将HDCOPY来着,就把软盘按扇区一个一个的复制过去。从APPLE II 到 PC-XT,一直到386时代,有了光盘后,这种加密方式才慢慢不留行了。当时真是觉得像是道和魔两边在斗法一样,各种加密/解密方法层出不穷,让人叹为观止。

我记得有一种号称无法破解的软盘加密方法,是把软盘上特定的磁道用激光打上孔,孔很小,用肉眼看不出来,但写入的数据再读出就会出错,而且每次还不一样,好像就是利用这个原理,再牛的拷贝软件也复制不了了,等等等等

woodheadz 发表于 17-10-2010 22:28:54

原帖由 nilei 于 17-10-2010 16:18 发表 http://www.freeoz.org/ibbs/images/common/back.gif

1. 完全没有必要用c++做这个加码解码的,c#都可以做。项目中多一个语言,维护成本上去很多。
2. 这类加密解密用一个现成库里的非对称的算法,任何中专毕业生1小时就能写完,安全性比本科生玩玩得方法好很多。

“加载核心的程序混淆化”我不是很明白什么意思,难道c#实现的别的部分的代码没有做?把原代码直接送给客户了?
用C#做的加密解密对于破解者就像是层纸一样,用reflector之类的东西一看,什么东西都清清楚楚。解决这个问题的方法之一,就是你不太明白的混淆化(obfuscte)。
对于我们的项目,我们再加上了第二层就是C++对二进制dll的再加密。采用本科生的算法不是因为这个本科生的算法有什么了不起,恰恰相反,这个算法完成度很低,无法解密标准算法的加密结果,其加密结果也无法被标准算法解密。
我们采用这个算法的原因就是因为这个算法是独一无二的加密算法。没有我们的加密程序,解密者即便从内存中dump了二进制镜像下来,也无法自行修改出一个可以发布的版本。
另外混淆化过的加载核心程序和C++制作的反编译难度相对较大的解密程序共同构成了保卫核心代码的一道防线。破解者想要得到核心的二进制代码,必须击溃这条防线或者采用dump内存的方式才可以。
再加上第三道保障数字签名,解密者想要破解我们的系统就很不容易了。即便破解,他也无法制作广泛发布的版本。

采用这个C++算法还有一个原因,有了这个算法,老板手上就有了两个关键钥匙:加密算法和数字签名的私钥。公司内部员工想要擅自生成发布key的难度就更高了。

key 发表于 17-10-2010 22:37:10

原帖由 woodheadz 于 17-10-2010 22:28 发表 http://www.freeoz.org/ibbs/images/common/back.gif

用C#做的加密解密对于破解者就像是层纸一样,用reflector之类的东西一看,什么东西都清清楚楚。解决这个问题的方法之一,就是你不太明白的混淆化(obfuscte)。
对于我们的项目,我们再加上了第二层就是C++对二进制 ...

由于木头同学提到小弟的名字,礼貌上回一贴。;P
主要是请教几个问题:
1. 什么叫做“完成度很低”?
2. 按你的说法,我是否可以理解:只要一个加密算法的加密程序不公开,则被加密系统永远安全?
3. 如果 2 的回答为true,我再想请教,为什么这么多年来,数据加密还需要这么多研究?:loveliness:

woodheadz 发表于 18-10-2010 10:28:05

原帖由 key 于 17-10-2010 22:37 发表 http://www.freeoz.org/ibbs/images/common/back.gif


1. 什么叫做“完成度很低”?
2. 按你的说法,我是否可以理解:只要一个加密算法的加密程序不公开,则被加密系统永远安全?
3. 如果 2 的回答为true,我再想请教,为什么这么多年来,数据加密还需要这么多研究?
完成度的意思就是指这个算法的接口包装几乎等于没有完成。 实际上这个算法是我们老板自己很多年前在大学里对des算法的一次不太成功的尝试 :lol
2,3个问题在我们这个应用场景下无意义。你和nilei同学都犯了同样的小错误,你们把一个严肃的加密解密算法和一个防止破解的trick混在一起了。 没有任何手段能够绝对防止客户端软件的破解,我们所能做的就是增大破解的成本。就像楼主帖子里面所讲的例子中的第三条,你们也许会不以为然,实际上这些小花招往往十分有效。
另外,如果我们使用了标准算法,破解者只需通过破解工具找到你所使用的加密key即可彻底绕过你这到防线。而我们使用现在的做法后,破解者基本得到加密key也无法重新制作出新的授权key来(要是他能根据解密程序的二进制代码推写出加密的算法,那么我只有对他磕头了)

[ 本帖最后由 woodheadz 于 18-10-2010 10:30 编辑 ]

coredump 发表于 18-10-2010 10:44:07

原帖由 key 于 17-10-2010 21:37 发表 http://www.freeoz.org/ibbs/images/common/back.gif


由于木头同学提到小弟的名字,礼貌上回一贴。;P
主要是请教几个问题:
1. 什么叫做“完成度很低”?
2. 按你的说法,我是否可以理解:只要一个加密算法的加密程序不公开,则被加密系统永远安全?
3. 如果 2 ...
比如代码:
if RSAVerify(MD5(Key), MD5(Code), e, n) then
      ShowMessage('注册成功!')
    else
      ShowMessage('注册失败!');如果改成   
if not RSAVerify(MD5(Key), MD5(Code), e, n) then
      ShowMessage('注册成功!')
    else
      ShowMessage('注册失败!');则,虽然 MD5算法本身没有被破解,却已经变得毫无用处。所以,数据加密算法本身,和软件加解密是两件不同的事情,软件加密会大量应用一些数据加密算法,但是不等于加密算法。 木头之所以说C#不适合做这件事,是因为对于Java/C#这类语言来说,这样的代码片段很容易被找出来,然后被加个Not或者被skip掉就很容易,其实C/C++,汇编也不见得安全,用心也同样能找到这个判断点。所以才会有有加壳,脱壳,代码混淆之类的办法。好的代码混淆,往往是把机器码再不改变逻辑的情况下翻译成某种等价形式,比如判断指令CMP,可以翻译成一系列MOV指令的组合,RET可以翻译成POP, PUSH的组合等,从而使得破解更加困难。

但是,任何软件都能被破解,就像任何软件都会有BUG一样,可以证明,任何不能被破解的软件,也必然不能做其他正常有用的功能

什么是”代码混淆“:
FROM: http://zh.wikipedia.org/zh/%E4%BB%A3%E7%A0%81%E6%B7%B7%E6%B7%86

代码混淆,是将计算机程序的代码转换成一种功能上等价,但是难于阅读和理解的形式的行为。代码混淆可以用于程序源代码,也可以用于程序编译而成的中间代码。执行代码混淆的程序被称作代码混淆器。目前已经存在许多种功能各异的代码混淆器。
代码混淆的主要目的是为了保护源代码,阻止反向工程。反向工程会带来许多问题,诸如知识产权泄露,程序弱点暴露易受攻击等。使用即时编译技术的语言,如Java、C#所编写的程序更容易受到反向工程的威胁。
代码混淆的主要的方法有:
将代码中的各种元素,如变量,函数,类的名字改写成无意义的名字。比如改写成单个字母,或是简短的无意义字母组合,甚至改写成“__”这样的符号,使得阅读的人无法根据名字猜测其用途。
重写代码中的部分逻辑,将其变成功能上等价但是更难理解的形式。比如将for循环改写成while循环,将循环改写成递归,精简中间变量,等等。
打乱代码的格式。比如删除空格,将多行代码挤到一行中,或者将一行代码断成多行等等。
代码混淆器也会带来一些问题。主要的问题包括:
被混淆的代码难于理解,因此调试除错也变得困难起来。开发人员通常需要保留原始的未混淆的代码用于调试。
对于支持反射的语言,代码混淆有可能与反射发生冲突。
代码混淆并不能真正阻止反向工程,只能增大其难度。因此,对于对安全性要求很高的场合,仅仅使用代码混淆并不能保证源代码的安全。

[ 本帖最后由 coredump 于 18-10-2010 09:47 编辑 ]

woodheadz 发表于 18-10-2010 11:30:04

原帖由 coredump 于 18-10-2010 10:44 发表 http://www.freeoz.org/ibbs/images/common/back.gif
被混淆的代码难于理解,因此调试除错也变得困难起来。开发人员通常需要保留原始的未混淆的代码用于调试。
对于支持反射的语言,代码混淆有可能与反射发生冲突。
补充点内容:lol
现在C#的混淆器很多都可以在混淆时产生的名字表,这样在将来接受到来自用户的异常信息时就可以通过这个名字表将异常信息里的信息恢复成正常可读的。
混淆器会影响反射以及对外公开的接口(比如plugin接口),所以多数混淆器都可以通过XML或者程序中的元数据配置在混淆时绕过一些名称。这样就不会有问题了

key 发表于 18-10-2010 12:12:46

http://mobile.dzone.com/print/28411

这是Android环境下的一些防盗版的方案,老core不妨参考一下,
或者对于 N 记的开发有一定参考价值。不过 N 记是基于 C++ 的,
这方面有天生的优势。

原帖由 coredump 于 18-10-2010 10:44 发表 http://www.freeoz.org/ibbs/images/common/back.gif

比如代码:
if RSAVerify(MD5(Key), MD5(Code), e, n) then
      ShowMessage('注册成功!')
    else
      ShowMessage('注册失败!');如果改成   
if not RSAVerify(MD5(Key), MD5(Code), e, n) then
...

EnsignKim 发表于 18-10-2010 12:46:35

原帖由 woodheadz 于 11-10-2010 15:37 发表 http://www.freeoz.org/ibbs/images/common/back.gif

当时有个工具好像叫“Ice”啥的,就是干这个事,把内存里面的程序抓到盘上来做破解:lol

softIce, 可以用来破解注册码。

coredump 发表于 18-10-2010 13:05:16

原帖由 key 于 18-10-2010 11:12 发表 http://www.freeoz.org/ibbs/images/common/back.gif
http://mobile.dzone.com/print/28411

这是Android环境下的一些防盗版的方案,老core不妨参考一下,
或者对于 N 记的开发有一定参考价值。不过 N 记是基于 C++ 的,
这方面有天生的优势。

这些还不就是木头说的那些嘛

key 发表于 18-10-2010 14:11:17

原帖由 coredump 于 18-10-2010 13:05 发表 http://www.freeoz.org/ibbs/images/common/back.gif
这些还不就是木头说的那些嘛

对的,第一个情况木头讲过。
至于2,3,4,应该是其他方案。2是指改写Google提供的基层软件保护的库,原因是这个库可能太弱了,
这和木头说的实现自己的算法不相同。
3好象不是太有意义,但 4 估计是现在很多Java软件正在用的手段,
就是发布的软件只是软件的一部分,而在线发布另一个部分。
C#的情况我不是太了解,但Java的话,基本上和Open Source差不多,
因为 ByteCode 本身就非常Human Readable。
所以把验证代码(不是密码)写在程序中显然不难破解。比如著名的JIRA和Jive都是
死在这种低级反编译下。对于Java开发,除了可以把一部分功能放在在线服务器上动态下载外,
还有一种做法就是把Class Loader改写,通过JNI或者在线URLClassLoader装入这个特殊的
Class Loader,解密本地的内容,然后再运行。

至于改写加密算法,我就不抬扛了。

woodheadz 发表于 18-10-2010 14:45:47

原帖由 key 于 18-10-2010 14:11 发表 http://www.freeoz.org/ibbs/images/common/back.gif
至于改写加密算法,我就不抬扛了。
抬杠也不怕,大家一起在抬杠中成长,哈哈 :lol :lol

艾瑞克 发表于 18-10-2010 15:34:32

楼上和楼上的楼上也别抬杠了,破解软件大都不是从算法和密钥下手的,非对称加密本身没有问题,这只是一种基于密钥的加密技术,和基于算法的加密技术(好比说你自己写一个算法,永远不公开),从效果上来说并没什么本质区别,真正有问题的是.NET Framework,混淆看似能解决一些问题,但也不能真正的解决问题,另一方面混淆也会增加开发维护成本,特别是当你需要开放一部分接口给别人的时候。

[ 本帖最后由 ericvan76 于 18-10-2010 15:37 编辑 ]

tavor 发表于 18-10-2010 16:38:10

牛人好多...

key 发表于 18-10-2010 18:21:36

原帖由 ericvan76 于 18-10-2010 15:34 发表 http://www.freeoz.org/ibbs/images/common/back.gif
楼上和楼上的楼上也别抬杠了,破解软件大都不是从算法和密钥下手的,非对称加密本身没有问题,这只是一种基于密钥的加密技术,和基于算法的加密技术(好比说你自己写一个算法,永远不公开),从效果上来说并没什么本 ...

你说得很对。
估计这也是新的软件发布理念中更重视软件服务,而对于软件本身则更强调低价和免费的原因吧。
而通过在线业务提供、免费基础软件等手段,不是用来妨止软件被盗用或被破解,而是让盗用和破解都变得没有任何价值。

earthengine 发表于 6-11-2010 21:58:30

原帖由 woodheadz 于 18-10-2010 10:28 发表 http://freeoz.org/ibbs/images/common/back.gif

而我们使用现在的做法后,破解者基本得到加密key也无法重新制作出新的授权key来(要是他能根据解密程序的二进制代码推写出加密的算法,那么我只有对他磕头了)
如果我是破解者,我不会试图从已有的解密程序反推加密算法。相反,我会对解密程序进行分析,看看能不能得到帮助,缩短必须枚举的授权key的空间。

比如,目前流行的加密算法都有一个Padding的问题。一般解密过程中Padding出错和解密出错是两个出口,所以这就造成了可乘之机,以至于可以用一个一个字节枚举确定的方法来得到合法密文。

procoder 发表于 6-11-2010 22:45:58

破解不需要破解加密算法,只需要找到判断点就ok了,哪怕使用了native c++,一样可以破解,因为c#部分需要取出,然后判断。软件做服务是王道,但是如果软件有人破解,也挺成功了。
页: [1]
查看完整版本: 几招百试不爽的软件防破解技巧,程序员必读