现在的位置: 首页 > 综合 > 正文

防爆破 转贴

2013年02月12日 ⁄ 综合 ⁄ 共 13623字 ⁄ 字号 评论关闭

从未公开过的方法:软件防爆破之绝招

http://www.cnsw.org/bbs/viewthread.php?tid=2056

从未公开过的方法:软件防爆破之绝招

假设A为验证代码段,爆破一般为找到A代码段中某处然后修改,可以这样做:

取随机数X为 1 或者 2

if X=1 then
再次取随机数X为 1 或者 2

    if X=1 then
    再次取随机数X为 1 或者 2

        if X=1 then
                插入代码A
        else
                插入代码A
        end if

    else
    再次取随机数X为 1 或者 2

        if X=1 then
                插入代码A
        else
                插入代码A
        end if

    end if

else
再次取随机数X为 1 或者 2

    if X=1 then
    再次取随机数X为 1 或者 2

        if X=1 then
                插入代码A
        else
                插入代码A
        end if

    else
    再次取随机数X为 1 或者 2

        if X=1 then
                插入代码A
        else
                插入代码A
        end if

    end if

end if

目的:由于取了随机数,破解者每次调试找到的代码A都不是同一处,很难全部Path8处代码A,甚至可以再多写一层随机,那就是16处。

最后说一下,这个方法是否有效我也不晓得,请哪位熟悉破解的朋友看过以后评价一下是否有效~~

种方法是有效的,但是要注意代码A本身的变形,所以重点是:
  代码A本身的变形 + 随机调用变形后的代码A

我曾经使用过,对于防止PATCH类的爆破是非常有效的。

因为我们知道,很多所谓的CRACKER都是连CRACKER本身的职业道德都缺乏,往往是拿过软件,修改几下,看起来正常就去发布了,根本不会仔细认真地测试,向上面的那种随机陷阱是可以用来让这些CRACKER出丑用的,呵呵,当然,同时再加上不定期的随机验证,可以让这个CRACKER在以后的日子里不再轻易发布你的软件的爆破产品--为什么?因为经常出丑,会害得他在解密圈里名声很臭,呵呵。。。。。

 

防爆破法术一则

http://www.cnsw.org/bbs/viewthread.php?tid=2088

设A为验证代码段

判断计算机cpu序列号(反正计算机唯一标示,随便取个什么),取其中一位赋值 X

select case X
case 0
    A
case 1
    A
case 2
    A
......
case 9
    A
end select

这样就ok啦,出来的爆破有十分之九的计算机上是不能用的~~

 

 

 

不使用CRC进行exe自校验的编程办法(转帖)

原文: http://skyfire.dns0755.net/newweb/list.asp?id=201

可执行文件的自身检测
nowcan.yeah.net  2003-9-1  老侃第一站

当我们完成一个工程,编译成可执行文件后,一般是不希望这个可执行文件被人改动的,那么这里就讲述一下这是如何做到的。

其实这并不难,只要一个API函数就可以完成,这就是MapFileAndCheckSum。这个函数的作用是1)映象文件,2)从映象文件中接受原始的校验和,它是在编译时有编译器写入文件的,3)计算文件的校验和。如果文件在编译后被改动,那么原始的校验和就会和计算得出的校验和不同,由此可知文件被改动。下面的程序中,HeadChksum是原始的校验和,Chksum是计算得出的校验和,最后比较他们是否相同来判断文件是否被改动。

程序是BCB5写的,要加上imagehlp.lib这个库,并且Project->Options->Advance Linker中要选中Calculate Checksum。这样编译器才会计算校验和并写入文件。例子程序在这里。

在VC6里又有不同,同样要连上imagehlp.lib这个库,然后在Project->Settings->Link中去掉Generate debug info和Link incrementlly选项,再选择Category组合框的Customize,去掉Use program database选项,最后在Project Options中加入"/release",一切OK!

//---------------------------------------------------------------------------

#pragma hdrstop

#include

#include

