e称为公钥指数(publicExponent)/加密指数(encryptionExponent)。
e选择较小的位长度在加密时会有更好的效率,普遍用数值0x10001(十进制65,537),数值3也有用到,但在某些情形显得不够安全。
5.确定整数d:
d≡e-1(modφ(n)),或写成(d*e)≡1(mod((p-1)(q-1)))。
即d是emodφ(n)的乘法逆。
通常使用扩展的欧几里德算法计算。
d称为私钥指数(privateExponent)/解密指数(decryptionExponent)。
最后密钥对用到三个数:
模n、加密指数e和解密指数d。
公钥含有n和e;而私钥含有n和d。
涉及RSA算法强度的是密钥长度,如今512位已经很少使用。
典型密钥长度,用户应使用1024位密钥,证书认证机构应用2048位或以上。
针对RSA最流行的攻击一般是基于大数因数分解。
2009年12月12日,编号为RSA-768(768bits,232digits)数被成功分解。
这一事件威胁了现通行的1024-bit密钥的安全性,普遍认为用户应尽快升级到2048-bit或以上。
三.注册算法分析
Restorator2007用RSA的签名消息来验证注册信息的有效性:
用户名就相当于消息,BomeSoftware为其计算一个SHA1值,再用私钥加密形成签名,作为注册码发送给用户。
程序运行时首先从注册表读入Name、Password和Type,如果失败,就提示输入Name和"LicenceKey",然后程序也为Name计算一个SHA1,再用公钥解密读入或输入的注册码得到另一个SHA1,两者相比较。
如果相符就表明是合法用户。
对比原版的b1709、b1729和b1747发现,密钥是相同的。
破解方面,REVENGE出过一个b1709,ZWT有b1729。
按RSA算法的原理,必然都是Keygen和Patch的组合。
由于算法没有变化,ZWT到b1746和b1747就只出Patch了。
两者的破解方法是相同的——公钥替换,但用了各自的密钥对。
私钥在Keygen里,公钥在Patch里。
REVENGE的Keygen用汇编写的,简单地用变异的UPX保护。
Patch里面,当程序需要公钥时,返回Base64编码的公钥明文。
ZWT的Keygen用C写的,用"ASProtect2.3SKEbuild06.26Beta"保护。
配合VolX的OllyDBG脚本,可脱壳正常运行,但有很多junkcodes,不便分析。
使用PE_Kill的"DecomAS-unpackerforASProtectVersion1.7Beta108.04.2011"脱壳,效果非常好。
ZWT的Patch做得和原版相似,公钥的Base64明文加密后写回原来的位置。
Keygen是好的,显得优雅而专业;当然,我们也可以粗鲁一点,不用“费那事”,直接Crack,简单且有效。
Restorator2007是用Delphi2007写的。
由于RSA算法的复杂性,注册算法采用了来自TSMInc.的两个现成组件:
AecRSA和SHA。
BomeSoftware一定是购买了TSMInc.的源码,程序中RSA组件有关私钥的代码全部去掉了。
我能找到的这两个组件的免费版最高只支持Borland的D6和CB6。
后面我会用这两个免费组件来演示制作一个Restorator2007的Keygen,先来看看REVENGE、ZWT们Patch了什么,以原版build1747和ZWT的Patch为例。
对比原版和Patch版发现,.text区段有两个地方被修改:
一段数据块和一个字节的跳转。
A.数据块对比
原版数据块VA004FB600,长度0x29A:
代码:
004FB5F0:
9A020000
004FB600:
21525B3E.2C79344B.703A3474.904C255C!
R[>,y4Kp:
4t?
L%\
004FB610:
2B527169.562A2D2C.4D762E4E.26667246+RqiV*-,Mv.N&frF
004FB620:
5B345328.45537347.2A42357A.53494754[4S(ESsG*B5zSIGT
...
004FB830:
6FD471D6.D7D87576.77DCDD7A.7BA0A1A2oquvwz{?
004FB840:
A3A44142.A7A84546.ABACADAE.4BB0B14EABEFRK+N
...
004FB880:
63646566.6768696A.6B9F6D6E.6F707172cdefghijkmnopqr
004FB890:
73677569.6A6B6C6D.6E6Fsguijklmno
Patch版数据块VA004FB600,长度0x242:
代码:
004FB5F0:
42020000
004FB600:
21526E5B.346E6F5B.2D2E4B4C.696A506D!
Rn[4no[-.KLijPm
004FB610:
2A2B5125.266E6947.2D5C5D5E.6C2B346D*+Q%&niG-\]^l+4m
004FB620:
666D4546.554D7B7C.6768515E.5B5C5C5DfmEFUM{|ghQ^[\\]
...
004FB830:
70717273.749B9C9D.9E9F6061.62636465pqrst>`abcde
004FB840:
66670042.A7A84546.ABACADAE.4BB0B14EfgBEFRK+N
...
使用这段数据的代码:
代码:
004FB5A8>/$55PUSHEBP;_Unit45.sub_004FB5A8
004FB5A9|.8BECMOVEBP,ESP
...
004FB5BE|.55PUSHEBP;/Arg1
004FB5BF|.8D55FCLEAEDX,[DWORDSS:
EBP-4];|
004FB5C2|.B800B64F00MOVEAX,Restorat.004FB600;|
004FB5C7|.E85CFFFFFFCALL;\Restorat.004FB528,DecodingPublicKey
...
原版调用004FB528返回后,EAX=00D940C8
代码:
00D940B8B2000000
00D940C82B2B3131496B3A5A7A6976384F424D57++11Ik:
Zziv8OBMW
00D940D8363766484776377A34476E54394B6B7167fHGv7z4GnT9Kkq
00D940E874417A6B556632463251454E4D536135tAzkUf2F2QENMSa5
00D940F859682B68446A2B373366456E52766B57Yh+hDj+73fEnRvkW
00D94108485270486234684474324A3331716E4DHRpHb4hDt2J31qnM
00D94118496941724957395A576343375469354DIiArIW9ZWcC7Ti5M
00D941284853505266444E59703578526678534CHSPRfDNYp5xRfxSL
00D9413838724C523436416B6F4C684B4234755A8rLR46AkoLhKB4uZ
00D94148586E486956384458554A472D6D475543XnHiV8DXUJG-mGUC
00D941585A652D6C546354796254377467355262Ze-lTcTybT7tg5Rb
00D941683346705568354D79467836627570762D3FpUh5MyFx6bupv-
00D941784159AY
这个就是BomeSoftware的Base64编码公钥了,用“:
”作分隔符:
前面"++11Ik"为加密指数e,经Base64解码后为0xC353(50003dec);后面为模n,解码后为长度0x80字节的一个大质数,表明密钥长度为1024位。
也就是说,004FB600处是加密存储的公钥,ZWT用自己的公钥将其替换。
B.代码对比
代码:
0057F577|.E8304FF8FFCALL;CRCcheck
0057F57C|.84C0TESTAL,AL
原版代码:
0057F57E7521JNZSHORTRestorat.0057F5A1
Patch版代码,75改为EB:
0057F57EEB21JMPSHORTRestorat.0057F5A1;Crack2-BypassCRCcheck
0057F580|.8D55F4LEAEDX,[DWORDSS:
EBP-C]
0057F583|.B8442B5700MOVEAX,Restorat.00572B44
0057F588|.E8BF7AE8FFCALL
0057F58D|.8B4DF4MOVECX,[DWORDSS:
EBP-C]
0057F590|.B201MOVDL,1
0057F592|.A154874000MOVEAX,[DWORDDS:
408754]
0057F597|.E8ECE3E8FFCALL
0057F59C|.E84351E8FFCALL
0057F5A1|>33C0XOREAX,EAX
0057F5A3|.5APOPEDX
0057F5A4|.59POPECX
0057F5A5|.59POPECX
0057F5A6|.64:
8910MOV[DWORDFS:
EAX],EDX
0057F5A9|.68BEF55700PUSHRestorat.0057F5BE
0057F5AE|>8B45FCMOVEAX,[DWORDSS:
EBP-4]
0057F5B1|.E87A48E8FFCALL
0057F5B6\.C3RETN
调用005044AC是什么呢?
代码:
005044AC>/$53PUSHEBX;_Unit47.sub_005044AC
005044AD|.56PUSHESI
005044AE|.8BD8MOVEBX,EAX
005044B0|.8BC3MOVEAX,EBX
005044B2|.E81D000000CALL
005044B7|.8BF0MOVESI,EAX
005044B9|.83FE85CMPESI,-7B
005044BC|.7410JESHORTRestorat.005044CE
005044BE|.8BC3MOVEAX,EBX
005044C0|.E88BFFFFFFCALL
005044C5|.3BF0CMPESI,EAX
005044C7|.7405JESHORTRestorat.005044CE
005044C9|.33C0XOREAX,EAX
005044CB|.5EPOPESI
005044CC|.5BPOPEBX
005044CD|.C3RETN
005044CE|>B001MOVAL,1
005044D0|.5EPOPESI
005044D1|.5BPOPEBX
005044D2\.C3RETN
调用005044D4从PEHeader里面读入保存的.text区段的CRC校验和,位置在文件偏移1F8(区段表起始位置)+(区段数[=9]+1)x区段项大小[=0x28]=0x1F8+0x0Ax0x28=0x388,其值为0xCECB4E86,返回到ESI;调用00504450计算整个.text区段的CRC校验和,返回到EAX,与ESI比较。
相同,AL置1,否则EAX清零。
你替换了人家的公钥,这里必须得处理。
要么把修改过的.text区段,用调用00504450跑一遍,将结果填到文件偏移0x388处,要么就硬跳。
0057F588处CALL的结果是:
"CRCcheckfailed.PleaseusetherepairfunctionorreinstallRestorator."
下面把整个过程大致走一遍。
程序入口:
代码:
005920FC>$55PUSHEBP;_Unit72.Restorator
005920FD.8BECMOVEBP,ESP
005920FF.83C4F0ADDESP,-10
00592102.B890095900MOVEAX,Restorat.00590990
00592107.E8CC50E7FFCALL
0059210C.E82B0BFEFFCALL
00592111.E8B62AE7FFCALL
...
进入00572C3C:
代码:
00572C3C>/$55PUSHEBP;URestorator.sub_00572C3C
...
00572CEE.E82185F8FFCALL;hereCALL
...
00572CFC.A184945900MOVEAX,[DWORDDS:
599484]
00572D01.8B00MOVEAX,[DWORDDS:
EAX];EAX:
TRegManager实例
00572D03.E8AC8EF8FFCALL
00572D08.A184945900MOVEAX,[DWORDDS:
599484]
00572D0D.8B00MOVEAX,[DWORDDS:
EAX]
00572D0F80781500CMP[BYTEDS:
EAX+15],0
00572D137546JNZSHORTRestorat.00572D5B
00572D15.8B0D08995900MOVECX,[DWORDDS:
599908]
00572D1B.8B09MOVECX,[DWORDDS:
ECX]
00572D1D.B201MOVDL,1
00572D1F.A1A4725400MOVEAX,[DWORDDS:
5472A4]
00572D24.E84346F0FFCALL;创建"EnterLicenseKey"窗体
00572D29.8B1510975900MOVEDX,[DWORDDS:
599710]
00572D2F.8902MOV[DWORDDS:
EDX],EAX
00572D31.A110975900MOVEAX,[DWORDDS:
599710]
00572D36.8B00MOVEAX,[DWORDDS:
EAX]
00572D38.E81F4EFDFFCALL;显示窗体,要求输入用户名和注册码
00572D3D.A184945900MOVEAX,[DWORDDS:
599484]
00572D42.8B00MOVEAX,[DWORDDS:
EAX]
00572D44.80781500CMP[BYTEDS:
EAX+15],0
00572D48.7511JNZSHORTRe