//---------------------------------------------------------------------------

#pragma argsused

int main(int argc, char* argv[])

{

DWORD HeadChksum=1,Chksum=0;

char Fn[512];

GetModuleFileName(GetModuleHandle(NULL),Fn,512);

if(MapFileAndCheckSum(Fn,&HeadChksum,&Chksum)!=CHECKSUM_SUCCESS)

{

MessageBox(NULL,"Check error!","Error",MB_OK);

}

else

{

if(HeadChksum!=Chksum)

MessageBox(NULL,"File changed.","Warning",MB_OK);

}

return 0;

}

//---------------------------------------------------------------------------

但是如果用了VCL,编译时居然说有冲突,主要是Imagehlp.h这个头文件的问题。我想最简单的解决方法是动态调用这个函数,LoadLibrary/GetProcAddress/FreeLibrary等,相信大家都会的,我就不写代码了。

 

 

 

防破解问答集(zt)

http://www.cnsw.org/bbs/viewthread.php?tid=1429

当发现自己为之工作了好几个月,甚至几年的程序被人破解的时候,所受的伤害是难以形容
的。
我作为一个共享软件作者,并不是因为我在乎那几块钱而已(我不想在这里做具体的计算,
那会使我更加难过...),不,我总是使我的程序尽可能的便宜,使包括学生和自由软件作
者在内的每个人都能用得起。
然而,我知道破解软件的魅力(如果你对程序破解者(Cracker)和黑客(Hacker)抱绝对
的不宽容态度,那么请原谅。但是我的一位同学是心理学家,我们一直在寻找其原因)。破
解一个受限制的软件程序就像解一个(有时是很狡猾)的谜语,而你可能沉迷于这种解迷的
感觉(当我发现我祖母在几个月里整天沉迷在玩字谜游戏时想起这些的)。问题是(我们现
在涉及到这种“游戏”的非法部分):程序破解者不会仅仅满足于只让自己了解他的“天赋
”。他必须传播消息,发布他的“破解” (Cracker)(看一下破解包,多数是由以下部分
组成:1、破解工具;2、简短的说明;3、一个巨大的文件,包含有似乎作者不亚于世界上
任何伟人,或者被破解的程序像所有其它程序一样无法用那脆弱的保护方式来阻止破解者破
解程序的进程的信息)。
但是现在,玩笑彻底结束了。发布这些破解包(让我们公正些:“研究其可能性“)给其他
人,散布到网站上,新闻组,邮件列表,匿名FTP,光盘,"abonnements"以及任何其它地方
,他们明显地破坏了所有那些花时间和精力在他们软件产品上的收益。虽然没有人可以说,
所有收到或者下载破解程序的人永远也不会购买。但是散布破解程序的确是犯罪,就像有人
在商场分发你车钥匙的拷贝——他是否以此赚钱又有何分别呢?
早些日子,我没有真正去花时间保护我的产品以防止被破解,但发现周围有它们的数个破解
之后。我对自己说:为什么让它如此简单? 作为一个程序员,我当然知道,不,决不!—
—程序不可能是破解不了的,而且我知道,每个有吸引力的程序都迟早会有破解(至少是盗
版或非法复制品)出现,但至少,我可以避免最糟糕的错误。
多数的高级语言程序员不再懂得汇编语言了,所以,他们使用的“保护措施“多数是很脆弱
的。我对汇编懂得也不多,所以我决定开始仔细收集防破解(Anti-Crack)的技巧。我也努
力“从另一方面努力学习”,你在这里看到的许多技巧我都是从典型的破解技术中捉摸出来
的,包括网上各种各样的破解指南和阅读甚至是由专业破解者给出程序保护技巧(他们给我
们这些技巧以给自己更大的挑战),我希望自己学得足够好,也想把我的经验在此与大家分
享,有些技巧可能已经在其它文章中有所提及,但在此列出的最为完整。许多技巧都是针对W
indows的,但他们可以被移植到其它操作系统中去。
这篇问答集是全新的,如果你觉得我遗漏了一些要点或者有用的、一个典型的Delphi程序员
可以简单的加入其程序,以加强对程序保护的技巧,请告诉我,如果你允许,我会把它加到
这里,否则我会告诉你我对它的体验。

不要问我问题,我可能无法回答:
1) 我已经提到,我对底层的东西没有什么研究;
2) 我不会把范例文件发给你,因为我没有准备过发布任何东西,如果我有一些,那么都在
这里了;
3) 最后,我不会提供任何人我发现这些技巧的连接,请记注,这是一个专注于编程的站点
,而非提供可利用的破解程序。需要更多的保护程序的信息,可以看我的DELPHI技巧页。
--------------------------------------------------------------------------------
最后,这里是:
如何使破解你程序的人感到头疼
(技巧未按其重要性排列)
--------------------------------------------------------------------------------
不要用有意义的过程名字,例如: function RegistrationOK: Boolean;//译者按:注册确

无论你在函数中编码多么奥妙和复杂,无论你相信于否一个有经验的破解者都会在10-20秒
内删除之。
作为一种选择,你可以把程序中需要的一部分代码置入其内,如果破解者禁止了这个函数,
你的程序将产生错误的结果。

不要用有意义的文件名比如License.Dat.。

用类似Asymetric(美国软件公司,代表软件Toolbook)的加密. 仅仅不寻常的文件名常常
是不够的,好的加密(编码)可以让破解者忙几个月(如果他愿意)

加上长时间延迟,当发现被自身被损坏时,不要发出警告,随后开始等待,也许是一或两天
(破解者讨厌者东西)。

加入短暂延迟,当输入口令或做其它检测时,停一到两秒钟,使穷举无法继续。简单易行,
但用处不大。

使用相互检查,在DLL和EXE中互相检查,这远谈不上安全,但可以使破解变得更困难。

在软件中使用自我修复,你知道就像纠错Modem和容错硬盘,这技术已经有许多年了,怎么
没人用在保护软件上?这方法最大的优点是:如果破解者使用反编译工具,它会见到一串无
用的列表。

修补你的软件!把代码变为每次调用不同的确认程序段,用“其人之道还治其人之身”。

把序列号放在不寻常的地方,比如数据库字段的属性中,经常听到或读到,“用一个DLL的
名字,然后把它放到系统目录里”,听的太多了,不要用哦

把序列号放到不同的地方。

不要依靠系统时间,从一些文件取得时间,比如SYSTEM.DAT,SYSTEM.DA0和BOOTLOG.TXT,
把它们和系统时间进行比较,要求它们比上次运行的时间晚(但是记住,许多用户近来在捉
千年虫)。

不要用明文字符串告诉用户:"对不起,不过...(或类似的东西)"这些是首先寻找的目标,
动态建立字符串或者加密它们。

用伪造的程序调用和字符串来灌水。

不要使用一个确认函数,每次你确认用户,把确认代码写在当前过程中。这样只是让破解者
做更多的破解工作。

使用“保留字”,当使用硬密钥或口令时,使它们看来像程序代码或者函数调用 (比如., "
73AF" 或 "GetWindowText"。这确实工作的很不错,可以迷惑一些反编译工具。

没有“禁止”特征,如果你的程序有不保存数据版本(Crapware Version),不要包含“灰”
色菜单项。没有保存项等于没有保存,就那么简单。

避免不必要的提示信息,唯一提醒用户他尚未注册的只是“关于”对话盒,此对话盒要动态
建立,以便保密。这有两个原因:许多程序员有这样的观点:多余的提示信息会在他们的顾
客中产生敌人,这是愚蠢的。一个可能是更重要的原因是:多余提示信息会引导对你代码的
反向工程而且经常直接引导至你的程序保护代码。

经常更新,频繁的更新指:经常更换代码,典型(简单)的破解只修改你的硬字节代码位置
,这可能当它还未面市已经过期了。并且保证上载礿iao卜衿鳎鼓憧梢愿玫目刂瞥绦?br /> ,人们无法找到破解所针对的旧版本。是的,这样无法防止包括旧版本和破解包盗版,如果
他们那么做了,你至少可以为把他们的硬盘挤满而做点贡献。

最后,花点时间考虑保护你自己的软件。它是否值得保护?它是否更应该改进你的软件?如
果没人用你的软件,保护也就没有意义了,不要过高估计你软件“对世界的重要性”。

--------------------------------------------------------------------------------
你可以考虑到的更多技巧
--------------------------------------------------------------------------------
用一个连续的几KB长的数学公式使任何想破解它的人精神崩溃。这使用一个密码生成器几乎
无效——阻止穷举攻击也是有效的。

小心运行时刻库!当写BETA版时,完全使用之,在正式版中重写部分函数,这至少可以使破
解者的生活更艰苦些。

毁坏结果,毁坏结果有时是保护程序的有效措施。
例如:想象一个图表程序,或者类似的程序,只是禁止打印然后根据一些注册码恢复打印是
最常见的毁坏结果的程序。允许你打印。当产生要打印数据结构时,用某种方式破坏之,在
打印前根据注册码或其它东西恢复。甚至,让破坏更奥妙,假设你有一个饼形图要打印,不
改变任何东西,但加入一些不大的随机数值在你的数据中——这样就破坏了。图表看上去“
不是很糟”,但是无论如何将无法使用(比如,如果是按20%的随机次序改变的)发现这样
的保护,如果这和注册码相关联,无疑会使破解需要更对的时间,一是必须深入你内部的数
据结构并找到可怕的破坏和恢复数据代码。

陷阱,一个我不太肯定,但听说有程序使用的方法:用CRC校验你的EXE文件,如果它被改变
了,不要显示典型错误信息,等一天,然后用意思含糊的错误代码通知用户,当他们和你联
系并告之错误代码时,你知道,是因为被破解了。记注:这样的陷阱可能被病毒或下载错误
所触发,当你谴责可能是你未来的客户前,先考虑所有可能性。

不要依赖EXE压缩程序,几乎任何EXE压缩程序(Shrinker, WWPack32, NeoLite ——和所有
著名的压缩软件)都有反压缩程序,所以,压缩程序的保护能力至少支持可配置的编码。以
上(和其它)压缩程序的反压缩软件并未广泛流传,但是,不要依赖那些软件作为你程序仅
有的一个“保护”。
--------------------------------------------------------------------------------
高级技巧——从汇编来的奇想
--------------------------------------------------------------------------------
rcr/rcl 把戏
如果RCR/RCL执行某值,对于破解者来说是痛苦的——在不知道最初操作时转送标志(Carry
Flag)的值的情况下,你无法逆转之或否定其作用,如果转送标志是由一些其它烦琐的关
键操作所产生的话,那么你几乎胜利了。

到处贴条件转移
条件跳转对于反向工程来说并不有趣。没有循环,只是跳转,作为有条件的路障,包括你那
些可爱的KEY处理代码。这样,没有简单的反向操作可以执行。

使用部分代码作为奇妙的数字表。
(更适合评论部分)如果你像多数的破解者或喜欢用SOFT-ICE(一个流行的破解工具)改东
西,你无法想象这会有多恼人,

和破解者斗智
这部分很有趣:-) 贴上连续的NOP,就像你在做自我代码修改(天啊,什么乱七八糟的,NOP
?哈!自我代码修改!白痴会花三年去捉摸那些本来该是什么东西)。混乱的注释代码。把
代码分成小块,把它们遍布在可执行代码中,在它们中间使用(最好是有条件的)跳转。

提早发现SoftIce.。
现在搞垮计算机,你可以搞垮奔腾或奔腾MMX计算机甚至不需要VXD,可以用操作码: F0 0F
C7 C8 (非法的带锁定前缀的 cmpxchg8b 指令). 处此之外, 我们必须采取真正的措施:使
用VXD把CPU带出保护模式。Windows 不喜欢那样,奇迹?另一方面,不要浪费太多的时间去
写破坏反汇编程序或调试的代码。那没用,相信我,有人写了那些东西,另一些人立刻会有
办法绕过它,所以,把你的兴趣转移到更重要的地方——那些容易且很快见效的措施,就像
上面的技巧。
--------------------------------------------------------------------------------
针对DELPHI控件的破解
--------------------------------------------------------------------------------
让我们了解一些关于Borland公司新开发工具的内核吧。这些知识会使我们加快破解的速度
,当然也使那些共享软件程序员更小心的使用Delphi,轻易的把他们的“秘密”暴露在那些
好奇的目光下。
VCL是指Visual Component Library(可视化组件库),它近来被Borland的可视化编程工具
所使用,比如Delphi和C++Builder。
这些环境使用特有的资源格式,在Resource Workshop(Borland编辑资源的一个工具)中显
示为“RCDATA'”。这些资源中含有Delphi所谓的窗体(Forms),窗体是程序的窗口(Wind
ows)。所有对窗口的设计的信息都包含内,当一个典型的Delphi程序开始运行时,其初始
化代码建立这种窗体,并从资源中读取所需要的信息。有时,这种读取会被推迟——不常用
的窗体在需要时才被建立和删除。这样的机制是Delphi的最大优势也是其最大的缺点。它大
大提高了程序设计的速度,但是对于整个应用程序,它减慢了程序被调用时的速度

这部分中真正有趣的是:例程(被用来响应用户界面的窗体的元素)的地址是按名字邦定的
。所以只要知道这些名字,我们就可以知道所需要的地址。
如果你曾经破解过我的Delphi程序,你一定对那些烦琐的库之间的调用,比如API调用断点
(breakpoint)和类似“do xx”的代码。
[讨论一个十分有名的用Delphi写的应用程序] 就像你将见到的那样,我彻底的破解了它,
而且十分轻松。我第一次安装以后一个星期后,我发现了一条令人厌恶的信息——“你的测
试已经过期”。
首先要做的是使用资源或窗体探测(SPY)工具收集有关目标EXE文件的有关信息。你也许会
想到去查看TVALIDATORDLG——很明显,用户名和注册码是由此输入的。但是你会发现那只
是一个简单的对话盒,真正的工作是由其调用者TSPLASHFORM来完成的。这是个恼人的窗口
,它在程序关闭、按“关于”按钮和程序开始部分不断出现。
你可以选择TsplashForm并且以文本格蔶iao鄄熘9赜诎磁ィ˙utton)和标签(Label)的许
多信息都将被很清楚的显示。让我们注意以下部分(接近最后):

object RegButton: TButton
Left = 200
Top = 176
Width = 97
Height = 25
Caption = 'Register'
TabOrder = 1
OnClick = RegButtonClick
end

这是什么?这是带有“注册”标题的按钮。你可以看到它的大小,位置......和一个有启发
性的名字——“OnClick”。 “OnClick”告诉我们当用户按注册按钮时所调用的例程,当
我们有了名字(Name),我们可以搜索例程的地址。这是因为例程是和按钮以名字(Name)邦定
的。
使用一个十六进制编辑器观察"RegButtonClick",我发现了两次,第二个是资源本身,第一个
是在地址表(Address Table)中的。

000A4990 ____ ____ ____ BC57 4A00 0E52 6567 4275 ______.WJ..RegBu

000A49A0 7474 6F6E 436C 6963 6B__ ____ ____ ____ ttonClick_______

现在,观察名字(Name)前那写神奇的数字,有一个字节('0E')指出了"RegButtonClick"
的长度(14 个字符)。而且,在此之前有其地址:004ABC57。

有的反汇编程序会以为文件太长,并且不能正确反汇编这部分——然而,使用特殊的工具,
我们可以在此停止,对了,就停在我们按按钮的部分。
这些会使你发现一个调用(CALL)。跟踪之,你会在44ECC8发现一个“标准栈框架(standa
rd stack frame)”:

0044ECC8 55 push ebp
0044ECC9 8BEC mov ebp, esp
这是一种程序员所写的,在高级例程开始部分所需要的东西。我们已经避开了一长串由Wind
ows通知(Notification)所产生的VCL库调用,来到了正确的位置。
在此,你可以方便的用设置断点的方法来测试一些调用——你会发现它们是用来显示要求输
入用户名和口令的对话盒。然后,注册码是由用户名和用户的输入比较所产生的。你可以输
入你所选择的用户名,和任何东西作为注册码,在BPX到44ED69之后,一个调用一个例程用
来比较两个字符串。D EDX会显示你输入(冒牌)的注册码,EAX会显示正确的注册码,简单
吧?初学者只需10分钟就可以完成,

如何避免被类似的程序破解?
阅读我以上的技巧。最基本的是不要用由双击按钮或有属性监视器(Object inspector.)
生成默认的方法,在程序的其它部分写代码,最好是在另外的模板中,然后用类似以下的代
码与按钮关联:

RegButton.OnClick := RegButtonClick;

当然你需要在窗体建立时(被调用前)执行这段代码,最好是被一些无关的例程所调用,当
然这远远不能防止你的程序被破解,但至少不会像你刚才看到的那样容易。

--------------------------------------------------------------------------------
关于注册码的提示
(如果你无法避免它)
--------------------------------------------------------------------------------
在安全,可行性,可编程性和最终用户的头痛间寻求平衡。
太长的,无字母的注册码可能造成连续的输入错误。考虑要求输入确认域(多数是口令),
或者至少提供一个“不固定”的注册码输入域,以便用户可以每次重写注册码,也许最后正
确的输入了。许多人会仅仅“瞥一眼”以比较输入的注册码和他们所收到E-Mail里的注册好
,他们最终认为,他们输入了正确的注册码。但是字体太小或者他们懒得注意到底“I”和
“1”被交换了位置(就像'l83jjd_0)pH1lTe' )。
根据不同用户的反馈,注册码输入区必须无限制的接受任何长度的信息。不要让破解者了解
你的注册码的类型——如果你采取“在线确认(online-verification)”并显示它有10个
字符长或只接受大写字母将给予他们帮助——不要这样做!
计算潜在用户的数量!没有比这样的事更坏的了:你把用户数限制在9,999,你不希望有第
10,000个用户,因为如此你就必须升级你的注册码以满足这第1,000个用户。
如果你的注册码有10位,可能有10^10个注册码。但是,你的应用程序可能只允许10^4(10
,000)个用户,你必须采取某种算法使10^4个用户每人一个得到10^10个注册码中一个。这
保护了用户和你的应用程序本身受到穷举攻击(就像一个使用VXD的宏播放器那样)。如果
只有10^4个用户,而你定义了10^9个合法的注册码,那么平均每试10次,就会有一个“合法
”的注册码。然而,在预期只有10^4的情况下,平均每10^6次才会成功。即使是使用高速的
计算机和极快的宏播放器(击键模拟输入注册码),要在10^6中寻找到需要的注册码所花费
的时间也是无法计算的。
从用户名(User name)到注册码(Registeration code)不应该只有简单的运算,它必须
是有既精通数学又精通汇编语言的人用汇编语言实现(记注,Delphi仍然允许你直接使用汇
编(ASM)代码)!然后,检查你的操作,绘制流程图,了解它是如何工作的。要彻底了解
你自己的工作,特别是它的不足之处。
要有创新意识,不要用任何看起来简单、迅速、有效的东西,除非你信奉类似爱因斯坦的相
对论的学说。你的方法的确是简单,也的确是迅速,但是绝对不是有效,的确是容易被破解
。我十分抱歉,我并非天才,没有找到一种行之有效的保护方案能维持太长时间。

只是些想法

Richey

摘自《hubdog未经证实的葵花宝典

返回:
ElGamal算法

  ElGamal算法既能用于数据加密也能用于数字签名,其安全性依赖于计算有限域上离散对数这一难题。
密钥对产生办法。首先选择一个素数p,两个随机数, g 和x,g, x < p, 计算 y = g^x ( m
od p ),则其公钥为 y, g 和p。私钥是x。g和p可由一组用户共享。
ElGamal用于数字签名。被签信息为M,首先选择一个随机数k, k与 p - 1互质,计算

a = g^k ( mod p )
再用扩展 Euclidean 算法对下面方程求解b:

M = xa + kb ( mod p - 1 )

签名就是( a, b )。随机数k须丢弃。
验证时要验证下式:

y^a * a^b ( mod p ) = g^M ( mod p )

同时一定要检验是否满足1<= a < p。否则签名容易伪造。
ElGamal用于加密。被加密信息为M,首先选择一个随机数k,k与 p - 1互质,计算

a = g^k ( mod p )
b = y^k M ( mod p )

( a, b )为密文,是明文的两倍长。解密时计算

M = b / a^x ( mod p )

ElGamal签名的安全性依赖于乘法群(IFp)* 上的离散对数计算。素数p必须足够大,且p-1至
少包含一个大素数
因子以抵抗Pohlig & Hellman算法的攻击。M一般都应采用信息的HASH值(如SHA算法)。ElGa
mal的安全性主要依赖于p和g,若选取不当则签名容易伪造,应保证g对于p-1的大素数因子
不可约。D.Bleichenbache“GeneratingElGamal Signatures Without Knowing the Secret
Key”中提到了一些攻击方法和对策。ElGamal的一个不足之处是它的密文成倍扩张。

美国的DSS(Digital Signature Standard)的DSA(Digital Signature Algorithm)算法是经E
lGamal算法演
变而来。

 

 

如何用简单方法防止破解

http://www.cnsw.org/bbs/viewthread.php?tid=1063

在Debug的手册里可以看到Debug工具的局限. 第一个局限是只能下4个内存区域的断点,每个断点不能控制超过两个字节,这样内存断点不能控制超过16个字节的区域. 第二个局限是对多线程只能同时跟踪一个线程.

假设你的注册部分有300行,你可以分成30个inline函数调用或MACRO(一定要inline),func1(),func2()... func30(). 将他们随意放到程序的各个部分,一定不能放在一起(自己能找到就行了)。不要用Memcpy等常用系统调用拷贝注册码,近可能自己写,像Memcpy很好写,性能差点无所谓。经过编译后inline函数展开,注册部分和其他代码混在一起,他要写出注册机就像大海里捞针,在几十万甚至上百万汇编代码里找出有用的注册部分。

利用Debug的第一个局限最重要的一点是:注册码也不要放在一起,假设你的注册码是12位,千万不要用一个12位的数组放注册码,你可以在程序的不同位置定义12个全局字符变量,每个放一位,这样注册码在内存就不连续了。最好再加密处理一下(简单的字符异或就可以),验证时再解密。也不要用连续内存保存验证用到的变量,尽量将用到的验证临时变量分散定义在程序的不同处,再在验证中,不断转移一些值到其他变量中,对付暴力和Loader会比较有效。

没有必要用复杂的加密算法,更容易成为追踪的目标。只要你将注册部分隐藏的足够好,也没有漏洞,你花1天写的加密算法,破解者可能会花100-1000倍的时间破解。大部分人都会放弃。

你将注册做在一起,就像将你的财宝放在现代保险箱里,虽然非常坚固难以解密,对于开锁高手两分钟就打开了。

而古代海盗用的方法是将财宝埋在海岛上,这样没有藏宝图,对应高手和低手都只有一条路,拿一把铁撬挖,可能要挖一生。程序有那么多代码,反编译出来可能超过百万行,你将注册部分藏在里面,藏的好就如同将财宝埋在海岛里。那些所谓的Crackme只是给高手玩儿的现代保险箱而已,用原始的方法可以达到同样效果。

1. 读完注册码后不要立刻检查注册码,因为读注册码肯定用到系统调用,系统调用附近很容易下断点。先放到内存作为全局变量,然后你可以在程序的任何部分,任何时候,读注册码,读内存是没有任何系统调用的.

2. 两种办法处理在内存的注册码,
  一种方法是在检查前分散隐藏注册码,这样他们无法从内存中搜索到注册码出现的位置,因为他们会在注册码出现位置附近下断点。
  还有一种方法是正好相反,你可以在读到注册码后,多次将注册码在内存(用Malloc分配多处)的各个位置做大量拷贝,这最多浪费一些内存。16Bits的注册码做10000份拷贝也只用160K内存。如果不用Malloc分配这些内存,那么最好和其他程序使用的全局变量交互混在一起(这样即使破解者用HEX 编辑器打开并搜索你的程序中使用那部分内存的代码,也无法将正常程序数据和注册码区分出来). 你不要立刻检查注册码,10000份拷贝你只要以后随机找一份用就行了,破解的人不知道你正在用的是那一个. 同时你可以不断生成一些假的读取内存注册码的调用干扰破解者。这种方法对程序的性能影响微不足到,只是浪费一点内存。因为Debug对内存下断点的局限,这种情况他要下断点,累死的就是破解的人了.

3. 程序多处做CRC校验文件大小检查,发现不对就退出。一定要多处检查,不能只检查一次。

4. 用inline函数将注册部分分成许多小块,分散到程序各处运行。最好能放在不同的线程中运行. 检查结束不要给任何提示,在程序中的内存中做一个标志即可,提示信息要延迟一段时间出现,不要让破解者通过提示信息找到标志位置或检查结束位置,否则前功尽弃。当然也可以象上面那样做10000个标记,随机用一个,这时你不用担心破解者知道标记的位置.而且标记最好不要用0或1,可以用一个貌似随机的值作为注册成功的标记,如何产生这个随即值只有你自己知道.

什么算法无所谓,最终目的就是让破解者的作用发挥不出来。和古代海岛藏宝一样,你只要把检查痕迹很好擦掉分散,破解高手的用处就发挥不出来。破解者玩的Crackme就是保险箱,如果是开锁高手,目标明确总能打开,不行还可以用炸药。但到海盗的藏宝地点,任何开锁高手都没有用。

这种方法用的好的结果是你容易创造检查注册码的方法,自我创造发挥的余地很大,而对破解者会很麻烦,他搞不清楚你在干什么,你只要让破解者感觉象是蒙着眼睛走迷宫或者在猜没有谜题的谜语就行了. 而且对你来说更换算法也很容易,因为可能根本没有算法,只有谜语和迷宫。要充分利用程序反汇编后代码多这个特点,除了读注册码的时刻,其他时候根本没有系统调用,除了内存,根本无处下断点. 而你使用复杂的加密算法通常的结果是你麻烦,破解者很容易,因为各种加密算法都已经研究透了,而且用复杂的加密算法的调用或系统调用立刻暴露你检查注册码的位置,为暴力破解提供了方便。

我和很多人一样,也是不会汇编语言,而且程序一出来就被0day破解,而且几乎每一个版本它们都要破解. 苦于不会汇编,也不太了解破解流程,只好去看SOFTICE的手册,想了这么一个简单的方法. 0day虽然它们经验丰富也能破解,而且似乎也逐渐了解和改进对我的程序的破解. 但许多破解是坏的,根本不能用. 而且就是被破解后,只要将这些inline调用和全局内存变量的位置稍微变一变(大概只需要2-3个小时),它们下一次的破解又是坏的. 而且我还没有完全使用上面的方法,例如我还没有做10000份的内存拷贝或10000份的标记. 因为只是简单的用inline和将注册信息与其他全局变量混在一起,现在就已经够了,0day的暴力破解就经常会破坏正常程序数据.

抱歉!评论已关闭.