首页
社区
课程
招聘
[原创]Restorator 2007注册的RSA算法分析及RCData中文处理补丁
发表于: 2012-7-30 18:58 16011

[原创]Restorator 2007注册的RSA算法分析及RCData中文处理补丁

2012-7-30 18:58
16011

  Restorator 2007是不错的工具,现在还有很多人在用。它同样存在文章“eXeScope, XNResourceEditor & IDR 之Form中文显示补丁”中提到的问题,就对其做了相似处理。这部分比较简单,让人更感兴趣的是它的注册算法,现整理出来分享给大家。

  目录:
  一.关于版本
  二.RSA算法
  三.注册算法分析
  四.用TSM Inc.的组件制作Keygen
  五.TRSA与其他RSA实现的对比
  六.附件列表

一.关于版本
  Bome Software的官方下载目前仍然是2007年七月发布的30天试用版:Update 2 (Build 1747)。
  试用版的限制:30天后不能再使用;保存的菜单、对话框和版本等资源中有"Patched with Restorator"字样;缺少ResPatcher和Grab Resources两个工具。试用版中ResPatcher Wizard可以走到最后一步,由于资源中没有EXE Stub,无法生成ResPatcher的执行档。当然也没有地方输入注册信息。
  Build 1747正式版的原版很难找,事实上我还真没找到,只找到Build 1709和Build 1729(见附件)的正式版安装包。好在Bome Software提供了Restorator2007_Full_1747_Patch.exe。这个Patch只适用于官方的1709或1729,任何破解或汉化版都无法升级到1747。
  在帖子“Restorator 2007 3.70 build 1747 Full”中有ZWT的b1747英文正式版破解,只有一个执行档Restorator.exe和注册信息,帖子中还提到1747修复了哪些Bugs。
  汉化方面,有West King(韦斯特·金)的b1729Digidea的b1747。和正式版的原版一样,采用Inno Setup安装包,但在安装时会自动在注册表中写入注册信息。
  另外还流传有一个“Restorator 2009 Bulid 1807”的版本,显示版本号4.0.0.1807。但它实际上是b1709:资源中残留有3.7.0.1709字样,执行档Restorator.exe中经加密的公钥位置在VA 004E7500处,与原版b1709位置相同。并且这个版本、WestKing.b1729和Digidea.b1747都源自ZWT的破解,注册信息在这些个版本是通用的。

二.RSA算法
  关于RSA算法,更详细的信息请参阅“RSA (algorithm) - Wikipedia, the free encyclopedia”或“RSA加密演算法 - 维基百科,自由的百科全书”。为了下面叙述方便,大致摘编于下:
  RSA加密演算法(public-key cryptography)是一种非对称加密演算法,在公钥加密标准和电子商业中RSA被广泛使用,比如超文本传输安全协议(HTTPS - Hypertext Transfer Protocol Secure)和数字签名等。该算法由Ron Rivest、Adi Shamir和Leonard Adleman于1976年一起首次提出,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏首字母的组合。
  RSA包括一个公钥(Public Key)和一个私钥(Private Key)。顾名思义,公钥是公开的,由他人使用;私钥则一定不能泄露,是持有者的身份证明。通常,公钥用于加密消息,用公钥加密的信息只能用私钥进行解密。
  但是,这里有个问题。假设甲向乙发送加密信息,因为任何人都可使用乙的公钥来加密,虽然乙可用自己的私钥正确解密,但无法确认发送者一定就是甲。
  RSA的另一个功能——签名消息(Signing Messages)——解决了这个问题,但公钥和私钥的用法正好颠倒过来。
  还是假设甲想给乙传递消息。首先,甲为消息产生一个消息文摘(Message Digest),通常就是计算消息的散列值(Hash)。然后甲用私钥加密这个散列值生成一个签名(Signature),并将这个签名附在消息的后面。这个签名只有用甲的公钥才能被解密。乙获得这个消息后用甲的公钥解密这个签名,然后将这个数据与他自己为这个消息计算的散列值相比较。假如两者相符的话,那么他/她就可以知道发送人持有甲的私钥,以及这个消息在传播路径上没有被篡改过。

  RSA算法的关键在于生成密钥对,过程涉及到数论里的很多东西,不晓得是否还有人记得华罗庚、陈景润等的名字。RSA算法的密钥按以下规则生成:
1. 选择两个不同的质数/素数p和q。整数p和q为安全起见,应随机选择,并有相同的位长度。
2. 计算 n = pq。n是用作公钥和私钥的模(modulus)。
3. 计算 φ(n) = (p–1)(q–1),这里φ是欧拉的totient函数。
4. 选择一个整数e:1 < e < φ(n),并且e和φ(n)的最大公约数为1,即e和φ(n)为互质。e称为公钥指数(public Exponent)/加密指数(encryption Exponent)。e选择较小的位长度在加密时会有更好的效率,普遍用数值0x10001(十进制65,537),数值3也有用到,但在某些情形显得不够安全。
5. 确定整数d:d ≡ e[sup]-1[/sup](mod φ(n)),或写成(d * e) ≡ 1 (mod ((p-1)(q-1)) )。即d是e mod φ(n)的乘法逆。通常使用扩展的欧几里德算法计算。d称为私钥指数(private Exponent)/解密指数(decryption Exponent)。
  最后密钥对用到三个数:模n、加密指数e和解密指数d。公钥含有n和e;而私钥含有n和d。

  涉及RSA算法强度的是密钥长度,如今512位已经很少使用。典型密钥长度,用户应使用1024位密钥,证书认证机构应用2048位或以上。针对RSA最流行的攻击一般是基于大数因数分解。2009年12月12日,编号为RSA-768(768 bits,232 digits)数被成功分解。这一事件威胁了现通行的1024-bit密钥的安全性,普遍认为用户应尽快升级到2048-bit或以上。

三.注册算法分析
  Restorator 2007用RSA的签名消息来验证注册信息的有效性:用户名就相当于消息,Bome Software为其计算一个SHA1值,再用私钥加密形成签名,作为注册码发送给用户。程序运行时首先从注册表读入Name、Password和Type,如果失败,就提示输入Name和"Licence Key",然后程序也为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写的,用"ASProtect 2.3 SKE build 06.26 Beta"保护。配合VolX的OllyDBG脚本,可脱壳正常运行,但有很多junk codes,不便分析。使用PE_Kill的"DecomAS - unpacker for ASProtect Version 1.7 Beta1 08.04.2011"脱壳,效果非常好。ZWT的Patch做得和原版相似,公钥的Base64明文加密后写回原来的位置。
  Keygen是好的,显得优雅而专业;当然,我们也可以粗鲁一点,不用“费那事”,直接Crack,简单且有效。

  Restorator 2007是用Delphi 2007写的。由于RSA算法的复杂性,注册算法采用了来自TSM Inc.的两个现成组件:AecRSA和SHA。Bome Software一定是购买了TSM Inc.的源码,程序中RSA组件有关私钥的代码全部去掉了。我能找到的这两个组件的免费版最高只支持Borland的D6和CB6。后面我会用这两个免费组件来演示制作一个Restorator 2007的Keygen,先来看看REVENGE、ZWT们Patch了什么,以原版build 1747和ZWT的Patch为例。
  对比原版和Patch版发现,.text区段有两个地方被修改:一段数据块和一个字节的跳转。

  A. 数据块对比
  原版数据块VA 004FB600,长度0x29A:

004FB5F0:                                      9A 02 00 00
004FB600:  21 52 5B 3E.2C 79 34 4B.70 3A 34 74.90 4C 25 5C  !R[>,y4Kp:4t?L%\
004FB610:  2B 52 71 69.56 2A 2D 2C.4D 76 2E 4E.26 66 72 46  +RqiV*-,Mv.N&frF
004FB620:  5B 34 53 28.45 53 73 47.2A 42 35 7A.53 49 47 54  [4S(ESsG*B5zSIGT
...
004FB830:  6F D4 71 D6.D7 D8 75 76.77 DC DD 7A.7B A0 A1 A2  o q   uvw  z{?
004FB840:  A3 A4 41 42.A7 A8 45 46.AB AC AD AE.4B B0 B1 4E    AB  EF   RK +N
...
004FB880:  63 64 65 66.67 68 69 6A.6B 9F 6D 6E.6F 70 71 72  cdefghijk mnopqr
004FB890:  73 67 75 69.6A 6B 6C 6D.6E 6F                    sguijklmno


  Patch版数据块VA 004FB600,长度0x242:
004FB5F0:                                      42 02 00 00
004FB600:  21 52 6E 5B.34 6E 6F 5B.2D 2E 4B 4C.69 6A 50 6D  !Rn[4no[-.KLijPm
004FB610:  2A 2B 51 25.26 6E 69 47.2D 5C 5D 5E.6C 2B 34 6D  *+Q%&niG-\]^l+4m
004FB620:  66 6D 45 46.55 4D 7B 7C.67 68 51 5E.5B 5C 5C 5D  fmEFUM{|ghQ^[\\]
...
004FB830:  70 71 72 73.74 9B 9C 9D.9E 9F 60 61.62 63 64 65  pqrst>    `abcde
004FB840:  66 67 00 42.A7 A8 45 46.AB AC AD AE.4B B0 B1 4E  fg B  EF   RK +N
...

  使用这段数据的代码:
004FB5A8 >/$ 55                  PUSH EBP                                ; _Unit45.sub_004FB5A8
004FB5A9  |. 8BEC                MOV EBP,ESP
...
004FB5BE  |. 55                  PUSH EBP                                ; /Arg1
004FB5BF  |. 8D55 FC             LEA EDX,[DWORD SS:EBP-4]                ; |
004FB5C2  |. B8 00B64F00         MOV EAX,Restorat.004FB600               ; |
004FB5C7  |. E8 5CFFFFFF         CALL <Restorat._Unit45.sub_004FB528>    ; \Restorat.004FB528, Decoding Public Key
...

  原版调用004FB528返回后,EAX=00D940C8
00D940B8                                      B2 00 00 00
00D940C8  2B 2B 31 31 49 6B 3A 5A 7A 69 76 38 4F 42 4D 57  ++11Ik:Zziv8OBMW
00D940D8  36 37 66 48 47 76 37 7A 34 47 6E 54 39 4B 6B 71  67fHGv7z4GnT9Kkq
00D940E8  74 41 7A 6B 55 66 32 46 32 51 45 4E 4D 53 61 35  tAzkUf2F2QENMSa5
00D940F8  59 68 2B 68 44 6A 2B 37 33 66 45 6E 52 76 6B 57  Yh+hDj+73fEnRvkW
00D94108  48 52 70 48 62 34 68 44 74 32 4A 33 31 71 6E 4D  HRpHb4hDt2J31qnM
00D94118  49 69 41 72 49 57 39 5A 57 63 43 37 54 69 35 4D  IiArIW9ZWcC7Ti5M
00D94128  48 53 50 52 66 44 4E 59 70 35 78 52 66 78 53 4C  HSPRfDNYp5xRfxSL
00D94138  38 72 4C 52 34 36 41 6B 6F 4C 68 4B 42 34 75 5A  8rLR46AkoLhKB4uZ
00D94148  58 6E 48 69 56 38 44 58 55 4A 47 2D 6D 47 55 43  XnHiV8DXUJG-mGUC
00D94158  5A 65 2D 6C 54 63 54 79 62 54 37 74 67 35 52 62  Ze-lTcTybT7tg5Rb
00D94168  33 46 70 55 68 35 4D 79 46 78 36 62 75 70 76 2D  3FpUh5MyFx6bupv-
00D94178  41 59                                            AY

  这个就是Bome Software的Base64编码公钥了,用“:”作分隔符:前面"++11Ik"为加密指数e,经Base64解码后为0xC353(50003dec);后面为模n,解码后为长度0x80字节的一个大质数,表明密钥长度为1024位。
  也就是说,004FB600处是加密存储的公钥,ZWT用自己的公钥将其替换。

  B. 代码对比
0057F577  |. E8 304FF8FF         CALL <Restorat._Unit47.sub_005044AC>    ; CRC check
0057F57C  |. 84C0                TEST AL,AL
  原版代码:
0057F57E     75 21               JNZ SHORT Restorat.0057F5A1
  Patch版代码,75改为EB:
0057F57E     EB 21               JMP SHORT Restorat.0057F5A1             ; Crack2 - Bypass CRC check
0057F580  |. 8D55 F4             LEA EDX,[DWORD SS:EBP-C]
0057F583  |. B8 442B5700         MOV EAX,Restorat.00572B44
0057F588  |. E8 BF7AE8FF         CALL <Restorat.System.LoadResString>
0057F58D  |. 8B4D F4             MOV ECX,[DWORD SS:EBP-C]
0057F590  |. B2 01               MOV DL,1
0057F592  |. A1 54874000         MOV EAX,[DWORD DS:408754]
0057F597  |. E8 ECE3E8FF         CALL <Restorat._Unit3.Exception.Create>
0057F59C  |. E8 4351E8FF         CALL <Restorat.System.@RaiseExcept>
0057F5A1  |> 33C0                XOR EAX,EAX
0057F5A3  |. 5A                  POP EDX
0057F5A4  |. 59                  POP ECX
0057F5A5  |. 59                  POP ECX
0057F5A6  |. 64:8910             MOV [DWORD FS:EAX],EDX
0057F5A9  |. 68 BEF55700         PUSH Restorat.0057F5BE
0057F5AE  |> 8B45 FC             MOV EAX,[DWORD SS:EBP-4]
0057F5B1  |. E8 7A48E8FF         CALL <Restorat.System.TObject.Free>
0057F5B6  \. C3                  RETN

  调用005044AC是什么呢?
005044AC >/$ 53                  PUSH EBX                                ; _Unit47.sub_005044AC
005044AD  |. 56                  PUSH ESI
005044AE  |. 8BD8                MOV EBX,EAX
005044B0  |. 8BC3                MOV EAX,EBX
005044B2  |. E8 1D000000         CALL <Restorat._Unit47.sub_005044D4>
005044B7  |. 8BF0                MOV ESI,EAX
005044B9  |. 83FE 85             CMP ESI,-7B
005044BC  |. 74 10               JE SHORT Restorat.005044CE
005044BE  |. 8BC3                MOV EAX,EBX
005044C0  |. E8 8BFFFFFF         CALL <Restorat._Unit47.sub_00504450>
005044C5  |. 3BF0                CMP ESI,EAX
005044C7  |. 74 05               JE SHORT Restorat.005044CE
005044C9  |. 33C0                XOR EAX,EAX
005044CB  |. 5E                  POP ESI
005044CC  |. 5B                  POP EBX
005044CD  |. C3                  RETN
005044CE  |> B0 01               MOV AL,1
005044D0  |. 5E                  POP ESI
005044D1  |. 5B                  POP EBX
005044D2  \. C3                  RETN

  调用005044D4从PE Header里面读入保存的.text区段的CRC校验和,位置在文件偏移1F8(区段表起始位置) + (区段数[=9]+1) x 区段项大小[=0x28] = 0x1F8 + 0x0A x 0x28 = 0x388,其值为0xCECB4E86,返回到ESI;调用00504450计算整个.text区段的CRC校验和,返回到EAX,与ESI比较。相同,AL置1,否则EAX清零。
  你替换了人家的公钥,这里必须得处理。要么把修改过的.text区段,用调用00504450跑一遍,将结果填到文件偏移0x388处,要么就硬跳。
  0057F588处CALL <Restorat.System.LoadResString>的结果是:"CRC check failed. Please use the repair function or reinstall Restorator."

  下面把整个过程大致走一遍。程序入口:
005920FC > $ 55                  PUSH EBP                                   ; _Unit72.Restorator
005920FD   . 8BEC                MOV EBP,ESP
005920FF   . 83C4 F0             ADD ESP,-10
00592102   . B8 90095900         MOV EAX,Restorat.00590990
00592107   . E8 CC50E7FF         CALL <Restorat._Unit2.@InitExe>
0059210C   . E8 2B0BFEFF         CALL <Restorat.URestorator.sub_00572C3C>
00592111   . E8 B62AE7FF         CALL <Restorat.System.@Halt0>
...

  进入00572C3C:
00572C3C >/$ 55                  PUSH EBP                                   ; URestorator.sub_00572C3C
...
00572CEE   . E8 2185F8FF         CALL <Restorat._Unit45.sub_004FB214>       ; here CALL <Restorat._Unit45.TRegManager.Create>
...
00572CFC   . A1 84945900         MOV EAX,[DWORD DS:599484]
00572D01   . 8B00                MOV EAX,[DWORD DS:EAX]                     ; EAX: TRegManager实例
00572D03   . E8 AC8EF8FF         CALL <Restorat._Unit45.sub_004FBBB4>
00572D08   . A1 84945900         MOV EAX,[DWORD DS:599484]
00572D0D   . 8B00                MOV EAX,[DWORD DS:EAX]
00572D0F     8078 15 00          CMP [BYTE DS:EAX+15],0
00572D13     75 46               JNZ SHORT Restorat.00572D5B
00572D15   . 8B0D 08995900       MOV ECX,[DWORD DS:599908]
00572D1B   . 8B09                MOV ECX,[DWORD DS:ECX]
00572D1D   . B2 01               MOV DL,1
00572D1F   . A1 A4725400         MOV EAX,[DWORD DS:5472A4]
00572D24   . E8 4346F0FF         CALL <Restorat.Forms.TCustomForm.Create>   ; 创建"Enter License Key"窗体
00572D29   . 8B15 10975900       MOV EDX,[DWORD DS:599710]
00572D2F   . 8902                MOV [DWORD DS:EDX],EAX
00572D31   . A1 10975900         MOV EAX,[DWORD DS:599710]
00572D36   . 8B00                MOV EAX,[DWORD DS:EAX]
00572D38   . E8 1F4EFDFF         CALL <Restorat._Unit59.sub_00547B5C>       ; 显示窗体,要求输入用户名和注册码
00572D3D   . A1 84945900         MOV EAX,[DWORD DS:599484]
00572D42   . 8B00                MOV EAX,[DWORD DS:EAX]
00572D44   . 8078 15 00          CMP [BYTE DS:EAX+15],0
00572D48   . 75 11               JNZ SHORT Restorat.00572D5B
00572D4A   . A1 08995900         MOV EAX,[DWORD DS:599908]
00572D4F   . 8B00                MOV EAX,[DWORD DS:EAX]
00572D51   . E8 EEE0F0FF         CALL <Restorat.Forms.TApplication.Terminate>
00572D56   . E9 45010000         JMP Restorat.00572EA0
00572D5B   > 803D 58925900 00    CMP [BYTE DS:599258],0
...

  进入004FBBB4:
004FBBB4 >/$ 55                  PUSH EBP                                   ; _Unit45.sub_004FBBB4
...
004FBBFB  |. E8 5CD4F2FF         CALL <Restorat.Registry.TRegistry.Create>
004FBC00  |. 8945 E0             MOV [DWORD SS:EBP-20],EAX                  ; TRegistry实例
...
004FBC55  |. E8 22D6F2FF         CALL <Restorat.Registry.TRegistry.OpenKey> ; "HKEY_CURRENT_USER\Software\Bomers\Restorator\Registration"
...
004FBCE6  |. 8B55 B0             MOV EDX,[DWORD SS:EBP-50]
004FBCE9  |. 8D4D FC             LEA ECX,[DWORD SS:EBP-4]                   ; 读入Name -> [DWORD SS:EBP-4]
004FBCEC  |. 8B45 E0             MOV EAX,[DWORD SS:EBP-20]
004FBCEF  |. E8 DCDCF2FF         CALL <Restorat.Registry.TRegistry.ReadString>
...
004FBD06  |. 8B55 AC             MOV EDX,[DWORD SS:EBP-54]
004FBD09  |. 8D4D F8             LEA ECX,[DWORD SS:EBP-8]                   ; 读入Password -> [DWORD SS:EBP-8]
004FBD0C  |. 8B45 E0             MOV EAX,[DWORD SS:EBP-20]
004FBD0F  |. E8 BCDCF2FF         CALL <Restorat.Registry.TRegistry.ReadString>
...
004FBD26  |. 8B55 A8             MOV EDX,[DWORD SS:EBP-58]
004FBD29  |. 8D4D F4             LEA ECX,[DWORD SS:EBP-C]                   ; 读入Type -> [DWORD SS:EBP-C]
004FBD2C  |. 8B45 E0             MOV EAX,[DWORD SS:EBP-20]                  ; 下面会判断Type的值只能是"Regular"或"Student"
004FBD2F  |. E8 9CDCF2FF         CALL <Restorat.Registry.TRegistry.ReadString>
...
004FBDA1  |. E8 CEFBFFFF         CALL <Restorat._Unit45.sub_004FB974>       ; Name比对加密的黑名单,看来早期版本的Key泄露得不少
...
004FBE20   . E8 7BCBFFFF         CALL <Restorat._Unit45.TRSA.Create>        ; 创建TRSA实例
004FBE25   . 8945 EC             MOV [DWORD SS:EBP-14],EAX
004FBE28   . B2 01               MOV DL,1                                   ; TKeyBits= (kb0512, kb1024, kb2048)
004FBE2A   . 8B45 EC             MOV EAX,[DWORD SS:EBP-14]                  ; 表明 "TRSA using 1024 bit key"
004FBE2D   . E8 D6CCFFFF         CALL <Restorat._Unit45.sub_004F8B08>
...
004FBE40   . B2 01               MOV DL,1
004FBE42   . A1 2CA14F00         MOV EAX,[DWORD DS:4FA12C]
004FBE47   . E8 B47FF0FF         CALL <Restorat.System.TObject.Create>      ; 创建TSHA实例
004FBE4C   . 8945 E8             MOV [DWORD SS:EBP-18],EAX
...
004FBE65   . 8D45 9C             LEA EAX,[DWORD SS:EBP-64]
004FBE68   . 8B4D FC             MOV ECX,[DWORD SS:EBP-4]                   ; Name
004FBE6B   . 8B55 F4             MOV EDX,[DWORD SS:EBP-C]                   ; "R" 或 "S"
004FBE6E   . E8 1992F0FF         CALL <Restorat.System.@LStrCat3>           ; 按Type的值,"R"+Name 或 "S"+Name
004FBE73   . 8B55 9C             MOV EDX,[DWORD SS:EBP-64]
004FBE76   . 8B45 E8             MOV EAX,[DWORD SS:EBP-18]
004FBE79   . E8 F2E3FFFF         CALL <Restorat._Unit45.sub_004FA270>
004FBE7E   . 8B45 E8             MOV EAX,[DWORD SS:EBP-18]                  ; TSHA
004FBE81   . E8 8EE4FFFF         CALL <Restorat._Unit45.sub_004FA314>       ; 计算"R"/"S"+Name的SHA1
004FBE86   . 8D55 CC             LEA EDX,[DWORD SS:EBP-34]
004FBE89   . 8B45 E8             MOV EAX,[DWORD SS:EBP-18]
004FBE8C   . E8 83E5FFFF         CALL <Restorat._Unit45.sub_004FA414>       ; 将SHA1值复制到[DWORD SS:EBP-34]
004FBE91   . 8D45 98             LEA EAX,[DWORD SS:EBP-68]
004FBE94   . E8 0FF7FFFF         CALL <Restorat._Unit45.sub_004FB5A8>       ; 解密加密存储的公钥为Base64明文
004FBE99   . 8B55 98             MOV EDX,[DWORD SS:EBP-68]
004FBE9C   . 8B45 EC             MOV EAX,[DWORD SS:EBP-14]                  ; TRSA
004FBE9F   . E8 28CDFFFF         CALL <Restorat._Unit45.sub_004F8BCC>       ; TRSA.SetPublicKey,解码Base64编码的公钥
004FBEA4   . 8B55 F8             MOV EDX,[DWORD SS:EBP-8]                   ; Password
004FBEA7   . 8B45 EC             MOV EAX,[DWORD SS:EBP-14]                  ; TRSA
004FBEAA   . E8 41D1FFFF         CALL <Restorat._Unit45.sub_004F8FF0>       ; TRSA.SetSignature,解码Base64编码的签名(Password)
004FBEAF   . 6A 14               PUSH 14                                    ; 要比较的字节数
004FBEB1   . 8D55 CC             LEA EDX,[DWORD SS:EBP-34]                  ; TSHA计算出的SHA1
004FBEB4   . B9 13000000         MOV ECX,13
004FBEB9   . 8B45 EC             MOV EAX,[DWORD SS:EBP-14]                  ; TRSA
004FBEBC   . E8 17CBFFFF         CALL <Restorat._Unit45.sub_004F89D8>       ; TRSA.Verify
004FBEC1   . 8845 E5             MOV [BYTE SS:EBP-1B],AL
...

  重点在004F89D8(TRSA.Verify)
004F89D8 >/$ 55                  PUSH EBP                                   ; _Unit45.sub_004F89D8
004F89D9  |. 8BEC                MOV EBP,ESP
004F89DB  |. 81C4 F0FDFFFF       ADD ESP,-210
004F89E1  |. 53                  PUSH EBX
004F89E2  |. 56                  PUSH ESI
004F89E3  |. 8BDA                MOV EBX,EDX                                ; TSHA计算出的SHA1
004F89E5  |. 8BF0                MOV ESI,EAX
004F89E7  |. 80BE 62080000 00    CMP [BYTE DS:ESI+862],0                    ; TRSA.PubKeyLoaded:Boolean, TRSA.SetPublicKey成功后为1
004F89EE  |. 75 2F               JNZ SHORT Restorat.004F8A1F
004F89F0  |. 8D46 12             LEA EAX,[DWORD DS:ESI+12]
004F89F3  |. BA BC8A4F00         MOV EDX,Restorat.004F8ABC                  ; ASCII "Public key not loaded"
004F89F8  |. E8 CBC3F0FF         CALL <Restorat.System.@LStrAsg>
004F89FD  |. 8BC6                MOV EAX,ESI
004F89FF  |. E8 F0000000         CALL <Restorat._Unit45.sub_004F8AF4>       ; TRSA.DoStatusUpdate
004F8A04  |. B9 BC8A4F00         MOV ECX,Restorat.004F8ABC                  ; ASCII "Public key not loaded"
004F8A09  |. B2 01               MOV DL,1
004F8A0B  |. A1 70884F00         MOV EAX,[DWORD DS:4F8870]                  ; ENoKeyLoaded
004F8A10  |. E8 734FF1FF         CALL <Restorat._Unit3.Exception.Create>    ; ENoKeyLoaded.Create
004F8A15  |. E8 CABCF0FF         CALL <Restorat.System.@RaiseExcept>
004F8A1A  |. E9 8B000000         JMP Restorat.004F8AAA
004F8A1F  |> 80BE 64080000 00    CMP [BYTE DS:ESI+864],0                    ; TRSA.SigLoaded:Boolean, TRSA.SetSignature成功后为1
004F8A26  |. 75 2A               JNZ SHORT Restorat.004F8A52
004F8A28  |. 8D46 12             LEA EAX,[DWORD DS:ESI+12]
004F8A2B  |. BA DC8A4F00         MOV EDX,Restorat.004F8ADC                  ; ASCII "Signature not loaded"
004F8A30  |. E8 93C3F0FF         CALL <Restorat.System.@LStrAsg>
004F8A35  |. 8BC6                MOV EAX,ESI
004F8A37  |. E8 B8000000         CALL <Restorat._Unit45.sub_004F8AF4>       ; TRSA.DoStatusUpdate
004F8A3C  |. B9 DC8A4F00         MOV ECX,Restorat.004F8ADC                  ; ASCII "Signature not loaded"
004F8A41  |. B2 01               MOV DL,1
004F8A43  |. A1 70884F00         MOV EAX,[DWORD DS:4F8870]                  ; ENoKeyLoaded
004F8A48  |. E8 3B4FF1FF         CALL <Restorat._Unit3.Exception.Create>    ; ENoKeyLoaded.Create
004F8A4D  |. E8 92BCF0FF         CALL <Restorat.System.@RaiseExcept>
004F8A52  |> BA 84000000         MOV EDX,84
004F8A57  |. 8D85 F0FDFFFF       LEA EAX,[DWORD SS:EBP-210]
004F8A5D  |. E8 46090000         CALL <Restorat._Unit45.sub_004F93A8>       ; BNAssignZero
004F8A62  |. 68 84000000         PUSH 84
004F8A67  |. 8D86 32020000       LEA EAX,[DWORD DS:ESI+232]                 ; TRSA.n_Modulus:BigNum
004F8A6D  |. 50                  PUSH EAX
004F8A6E  |. 68 84000000         PUSH 84
004F8A73  |. 8D4E 22             LEA ECX,[DWORD DS:ESI+22]                  ; TRSA.e_Exponent:BigNum
004F8A76  |. 8D96 52060000       LEA EDX,[DWORD DS:ESI+652]                 ; TRSA.Signature:BigNum
004F8A7C  |. 8D85 F0FDFFFF       LEA EAX,[DWORD SS:EBP-210]                 ; Output buffer
004F8A82  |. E8 2D0E0000         CALL <Restorat._Unit45.sub_004F98B4>       ; BNModExp
004F8A87  |. 8B4D 08             MOV ECX,[DWORD SS:EBP+8]                   ; SHA1字节数
004F8A8A  |. 49                  DEC ECX                                    ; 程序逻辑:如果要比较的字节数为0,就跳过比较。
004F8A8B  |. 85C9                TEST ECX,ECX                               ; 但为什么将返回置为“比对相符”?
004F8A8D  |. 7C 19               JL SHORT Restorat.004F8AA8                 ; Crack1 - Option #1:SHA1 Comparing
004F8A8F  |. 41                  INC ECX
004F8A90  |. 8BC3                MOV EAX,EBX                                ; TSHA计算出的SHA1
004F8A92  |. 8D95 F0FDFFFF       LEA EDX,[DWORD SS:EBP-210]                 ; BNModExp解密后的签名
004F8A98  |> 0FB618              /MOVZX EBX,[BYTE DS:EAX]
004F8A9B  |. 3A1A                |CMP BL,[BYTE DS:EDX]                      ; 逐字节比较
004F8A9D  |. 74 04               |JE SHORT Restorat.004F8AA3
004F8A9F  |. 33C0                |XOR EAX,EAX                               ; 不相符,EAX清0
004F8AA1  |. EB 07               |JMP SHORT Restorat.004F8AAA               ; Crack1 - Option #2:SHA1 Comparing
004F8AA3  |> 42                  |INC EDX
004F8AA4  |. 40                  |INC EAX
004F8AA5  |. 49                  |DEC ECX
004F8AA6  |.^75 F0               \JNZ SHORT Restorat.004F8A98               ; 继续比较下一字节
004F8AA8  |> B0 01               MOV AL,1                                   ; SHA1相同,AL置1
004F8AAA  |> 5E                  POP ESI
004F8AAB  |. 5B                  POP EBX
004F8AAC  |. 8BE5                MOV ESP,EBP
004F8AAE  |. 5D                  POP EBP
004F8AAF  \. C2 0400             RETN 4

  BNModExp用公钥的模n和加密指数e去解密签名(注册码),然后逐字节比较计算出的SHA1和解密出的SHA1。破解点任选其一:
004F8A8D     EB 19               JMP SHORT Restorat.004F8AA8

  或
004F8AA1     EB 05               JMP SHORT Restorat.004F8AA8

  004F89D8(TRSA.Verify)除了这里(004FBEBC)——注册信息从注册表读入流程——被调用外,还有一处在00547C7A:注册信息用户输入流程。

四.用TSM Inc.的组件制作Keygen
  本节使用TSM Inc.的两个免费组件RSA和SHA来深入了解RSA的算法。前面讲过它们最高只支持Delphi 6,为了编译RSA组件中的示例程序,我不得不在虚拟机中安装"Borland Delphi Enterprise Version 6.0"。
  Delphi 6安装好后,分别运行两个组件包中的tsm_installer.exe进行组件安装,顺利的话Delphi 6中会多出一个"Crypto"标签,里面会有RSA和SHA组件。两个组件的缺省安装位置在"\Program Files\RSA\delphi6\d6_rsa.bpl"和"\Program Files\SHADemo\delphi6\d6_sha.bpl"。万一tsm_installer.exe没有成功,可点菜单"Component"下的"Install packages",注意不是"install component","Project Options"窗出现,点"Add"按钮,"Add Design Package"窗出现,再选择上面的bpl文件就好了。
  在Delphi 6中打开示例项目"\Program Files\RSA\examples\delphi\rsatest\rsa_test.dpr",切换到"Crypto"标签。注意到Form中已经有了组件RSA的一个控件RSA1:TRSA,双击"Crypto"标签下的SHA图标增加一个SHA1:TSHA控件。改写两个事件处理过程btnSignClick和btnVerifyClick为下面代码:
procedure TfrmRSATest.btnSignClick(Sender: TObject);
var
     Digest: TDigest;
begin
     SHA1.Init;
     SHA1.HashString(edtTestText.Text);
     SHA1.Finish;
     SHA1.GetHashDigest(Digest);

     // create the signature
     RSA1.Sign(Digest, Sizeof(Digest));

     // display the signature
     edtSignature.Text := RSA1.Signature;
end; {TfrmRSATest.btnSignClick}


procedure TfrmRSATest.btnVerifyClick(Sender: TObject);
var
     Digest: TDigest;
     Verified: Boolean;
begin
     SHA1.Init;
     SHA1.HashString(edtTestText.Text);
     SHA1.Finish;
     SHA1.GetHashDigest(Digest);

     // verify that the sig string in RSA1.Signature matches the digest
     Verified := RSA1.Verify(Digest, Sizeof(Digest));

     // tell the user
     if Verified then
     begin
          ShowMessage('Signature verified OK.');
     end
     else
     begin
          ShowMessage('Signature did not verify.');
     end;
end; {TfrmRSATest.btnVerifyClick}


  运行编译好的程序rsa_test.exe。RSA Test示例程序可以演示生成512位、1024位和2048位的密钥对,用密钥对来加密、解密,或者签名、验证信息。

  首先选择1024为密钥长度,再点"Create Key"按钮,就产生了一对密钥。
  公钥(Public Key):
++11KE:WfxAbH0Wrf4rVa51NFkr37zxvtv9bbGXSU-dg3xiYXz1MoccO0EL2mxwGNBwr5-aYGYdrDW0LPvd+lqx2C6VVQYSkmeneTCRnBrGQYBjUsHeZMQsumHBe1cV88srkhlYH-mvjPliBO7i7GvGG7pib54a0oId1eNYHc4G0NKOP+M

  私钥(Private Key):
WfxAbH0Wrf4rVa51NFkr37zxvtv9bbGXSU-dg3xiYXz1MoccO0EL2mxwGNBwr5-aYGYdrDW0LPvd+lqx2C6VVQYSkmeneTCRnBrGQYBjUsHeZMQsumHBe1cV88srkhlYH-mvjPliBO7i7GvGG7pib54a0oId1eNYHc4G0NKOP+M:T0R8DLeJzpMnxCBgoF1mcf+yK8wpfdwP2Z3ST44XBjse-Qny-HkF8KXV6Ne139kSnUnanfBCk4nCw9Upn5WspVrSt9GG4KiTSf0WNRax4x6r2PHqqunuGOIauCdPvWEvJ3FmYAngBp-jzpvNCno5o2r0zoAf2nRYIXQsRIINuvY

  在"Test text to encode/decode"下随便输入一串字符,来观察"Encrypt"和"Decrypt";或者交换公钥和私钥的作用,进行"Reverse Encrypt"和"Reverse Decrypt"的实验。
  这里我们重点关注签名和验证。假设用户名为:stillHiM,则在"Test text to encode/decode"下输入:RstillHiM。点"Sign","Signature"下得到输出,比如:
GWiAjMKJKQk3OvWXuLYbubbMsm7Jhxurj3YEDomC2YGqe50Moqsj3Tk9G6hC4mZvIaPjysNOIk-gMOHBgs0kv7yhis9lXEU8toWL+IwM9TK184G2OOIUiG9DxZ84ZG7V+NC3vlRGgVzmIiuj6Rk819MlpogoZnHJBgOiNDdYaq+

  这就是stillHiM的注册码。每次点"Sign",结果都会不同,因为签名加入了时间戳的缘故。没有关系,反正只需要验证签名的哈希值部分,点"Verify"一定是"Signature verified OK."。
  下一步我们需要将公钥“植入”Restorator.exe中:写一个上面分析中调用004FB528的逆过程,加密Base64编码的公钥,放回原位置004FB600处。这项工作选择在OD里进行,方便调试。
  首先选择一个小的、现成的Win32程序。比如,\WINDOWS\system32\systray.exe(Windows XP Pro. SP3),大小只有3072字节,是一个Win32的后台程序,如果不带参数运行,它什么也不做。反正我们只需要一个在OD里的可执行程序框架,它的.text段(01001000)和.data段(01002000)各有0x1000大小,足够用了。
  在OD里载入systray.exe,改写EP处长度0x7A字节为:
0100113E >   BD B2000000         MOV EBP,0B2
01001143     BF 00200001         MOV EDI,systray.01002000
01001148     8D543D 04           LEA EDX,[DWORD SS:EBP+EDI+4]
0100114C     8BC5                MOV EAX,EBP
0100114E     D1E0                SHL EAX,1
01001150     D0E8                SHR AL,1
01001152     80C4 20             ADD AH,20
01001155     04 20               ADD AL,20
01001157     86C4                XCHG AH,AL
01001159     66:8902             MOV [WORD DS:EDX],AX
0100115C     33DB                XOR EBX,EBX
0100115E     8BCB                MOV ECX,EBX
01001160     0FB6043B            MOVZX EAX,[BYTE DS:EBX+EDI]
01001164     2BC8                SUB ECX,EAX
01001166     83E9 03             SUB ECX,3
01001169     79 02               JNS SHORT systray.0100116D
0100116B     03CD                ADD ECX,EBP
0100116D     34 1F               XOR AL,1F
0100116F     807C11 02 00        CMP [BYTE DS:ECX+EDX+2],0
01001174     74 04               JE SHORT systray.0100117A
01001176     03CD                ADD ECX,EBP
01001178    ^EB F5               JMP SHORT systray.0100116F
0100117A     884411 02           MOV [BYTE DS:ECX+EDX+2],AL
0100117E     3B4A FC             CMP ECX,[DWORD DS:EDX-4]
01001181     7C 03               JL SHORT systray.01001186
01001183     894A FC             MOV [DWORD DS:EDX-4],ECX
01001186     43                  INC EBX
01001187     3BDD                CMP EBX,EBP
01001189    ^72 D3               JB SHORT systray.0100115E
0100118B     8342 FC 03          ADD [DWORD DS:EDX-4],3
0100118F     8B5A FC             MOV EBX,[DWORD DS:EDX-4]
01001192     43                  INC EBX
01001193     4B                  DEC EBX
01001194     83FB 02             CMP EBX,2
01001197     76 27               JBE SHORT systray.010011C0        ; 退出进程,CALL [DWORD DS:<&KERNEL32.ExitProcess>]
01001199     807C1A FF 00        CMP [BYTE DS:EDX+EBX-1],0
0100119E     74 0D               JE SHORT systray.010011AD
010011A0     0FB6441A FF         MOVZX EAX,[BYTE DS:EDX+EBX-1]
010011A5     34 1F               XOR AL,1F
010011A7     03C3                ADD EAX,EBX
010011A9     8BC8                MOV ECX,EAX
010011AB    ^EB E6               JMP SHORT systray.01001193
010011AD     2BCB                SUB ECX,EBX
010011AF     80F1 1F             XOR CL,1F
010011B2     884C1A FF           MOV [BYTE DS:EDX+EBX-1],CL
010011B6    ^EB E8               JMP SHORT systray.010011A0


  把公钥保存为文本文件pubkey.txt,在OD里View|File载入它,"Binary copy","Binary paste"到01002000处,F9后得到结果在010020B2处:
010020B0        0A 02 00 00 21 52 53 49 49 2D 2E 2F 2D 4D    ....!RSII-./-M
010020C0  4E 79 7A 6C 2A 4B 44 45 46 4D 5C 7A 31 32 45 4E  Nyzl*KDEFM\z12EN
010020D0  76 77 2E 2F 69 74 75 5C 29 4E 2D 5D 52 34 57 5C  vw./itu\)N-]R4W\
010020E0  5D 45 46 54 55 56 57 57 58 59 5A 5B 5C 5D 7D 4D  ]EFTUVWWXYZ[\]}M
010020F0  4E 4F 7E 7B 57 4F 50 66 67 7B 7C 26 27 27 2C 2D  NO~{WOPfg{|&'',-
01002100  2E 5C 5D 6C 6D 58 6C 6D 78 79 65 50 51 67 6C 6D  .\]lmXlmxyePQglm
01002110  7D 79 69 6B 57 74 28 48 58 52 7E 66 67 47 48 53  }yikWt(HXR~fgGHS
01002120  54 46 47 48 49 58 59 5A 7D 7D 2B 57 76 7B 68 5D  TFGHIXYZ}}+Wv{h]
01002130  5E 67 68 25 46 47 72 2D 2E 2E 4A 4C 34 34 46 47  ^gh%FGr-..JL44FG
01002140  6D 68 69 2E 2F 58 29 2A 6B 6C 6D 6E 2E 52 2B 2C  mhi./X)*klmn.R+,
01002150  26 4F 50 51 52 53 45 46 50 51 72 5A 47 48 6D 58  &OPQRSEFPQrZGHmX
01002160  2C 30 31 32 6C 7A 5D 4F 2E 6A 6C 46 58 59 5A 5B  ,012lz]O.jlFXYZ[
01002170  4A 4B 4C 69 6A 6B 6C 6D 66 67 68 69 71 72 73 74  JKLijklmfghiqrst
01002180  73 4A 71 72 6F 70 71 72 73 57 58 75 76 47 48 49  sJqropqrsWXuvGHI
01002190  76 6F 70 71 72 73 74 75 76 6D 6E 6F 70 71 72 73  vopqrstuvmnopqrs
010021A0  74 75 76 77 78 79 7A 4B 4C 4D 4E 4F 50 51 52 53  tuvwxyzKLMNOPQRS
010021B0  54 55 56 57 58 57 58 4E 4F 50 51 52 53 54 55 56  TUVWXWXNOPQRSTUV
010021C0  27 28 69 28 50 51 50 52 53 54 26 27 28 29 2A 64  '(i(PQPRST&'()*d
010021D0  65 2A 2B 2C 2D 2E 2F 2C 2D 2E 75 76 77 78 70 4E  e*+,-./,-.uvwxpN
010021E0  4F 50 51 66 67 68 69 6A 6B 6C 6D 59 7C 44 45 46  OPQfghijklmY|DEF
010021F0  25 26 27 28 29 2A 2B 67 22 23 24 25 26 27 28 7B  %&'()*+g"#$%&'({
01002200  4F 50 41 42 43 44 45 46 6F 70 71 72 73 74 6D 6E  OPABCDEFopqrstmn
01002210  6F 70 71 78 79 7A 54 55 56 57 58 73 74 75 6C 6D  opqxyzTUVWXstulm
01002220  6E 6F 70 71 72 6E 6F 70 71 72 73 74 75 76 77 78  nopqrnopqrstuvwx
01002230  79 7A 7B 7C 61 62 63 64 65 66 67 68 69 6A 6B 6C  yz{|abcdefghijkl
01002240  6D 6E 6F 69 6A 6B 6C 6D 6E 6F 70 6B 6C 6D 6E 6F  mnoijklmnopklmno
01002250  70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F  pqrstuvwxyz{|}~.
01002260  40 41 42 43 44 45 46 25 26 27 28 29 2A 2B 2C 2D  @ABCDEF%&'()*+,-
01002270  2E 2F 30 31 32 4C 4D 4E 4F 22 23 24 25 26 27 28  ./012LMNO"#$%&'(
01002280  29 2A 2B 9A 9B 9C 9D 9E 9F 60 61 62 63 64 65 66  )*+殯湞灍`abcdef
01002290  67 2C 2D 2E 2F 74 75 76 77 78 79 7A 7B 7C 34 6D  g,-./tuvwxyz{|4m
010022A0  6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D  nopqrstuvwxyz{|}
010022B0  7E 71 72 73 76 77 78 79 7A 7B 6C 6D 6E 6F 70 71  ~qrsvwxyz{lmnopq


  把这段0x20E字节的数据保存为二进制文件pubkey.bin。注:由于原版数据004FB600处,数据块大小为0x29A字节,为保证新的公钥加密后能放进这个空间,实际上"Create Key"做了几次,将每次的Base64公钥重复上面加密过程,这里贴出的公钥加密后长度为0x20A(ZWT的加密公钥长度为0x242),满足要求。
  现在我们来测试这个Keygen。
  先删除注册表里的注册信息,在OD中载入原版Restorator.exe,在004FB528(Decoding Public Key)处F2,F9。"Follow in Dump"寄存器EAX的值004FB600。View|File载入pubkey.bin,"Binary copy","Binary paste"到004FB5FC处。取消F2断点,F9,注册界面"Enter License Key"出现:

  填入上面的用户名和注册码,点"OK"。提示"Thank you for purchasing Restorator 2007 !",确认后,显示Splash,正常进入程序:

  证明我们的Keygen成功。附件中的中文处理Patch,没有采用这里演示的替换公钥方法,只修改了两个字节以跳过CRC检测和SHA1比对。

  利用RSA Test示例程序还可以得到ZWT公钥和私钥的Base64明文。
  OD载入rsa_test.exe,停在00459BB5处(点"Create Key"会来到这里),它位于TRSA.MakeKeyPair流程里TRSA.RSAMakeKeyPair返回处,这时e_Exponent、n_Modulus和d_Exponent已经产生了。用ZWT Keygen里的值替换它们,就得到了ZWT Base64编码的公钥和私钥:
Public Key:
++2++E:giW+QMdQFlBIuRioyBIoZYjT+m9t+hCnfFPH3DkAG+ShTSn7f68O1PknjIPxiTQ4dDu+2DL96tz4jhWpYfkyinAOSiNSlF3t3SJ5sMAiJXCA3qPHpRNEiBYR30MruKOQqyEkctvA-sirUrY-1JEyR-wfTlwvfxRPokv6COM4xRc
Private Key:
giW+QMdQFlBIuRioyBIoZYjT+m9t+hCnfFPH3DkAG+ShTSn7f68O1PknjIPxiTQ4dDu+2DL96tz4jhWpYfkyinAOSiNSlF3t3SJ5sMAiJXCA3qPHpRNEiBYR30MruKOQqyEkctvA-sirUrY-1JEyR-wfTlwvfxRPokv6COM4xRc:y7eIRP2BTM6SAZNkc+kKOAdRIg7KSj92HPgu268Fi5HO5LGx0M-WyZwRCBnLj5x8zC2hYhR8ESlp5uJvpG0PqHxkvjQA4v-yvxXFvj+XabZMuOwNfbT0ZHwj6hXKp1Vf3i7zhyzHrkRCVD36B3GxHxxz654NSGKxg+BUg2B7hC+

  公钥与OD载入ZWT Patch后的Restorator.exe,调用004FB528返回的结果一致。
  将这两个密钥填入RSA Test示例程序对应的输入框中,再分别点"Set entered Key"。我们就可以为ZWT的Patch生成注册码了。注册码也适用于汉化版WestKing.b1729和Digidea.b1747。

五.TRSA与其他RSA实现的对比
  因为这方面涉及的内容实在太多,只讨论密钥生成部分。
  OpenSSL是一个符合工业标准、跨平台的开源SSL/TLS套件。目前版本v1.0.1c,源码下载:http://www.openssl.org/source/openssl-1.0.1c.tar.gz,编译好的Win32平台下载:http://slproweb.com/download/Win32OpenSSL-1_0_1c.exe,需要先安装"Microsoft Visual C++ 2008 Redistributable"。
  Win32OpenSSL-1_0_1c.exe按缺省位置安装好后,为方便,需要在环境变量Path中添加"\OpenSSL-Win32\bin",它是命令行工具。OpenSSL功能强大,模块众多,RSA只是其中的一个。

  使用也简单明了,比如用OpenSSL生成一个1024位的RSA私钥,输出到文件privkey.pem:
openssl genrsa -out privkey.pem 1024

  以此可得到它的公钥,输出到文件pubkey.pem:
openssl rsa -in privkey.pem -pubout -out pubkey.pem

  这里.pem文件是一个Base64编码的文本文件,现在的标准叫做"MIME Base64",完整的定义可见RFC 1421和RFC 2045,于1987年在RFC 989中的电子隐私增强邮件协议[Privacy-enhanced Electronic Mail (PEM) protocol]中提出。
  该编码的字符包括大小写字母各26个,加上10个数字,和加号“+”,斜杠“/”,一共64个字符,等号“=”用来作为后缀用途。可在OpenSSL的源码"openssl-1.0.1c\crypto\evp\encode.c"中找到:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

  从Restorator.exe的_Unit45::sub_004F9174(RSA:: DecodeBase64)处分析发现,TRSA的Base64字符集为:
+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz

  与GEDCOM(GEnealogical Data COMmunication的缩写)版本5.5规定的Base64字符集类似(好象OpenSSL里某个模块也用到它):
./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz


  就Windows而言,微软当然也有自己的工具。比如命令行CryptoAPI工具Makecert.exe(Certificate Creation Tool)Sn.exe(Strong Name Tool),可由Visual Studio和Windows SDK/WDK得到。Makecert.exe可在这里下载,Sn.exe见附件。

  证书生成工具Makecert.exe主要用于为测试目的生成X.509证书,为数字签名产生一对公钥和私钥并存储在生成的证书文件中。比如下列命令:
makecert -r -n "CN=TestPVK" -sv TestPVK.pvk TestPVK.cer

  生成一个自签名的X.509证书文件TestPVK.cer,创建私钥到二进制文件TestPVK.pvk。也可以用下列命令:
makecert -sk myTestKey -pe -len 1024 -n "CN=TestCert" -ss TestCertStore

  将证书放在证书存储TestCertStore里,再用"certmgr.msc"控制台导出私钥为私人信息交换(Personal Information Exchange).pfx文件。
  .pvk是微软的专有格式,英国一位OpenSSL大师Dr. Stephen N Henson逆向工程了.pvk格式,写了一个工具"PVK file conversion tool 0.12",实现.pvk和.pem间的相互转换:
pvk.exe -in TestPVK.pvk -out TestPVK.pem -nocrypt

  作为一个例子,TestPVK.pem的内容为:
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQCxxplt8WarA72zVnF69JoVCz/ZBbYjZGA5095Q0bC4l8VpLnLq
nUfzsagwmEZ1yjaIl0JmNd3t/4dfVdoAt4BuQjD1GA/MVPJ8l9B8OlV1TbzvWmjA
sI+l8ewP2iYXhdd5cdtwM1mSzx5Gu7FABeU/yGy7S9UCH05bhIJAopRjxwIDAQAB
AoGAZCFZL9ylGDO+OHG67ycwViQE7UbTRPH3ZPrZoCnLYN1TOqAH5+94pGDvO5e5
MAUaXCreIlW6z596bw8bAAZbVk4fOkwVjgnVcBygByBTIyM0qsCR0FHs8KYFdlZc
5rkTm5oyZ/pr6RF15+wWIZalk6VGr6RKkcQl7+3fGWnHv1kCQQDkZrGbhpaoN8uc
FRjFtpIUSudCIyzEVBwyY39e1TIUwS/w9DsqYQkD/kZGYw2Jt/P+5IDhHaNjiWvb
OJq0GaSDAkEAx0HfX9M+Cvf/xiR8lFVn2e2MXJ8Xb/HQCXZSfvEEIyA6P1Sdt28l
5VjnFRCg5v/DplcrQbFl/yIYtlNiHOHIbQJBAI9HPLNrwqbUGY5YTan51bmVI22B
01t1yBp0ADrlUv1iE0j8bQEwzg8LO9p72MpD83Q6s/6EMTMHyflDkQjZ7TECQQCO
ko6vNSpGlO7Zqw/M31Ngtr1hJKCTg/W0X4pltDSeoZer6vKy5v+5nCQ0iWJoBwfK
RML5zWJK7O27v+wK+G79AkEAqfz1Igy68+c4AT6+YkE4zIP/5mkt0caiMMNV7PWq
1p6iOfUMYiBUJgBcvZwnaW7xARvE5oCuIIh1vJ68OnoKpw==
-----END RSA PRIVATE KEY-----

  用OpenSSL来查看这个私钥的组成:
openssl rsa -in TestPVK.pem -text -noout

  输出结果:
Private-Key: (1024 bit)
modulus:
    00:b1:c6:99:6d:f1:66:ab:03:bd:b3:56:71:7a:f4:
    9a:15:0b:3f:d9:05:b6:23:64:60:39:d3:de:50:d1:
    b0:b8:97:c5:69:2e:72:ea:9d:47:f3:b1:a8:30:98:
    46:75:ca:36:88:97:42:66:35:dd:ed:ff:87:5f:55:
    da:00:b7:80:6e:42:30:f5:18:0f:cc:54:f2:7c:97:
    d0:7c:3a:55:75:4d:bc:ef:5a:68:c0:b0:8f:a5:f1:
    ec:0f:da:26:17:85:d7:79:71:db:70:33:59:92:cf:
    1e:46:bb:b1:40:05:e5:3f:c8:6c:bb:4b:d5:02:1f:
    4e:5b:84:82:40:a2:94:63:c7
publicExponent: 65537 (0x10001)
privateExponent:
    64:21:59:2f:dc:a5:18:33:be:38:71:ba:ef:27:30:
    56:24:04:ed:46:d3:44:f1:f7:64:fa:d9:a0:29:cb:
    60:dd:53:3a:a0:07:e7:ef:78:a4:60:ef:3b:97:b9:
    30:05:1a:5c:2a:de:22:55:ba:cf:9f:7a:6f:0f:1b:
    00:06:5b:56:4e:1f:3a:4c:15:8e:09:d5:70:1c:a0:
    07:20:53:23:23:34:aa:c0:91:d0:51:ec:f0:a6:05:
    76:56:5c:e6:b9:13:9b:9a:32:67:fa:6b:e9:11:75:
    e7:ec:16:21:96:a5:93:a5:46:af:a4:4a:91:c4:25:
    ef:ed:df:19:69:c7:bf:59
prime1:
    00:e4:66:b1:9b:86:96:a8:37:cb:9c:15:18:c5:b6:
    92:14:4a:e7:42:23:2c:c4:54:1c:32:63:7f:5e:d5:
    32:14:c1:2f:f0:f4:3b:2a:61:09:03:fe:46:46:63:
    0d:89:b7:f3:fe:e4:80:e1:1d:a3:63:89:6b:db:38:
    9a:b4:19:a4:83
prime2:
    00:c7:41:df:5f:d3:3e:0a:f7:ff:c6:24:7c:94:55:
    67:d9:ed:8c:5c:9f:17:6f:f1:d0:09:76:52:7e:f1:
    04:23:20:3a:3f:54:9d:b7:6f:25:e5:58:e7:15:10:
    a0:e6:ff:c3:a6:57:2b:41:b1:65:ff:22:18:b6:53:
    62:1c:e1:c8:6d
exponent1:
    00:8f:47:3c:b3:6b:c2:a6:d4:19:8e:58:4d:a9:f9:
    d5:b9:95:23:6d:81:d3:5b:75:c8:1a:74:00:3a:e5:
    52:fd:62:13:48:fc:6d:01:30:ce:0f:0b:3b:da:7b:
    d8:ca:43:f3:74:3a:b3:fe:84:31:33:07:c9:f9:43:
    91:08:d9:ed:31
exponent2:
    00:8e:92:8e:af:35:2a:46:94:ee:d9:ab:0f:cc:df:
    53:60:b6:bd:61:24:a0:93:83:f5:b4:5f:8a:65:b4:
    34:9e:a1:97:ab:ea:f2:b2:e6:ff:b9:9c:24:34:89:
    62:68:07:07:ca:44:c2:f9:cd:62:4a:ec:ed:bb:bf:
    ec:0a:f8:6e:fd
coefficient:
    00:a9:fc:f5:22:0c:ba:f3:e7:38:01:3e:be:62:41:
    38:cc:83:ff:e6:69:2d:d1:c6:a2:30:c3:55:ec:f5:
    aa:d6:9e:a2:39:f5:0c:62:20:54:26:00:5c:bd:9c:
    27:69:6e:f1:01:1b:c4:e6:80:ae:20:88:75:bc:9e:
    bc:3a:7a:0a:a7

  可以看到,除了modulus、publicExponent和privateExponent,还包括计算过程中的中间变量,而TRSA的私钥只含有结果modulus和privateExponent。OpenSSL产生的Key同样也包含这些信息。另外,注意到makecert和OpenSSL的publicExponent采用了常量65537,而"TSM RSA freeware v1.15"中这个值为50001,Restorator.exe中为50003。
  从私钥输出公钥部分:
openssl rsa -in TestPVK.pem -pubout -out Testpubkey.pem

  Testpubkey.pem的内容:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxxplt8WarA72zVnF69JoVCz/Z
BbYjZGA5095Q0bC4l8VpLnLqnUfzsagwmEZ1yjaIl0JmNd3t/4dfVdoAt4BuQjD1
GA/MVPJ8l9B8OlV1TbzvWmjAsI+l8ewP2iYXhdd5cdtwM1mSzx5Gu7FABeU/yGy7
S9UCH05bhIJAopRjxwIDAQAB
-----END PUBLIC KEY-----

  查看它的组成:
openssl rsa -pubin -in Testpubkey.pem -text -noout

  输出为:
Public-Key: (1024 bit)
Modulus:
    00:b1:c6:99:6d:f1:66:ab:03:bd:b3:56:71:7a:f4:
    9a:15:0b:3f:d9:05:b6:23:64:60:39:d3:de:50:d1:
    b0:b8:97:c5:69:2e:72:ea:9d:47:f3:b1:a8:30:98:
    46:75:ca:36:88:97:42:66:35:dd:ed:ff:87:5f:55:
    da:00:b7:80:6e:42:30:f5:18:0f:cc:54:f2:7c:97:
    d0:7c:3a:55:75:4d:bc:ef:5a:68:c0:b0:8f:a5:f1:
    ec:0f:da:26:17:85:d7:79:71:db:70:33:59:92:cf:
    1e:46:bb:b1:40:05:e5:3f:c8:6c:bb:4b:d5:02:1f:
    4e:5b:84:82:40:a2:94:63:c7
Exponent: 65537 (0x10001)

  与TRSA的公钥类似。只包含modulus和publicExponent部分。
  解码Testpubkey.pem为Testpubkey.bin:
openssl enc -base64 -d -in Testpubkey.pem -out Testpubkey.bin

  Testpubkey.bin的内容:
         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0000h:  30 81 9F 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01
0010h:  05 00 03 81 8D 00 30 81 89 02 81 81 00 B1 C6 99
0020h:  6D F1 66 AB 03 BD B3 56 71 7A F4 9A 15 0B 3F D9
0030h:  05 B6 23 64 60 39 D3 DE 50 D1 B0 B8 97 C5 69 2E
0040h:  72 EA 9D 47 F3 B1 A8 30 98 46 75 CA 36 88 97 42
0050h:  66 35 DD ED FF 87 5F 55 DA 00 B7 80 6E 42 30 F5
0060h:  18 0F CC 54 F2 7C 97 D0 7C 3A 55 75 4D BC EF 5A
0070h:  68 C0 B0 8F A5 F1 EC 0F DA 26 17 85 D7 79 71 DB
0080h:  70 33 59 92 CF 1E 46 BB B1 40 05 E5 3F C8 6C BB
0090h:  4B D5 02 1F 4E 5B 84 82 40 A2 94 63 C7 02 03 01
00A0h:  00 01

  这个就看不懂了,但可识别出modulus和publicExponent,其结构需要研究OpenSSL的文档和源码才能搞清楚。

  强名称工具Sn.exe用来使用强名称对程序集(assemblies)进行签名。它提供用于密钥管理、签名生成和签名验证的选项。需要"Microsoft .NET Framework"环境才能运行。
  下列命令生成一个密钥对,缺省为1024位长度,保存到文件keyPair.snk:
Sn -k keyPair.snk

  用下列命令提取公钥部分到文件publicKey.snk:
sn -p keyPair.snk publicKey.snk

  strongname.h定义了.snk文件的格式。感谢Marcel Roma,他写了一个模板SNKTemplate_mro.bt,可在"010 Editor"里方便地查看.snk文件各字段的内容:





六.附件列表
  1. Restorator.2007.v3.70.1729.part1.rar & Restorator.2007.v3.70.1729.part2.rar
  如果你需要Restorator 2007 v3.70.1747的英文原版,先安装这个,再运行官方的升级补丁。
Restorator 2007 v3.70.1729 (Retail).exe
Size: 3,446,688
MD5:  8dc1eb0478cdbe256d41e0b5f4a21afb


  2. RSAfree.zip
  TSM Inc.的"TSM RSA freeware v1.15",支持:CB3 CB4 CB5 CB6 D3 D4 D5 D6,安装密码:"hjkDL9l3s0s[39s3fm3"。
RSAfree.zip
Size: 791,854
MD5:  8298b3e7ab21c7e002d6d8c22db16e01


  3. SHAfree.zip
  TSM Inc.的"TSM SHA freeware v1.15",支持:CB3 CB4 CB5 CB6 D3 D4 D5 D6,安装密码:"JF9kf+#vn39LccspeD"。
SHAfree.zip
Size: 619,350
Md5:  04adf0f2968b30ff325f9a55f9c7fa48


  4. RSA_Test.exe.7z
  RSAfree中的示例程序,加入了SHA组件的修改版本。
rsa_test.exe
Size: 447,488
MD5:  484e68d51efbd05a9f3bb6063c5adc3c


  5. Sn.exe.7z
  强名称工具,来自"Microsoft Visual Studio 2005 Professional"英文版DVD。
sn.exe
Size: 83,128
MD5:  975fad465bc8e758297263b7f8314ab3


  6. Restorator.exe.7z
  Restorator 2007 v3.70.1747英文版,加入了RCData中文处理补丁。注册部分改了两个字节(详见上面分析部分):[1] 0057F57E处跳过CRC验证,[2] 004F8AA1处跳过SHA1比较。这样修改方便使用:用户名可任意填写,注册码只有长度要求[171(0xAB)个TRSA Base64字符]。
Restorator.exe
Size: 2,337,792
MD5:  921aed97bbef0b5de13fd0dc96cd5310




Restorator.2007.v3.70.1729.part1.rar
Restorator.2007.v3.70.1729.part2.rar
RSAfree.zip
SHAfree.zip
RSA_Test.exe.7z
Sn.exe.7z
Restorator.exe.7z

004FB5F0:                                      9A 02 00 00
004FB600:  21 52 5B 3E.2C 79 34 4B.70 3A 34 74.90 4C 25 5C  !R[>,y4Kp:4t?L%\
004FB610:  2B 52 71 69.56 2A 2D 2C.4D 76 2E 4E.26 66 72 46  +RqiV*-,Mv.N&frF
004FB620:  5B 34 53 28.45 53 73 47.2A 42 35 7A.53 49 47 54  [4S(ESsG*B5zSIGT
...
004FB830:  6F D4 71 D6.D7 D8 75 76.77 DC DD 7A.7B A0 A1 A2  o q   uvw  z{?
004FB840:  A3 A4 41 42.A7 A8 45 46.AB AC AD AE.4B B0 B1 4E    AB  EF   RK +N
...
004FB880:  63 64 65 66.67 68 69 6A.6B 9F 6D 6E.6F 70 71 72  cdefghijk mnopqr
004FB890:  73 67 75 69.6A 6B 6C 6D.6E 6F                    sguijklmno
004FB5F0:                                      42 02 00 00
004FB600:  21 52 6E 5B.34 6E 6F 5B.2D 2E 4B 4C.69 6A 50 6D  !Rn[4no[-.KLijPm
004FB610:  2A 2B 51 25.26 6E 69 47.2D 5C 5D 5E.6C 2B 34 6D  *+Q%&niG-\]^l+4m
004FB620:  66 6D 45 46.55 4D 7B 7C.67 68 51 5E.5B 5C 5C 5D  fmEFUM{|ghQ^[\\]
...
004FB830:  70 71 72 73.74 9B 9C 9D.9E 9F 60 61.62 63 64 65  pqrst>    `abcde
004FB840:  66 67 00 42.A7 A8 45 46.AB AC AD AE.4B B0 B1 4E  fg B  EF   RK +N
...
004FB5A8 >/$ 55                  PUSH EBP                                ; _Unit45.sub_004FB5A8
004FB5A9  |. 8BEC                MOV EBP,ESP
...
004FB5BE  |. 55                  PUSH EBP                                ; /Arg1
004FB5BF  |. 8D55 FC             LEA EDX,[DWORD SS:EBP-4]                ; |
004FB5C2  |. B8 00B64F00         MOV EAX,Restorat.004FB600               ; |
004FB5C7  |. E8 5CFFFFFF         CALL <Restorat._Unit45.sub_004FB528>    ; \Restorat.004FB528, Decoding Public Key
...
00D940B8                                      B2 00 00 00
00D940C8  2B 2B 31 31 49 6B 3A 5A 7A 69 76 38 4F 42 4D 57  ++11Ik:Zziv8OBMW
00D940D8  36 37 66 48 47 76 37 7A 34 47 6E 54 39 4B 6B 71  67fHGv7z4GnT9Kkq
00D940E8  74 41 7A 6B 55 66 32 46 32 51 45 4E 4D 53 61 35  tAzkUf2F2QENMSa5
00D940F8  59 68 2B 68 44 6A 2B 37 33 66 45 6E 52 76 6B 57  Yh+hDj+73fEnRvkW
00D94108  48 52 70 48 62 34 68 44 74 32 4A 33 31 71 6E 4D  HRpHb4hDt2J31qnM
00D94118  49 69 41 72 49 57 39 5A 57 63 43 37 54 69 35 4D  IiArIW9ZWcC7Ti5M
00D94128  48 53 50 52 66 44 4E 59 70 35 78 52 66 78 53 4C  HSPRfDNYp5xRfxSL
00D94138  38 72 4C 52 34 36 41 6B 6F 4C 68 4B 42 34 75 5A  8rLR46AkoLhKB4uZ
00D94148  58 6E 48 69 56 38 44 58 55 4A 47 2D 6D 47 55 43  XnHiV8DXUJG-mGUC
00D94158  5A 65 2D 6C 54 63 54 79 62 54 37 74 67 35 52 62  Ze-lTcTybT7tg5Rb
00D94168  33 46 70 55 68 35 4D 79 46 78 36 62 75 70 76 2D  3FpUh5MyFx6bupv-
00D94178  41 59                                            AY
0057F577  |. E8 304FF8FF         CALL <Restorat._Unit47.sub_005044AC>    ; CRC check
0057F57C  |. 84C0                TEST AL,AL
  原版代码:
0057F57E     75 21               JNZ SHORT Restorat.0057F5A1
  Patch版代码,75改为EB:
0057F57E     EB 21               JMP SHORT Restorat.0057F5A1             ; Crack2 - Bypass CRC check
0057F580  |. 8D55 F4             LEA EDX,[DWORD SS:EBP-C]
0057F583  |. B8 442B5700         MOV EAX,Restorat.00572B44
0057F588  |. E8 BF7AE8FF         CALL <Restorat.System.LoadResString>
0057F58D  |. 8B4D F4             MOV ECX,[DWORD SS:EBP-C]
0057F590  |. B2 01               MOV DL,1
0057F592  |. A1 54874000         MOV EAX,[DWORD DS:408754]
0057F597  |. E8 ECE3E8FF         CALL <Restorat._Unit3.Exception.Create>
0057F59C  |. E8 4351E8FF         CALL <Restorat.System.@RaiseExcept>
0057F5A1  |> 33C0                XOR EAX,EAX
0057F5A3  |. 5A                  POP EDX
0057F5A4  |. 59                  POP ECX
0057F5A5  |. 59                  POP ECX
0057F5A6  |. 64:8910             MOV [DWORD FS:EAX],EDX
0057F5A9  |. 68 BEF55700         PUSH Restorat.0057F5BE
0057F5AE  |> 8B45 FC             MOV EAX,[DWORD SS:EBP-4]
0057F5B1  |. E8 7A48E8FF         CALL <Restorat.System.TObject.Free>
0057F5B6  \. C3                  RETN
005044AC >/$ 53                  PUSH EBX                                ; _Unit47.sub_005044AC
005044AD  |. 56                  PUSH ESI
005044AE  |. 8BD8                MOV EBX,EAX
005044B0  |. 8BC3                MOV EAX,EBX
005044B2  |. E8 1D000000         CALL <Restorat._Unit47.sub_005044D4>
005044B7  |. 8BF0                MOV ESI,EAX
005044B9  |. 83FE 85             CMP ESI,-7B
005044BC  |. 74 10               JE SHORT Restorat.005044CE
005044BE  |. 8BC3                MOV EAX,EBX
005044C0  |. E8 8BFFFFFF         CALL <Restorat._Unit47.sub_00504450>
005044C5  |. 3BF0                CMP ESI,EAX
005044C7  |. 74 05               JE SHORT Restorat.005044CE
005044C9  |. 33C0                XOR EAX,EAX
005044CB  |. 5E                  POP ESI
005044CC  |. 5B                  POP EBX
005044CD  |. C3                  RETN
005044CE  |> B0 01               MOV AL,1
005044D0  |. 5E                  POP ESI
005044D1  |. 5B                  POP EBX
005044D2  \. C3                  RETN
005920FC > $ 55                  PUSH EBP                                   ; _Unit72.Restorator
005920FD   . 8BEC                MOV EBP,ESP
005920FF   . 83C4 F0             ADD ESP,-10
00592102   . B8 90095900         MOV EAX,Restorat.00590990
00592107   . E8 CC50E7FF         CALL <Restorat._Unit2.@InitExe>
0059210C   . E8 2B0BFEFF         CALL <Restorat.URestorator.sub_00572C3C>
00592111   . E8 B62AE7FF         CALL <Restorat.System.@Halt0>
...
00572C3C >/$ 55                  PUSH EBP                                   ; URestorator.sub_00572C3C
...
00572CEE   . E8 2185F8FF         CALL <Restorat._Unit45.sub_004FB214>       ; here CALL <Restorat._Unit45.TRegManager.Create>
...
00572CFC   . A1 84945900         MOV EAX,[DWORD DS:599484]
00572D01   . 8B00                MOV EAX,[DWORD DS:EAX]                     ; EAX: TRegManager实例
00572D03   . E8 AC8EF8FF         CALL <Restorat._Unit45.sub_004FBBB4>
00572D08   . A1 84945900         MOV EAX,[DWORD DS:599484]
00572D0D   . 8B00                MOV EAX,[DWORD DS:EAX]
00572D0F     8078 15 00          CMP [BYTE DS:EAX+15],0
00572D13     75 46               JNZ SHORT Restorat.00572D5B
00572D15   . 8B0D 08995900       MOV ECX,[DWORD DS:599908]
00572D1B   . 8B09                MOV ECX,[DWORD DS:ECX]
00572D1D   . B2 01               MOV DL,1
00572D1F   . A1 A4725400         MOV EAX,[DWORD DS:5472A4]
00572D24   . E8 4346F0FF         CALL <Restorat.Forms.TCustomForm.Create>   ; 创建"Enter License Key"窗体
00572D29   . 8B15 10975900       MOV EDX,[DWORD DS:599710]
00572D2F   . 8902                MOV [DWORD DS:EDX],EAX
00572D31   . A1 10975900         MOV EAX,[DWORD DS:599710]
00572D36   . 8B00                MOV EAX,[DWORD DS:EAX]
00572D38   . E8 1F4EFDFF         CALL <Restorat._Unit59.sub_00547B5C>       ; 显示窗体,要求输入用户名和注册码
00572D3D   . A1 84945900         MOV EAX,[DWORD DS:599484]
00572D42   . 8B00                MOV EAX,[DWORD DS:EAX]
00572D44   . 8078 15 00          CMP [BYTE DS:EAX+15],0
00572D48   . 75 11               JNZ SHORT Restorat.00572D5B
00572D4A   . A1 08995900         MOV EAX,[DWORD DS:599908]
00572D4F   . 8B00                MOV EAX,[DWORD DS:EAX]
00572D51   . E8 EEE0F0FF         CALL <Restorat.Forms.TApplication.Terminate>
00572D56   . E9 45010000         JMP Restorat.00572EA0
00572D5B   > 803D 58925900 00    CMP [BYTE DS:599258],0
...
004FBBB4 >/$ 55                  PUSH EBP                                   ; _Unit45.sub_004FBBB4
...
004FBBFB  |. E8 5CD4F2FF         CALL <Restorat.Registry.TRegistry.Create>
004FBC00  |. 8945 E0             MOV [DWORD SS:EBP-20],EAX                  ; TRegistry实例
...
004FBC55  |. E8 22D6F2FF         CALL <Restorat.Registry.TRegistry.OpenKey> ; "HKEY_CURRENT_USER\Software\Bomers\Restorator\Registration"
...
004FBCE6  |. 8B55 B0             MOV EDX,[DWORD SS:EBP-50]
004FBCE9  |. 8D4D FC             LEA ECX,[DWORD SS:EBP-4]                   ; 读入Name -> [DWORD SS:EBP-4]
004FBCEC  |. 8B45 E0             MOV EAX,[DWORD SS:EBP-20]
004FBCEF  |. E8 DCDCF2FF         CALL <Restorat.Registry.TRegistry.ReadString>
...
004FBD06  |. 8B55 AC             MOV EDX,[DWORD SS:EBP-54]
004FBD09  |. 8D4D F8             LEA ECX,[DWORD SS:EBP-8]                   ; 读入Password -> [DWORD SS:EBP-8]
004FBD0C  |. 8B45 E0             MOV EAX,[DWORD SS:EBP-20]
004FBD0F  |. E8 BCDCF2FF         CALL <Restorat.Registry.TRegistry.ReadString>
...
004FBD26  |. 8B55 A8             MOV EDX,[DWORD SS:EBP-58]
004FBD29  |. 8D4D F4             LEA ECX,[DWORD SS:EBP-C]                   ; 读入Type -> [DWORD SS:EBP-C]
004FBD2C  |. 8B45 E0             MOV EAX,[DWORD SS:EBP-20]                  ; 下面会判断Type的值只能是"Regular"或"Student"
004FBD2F  |. E8 9CDCF2FF         CALL <Restorat.Registry.TRegistry.ReadString>
...
004FBDA1  |. E8 CEFBFFFF         CALL <Restorat._Unit45.sub_004FB974>       ; Name比对加密的黑名单,看来早期版本的Key泄露得不少
...
004FBE20   . E8 7BCBFFFF         CALL <Restorat._Unit45.TRSA.Create>        ; 创建TRSA实例
004FBE25   . 8945 EC             MOV [DWORD SS:EBP-14],EAX
004FBE28   . B2 01               MOV DL,1                                   ; TKeyBits= (kb0512, kb1024, kb2048)
004FBE2A   . 8B45 EC             MOV EAX,[DWORD SS:EBP-14]                  ; 表明 "TRSA using 1024 bit key"
004FBE2D   . E8 D6CCFFFF         CALL <Restorat._Unit45.sub_004F8B08>
...
004FBE40   . B2 01               MOV DL,1
004FBE42   . A1 2CA14F00         MOV EAX,[DWORD DS:4FA12C]
004FBE47   . E8 B47FF0FF         CALL <Restorat.System.TObject.Create>      ; 创建TSHA实例
004FBE4C   . 8945 E8             MOV [DWORD SS:EBP-18],EAX
...
004FBE65   . 8D45 9C             LEA EAX,[DWORD SS:EBP-64]
004FBE68   . 8B4D FC             MOV ECX,[DWORD SS:EBP-4]                   ; Name
004FBE6B   . 8B55 F4             MOV EDX,[DWORD SS:EBP-C]                   ; "R" 或 "S"
004FBE6E   . E8 1992F0FF         CALL <Restorat.System.@LStrCat3>           ; 按Type的值,"R"+Name 或 "S"+Name
004FBE73   . 8B55 9C             MOV EDX,[DWORD SS:EBP-64]
004FBE76   . 8B45 E8             MOV EAX,[DWORD SS:EBP-18]
004FBE79   . E8 F2E3FFFF         CALL <Restorat._Unit45.sub_004FA270>
004FBE7E   . 8B45 E8             MOV EAX,[DWORD SS:EBP-18]                  ; TSHA
004FBE81   . E8 8EE4FFFF         CALL <Restorat._Unit45.sub_004FA314>       ; 计算"R"/"S"+Name的SHA1
004FBE86   . 8D55 CC             LEA EDX,[DWORD SS:EBP-34]
004FBE89   . 8B45 E8             MOV EAX,[DWORD SS:EBP-18]
004FBE8C   . E8 83E5FFFF         CALL <Restorat._Unit45.sub_004FA414>       ; 将SHA1值复制到[DWORD SS:EBP-34]
004FBE91   . 8D45 98             LEA EAX,[DWORD SS:EBP-68]
004FBE94   . E8 0FF7FFFF         CALL <Restorat._Unit45.sub_004FB5A8>       ; 解密加密存储的公钥为Base64明文
004FBE99   . 8B55 98             MOV EDX,[DWORD SS:EBP-68]
004FBE9C   . 8B45 EC             MOV EAX,[DWORD SS:EBP-14]                  ; TRSA
004FBE9F   . E8 28CDFFFF         CALL <Restorat._Unit45.sub_004F8BCC>       ; TRSA.SetPublicKey,解码Base64编码的公钥
004FBEA4   . 8B55 F8             MOV EDX,[DWORD SS:EBP-8]                   ; Password
004FBEA7   . 8B45 EC             MOV EAX,[DWORD SS:EBP-14]                  ; TRSA
004FBEAA   . E8 41D1FFFF         CALL <Restorat._Unit45.sub_004F8FF0>       ; TRSA.SetSignature,解码Base64编码的签名(Password)
004FBEAF   . 6A 14               PUSH 14                                    ; 要比较的字节数
004FBEB1   . 8D55 CC             LEA EDX,[DWORD SS:EBP-34]                  ; TSHA计算出的SHA1
004FBEB4   . B9 13000000         MOV ECX,13
004FBEB9   . 8B45 EC             MOV EAX,[DWORD SS:EBP-14]                  ; TRSA
004FBEBC   . E8 17CBFFFF         CALL <Restorat._Unit45.sub_004F89D8>       ; TRSA.Verify
004FBEC1   . 8845 E5             MOV [BYTE SS:EBP-1B],AL
...
004F89D8 >/$ 55                  PUSH EBP                                   ; _Unit45.sub_004F89D8
004F89D9  |. 8BEC                MOV EBP,ESP
004F89DB  |. 81C4 F0FDFFFF       ADD ESP,-210
004F89E1  |. 53                  PUSH EBX
004F89E2  |. 56                  PUSH ESI
004F89E3  |. 8BDA                MOV EBX,EDX                                ; TSHA计算出的SHA1
004F89E5  |. 8BF0                MOV ESI,EAX
004F89E7  |. 80BE 62080000 00    CMP [BYTE DS:ESI+862],0                    ; TRSA.PubKeyLoaded:Boolean, TRSA.SetPublicKey成功后为1
004F89EE  |. 75 2F               JNZ SHORT Restorat.004F8A1F
004F89F0  |. 8D46 12             LEA EAX,[DWORD DS:ESI+12]
004F89F3  |. BA BC8A4F00         MOV EDX,Restorat.004F8ABC                  ; ASCII "Public key not loaded"
004F89F8  |. E8 CBC3F0FF         CALL <Restorat.System.@LStrAsg>
004F89FD  |. 8BC6                MOV EAX,ESI
004F89FF  |. E8 F0000000         CALL <Restorat._Unit45.sub_004F8AF4>       ; TRSA.DoStatusUpdate
004F8A04  |. B9 BC8A4F00         MOV ECX,Restorat.004F8ABC                  ; ASCII "Public key not loaded"
004F8A09  |. B2 01               MOV DL,1
004F8A0B  |. A1 70884F00         MOV EAX,[DWORD DS:4F8870]                  ; ENoKeyLoaded
004F8A10  |. E8 734FF1FF         CALL <Restorat._Unit3.Exception.Create>    ; ENoKeyLoaded.Create
004F8A15  |. E8 CABCF0FF         CALL <Restorat.System.@RaiseExcept>
004F8A1A  |. E9 8B000000         JMP Restorat.004F8AAA
004F8A1F  |> 80BE 64080000 00    CMP [BYTE DS:ESI+864],0                    ; TRSA.SigLoaded:Boolean, TRSA.SetSignature成功后为1
004F8A26  |. 75 2A               JNZ SHORT Restorat.004F8A52
004F8A28  |. 8D46 12             LEA EAX,[DWORD DS:ESI+12]
004F8A2B  |. BA DC8A4F00         MOV EDX,Restorat.004F8ADC                  ; ASCII "Signature not loaded"
004F8A30  |. E8 93C3F0FF         CALL <Restorat.System.@LStrAsg>
004F8A35  |. 8BC6                MOV EAX,ESI
004F8A37  |. E8 B8000000         CALL <Restorat._Unit45.sub_004F8AF4>       ; TRSA.DoStatusUpdate
004F8A3C  |. B9 DC8A4F00         MOV ECX,Restorat.004F8ADC                  ; ASCII "Signature not loaded"
004F8A41  |. B2 01               MOV DL,1
004F8A43  |. A1 70884F00         MOV EAX,[DWORD DS:4F8870]                  ; ENoKeyLoaded
004F8A48  |. E8 3B4FF1FF         CALL <Restorat._Unit3.Exception.Create>    ; ENoKeyLoaded.Create
004F8A4D  |. E8 92BCF0FF         CALL <Restorat.System.@RaiseExcept>
004F8A52  |> BA 84000000         MOV EDX,84
004F8A57  |. 8D85 F0FDFFFF       LEA EAX,[DWORD SS:EBP-210]
004F8A5D  |. E8 46090000         CALL <Restorat._Unit45.sub_004F93A8>       ; BNAssignZero
004F8A62  |. 68 84000000         PUSH 84
004F8A67  |. 8D86 32020000       LEA EAX,[DWORD DS:ESI+232]                 ; TRSA.n_Modulus:BigNum
004F8A6D  |. 50                  PUSH EAX
004F8A6E  |. 68 84000000         PUSH 84
004F8A73  |. 8D4E 22             LEA ECX,[DWORD DS:ESI+22]                  ; TRSA.e_Exponent:BigNum
004F8A76  |. 8D96 52060000       LEA EDX,[DWORD DS:ESI+652]                 ; TRSA.Signature:BigNum
004F8A7C  |. 8D85 F0FDFFFF       LEA EAX,[DWORD SS:EBP-210]                 ; Output buffer
004F8A82  |. E8 2D0E0000         CALL <Restorat._Unit45.sub_004F98B4>       ; BNModExp
004F8A87  |. 8B4D 08             MOV ECX,[DWORD SS:EBP+8]                   ; SHA1字节数
004F8A8A  |. 49                  DEC ECX                                    ; 程序逻辑:如果要比较的字节数为0,就跳过比较。
004F8A8B  |. 85C9                TEST ECX,ECX                               ; 但为什么将返回置为“比对相符”?
004F8A8D  |. 7C 19               JL SHORT Restorat.004F8AA8                 ; Crack1 - Option #1:SHA1 Comparing
004F8A8F  |. 41                  INC ECX
004F8A90  |. 8BC3                MOV EAX,EBX                                ; TSHA计算出的SHA1
004F8A92  |. 8D95 F0FDFFFF       LEA EDX,[DWORD SS:EBP-210]                 ; BNModExp解密后的签名
004F8A98  |> 0FB618              /MOVZX EBX,[BYTE DS:EAX]
004F8A9B  |. 3A1A                |CMP BL,[BYTE DS:EDX]                      ; 逐字节比较
004F8A9D  |. 74 04               |JE SHORT Restorat.004F8AA3
004F8A9F  |. 33C0                |XOR EAX,EAX                               ; 不相符,EAX清0
004F8AA1  |. EB 07               |JMP SHORT Restorat.004F8AAA               ; Crack1 - Option #2:SHA1 Comparing
004F8AA3  |> 42                  |INC EDX
004F8AA4  |. 40                  |INC EAX
004F8AA5  |. 49                  |DEC ECX
004F8AA6  |.^75 F0               \JNZ SHORT Restorat.004F8A98               ; 继续比较下一字节
004F8AA8  |> B0 01               MOV AL,1                                   ; SHA1相同,AL置1
004F8AAA  |> 5E                  POP ESI
004F8AAB  |. 5B                  POP EBX
004F8AAC  |. 8BE5                MOV ESP,EBP
004F8AAE  |. 5D                  POP EBP
004F8AAF  \. C2 0400             RETN 4
004F8A8D     EB 19               JMP SHORT Restorat.004F8AA8
004F8AA1     EB 05               JMP SHORT Restorat.004F8AA8
procedure TfrmRSATest.btnSignClick(Sender: TObject);
var
     Digest: TDigest;
begin
     SHA1.Init;
     SHA1.HashString(edtTestText.Text);
     SHA1.Finish;
     SHA1.GetHashDigest(Digest);

     // create the signature
     RSA1.Sign(Digest, Sizeof(Digest));

     // display the signature
     edtSignature.Text := RSA1.Signature;
end; {TfrmRSATest.btnSignClick}
procedure TfrmRSATest.btnVerifyClick(Sender: TObject);
var
     Digest: TDigest;
     Verified: Boolean;
begin
     SHA1.Init;
     SHA1.HashString(edtTestText.Text);
     SHA1.Finish;
     SHA1.GetHashDigest(Digest);

     // verify that the sig string in RSA1.Signature matches the digest
     Verified := RSA1.Verify(Digest, Sizeof(Digest));

     // tell the user
     if Verified then
     begin
          ShowMessage('Signature verified OK.');
     end
     else
     begin
          ShowMessage('Signature did not verify.');
     end;
end; {TfrmRSATest.btnVerifyClick}
++11KE:WfxAbH0Wrf4rVa51NFkr37zxvtv9bbGXSU-dg3xiYXz1MoccO0EL2mxwGNBwr5-aYGYdrDW0LPvd+lqx2C6VVQYSkmeneTCRnBrGQYBjUsHeZMQsumHBe1cV88srkhlYH-mvjPliBO7i7GvGG7pib54a0oId1eNYHc4G0NKOP+M
WfxAbH0Wrf4rVa51NFkr37zxvtv9bbGXSU-dg3xiYXz1MoccO0EL2mxwGNBwr5-aYGYdrDW0LPvd+lqx2C6VVQYSkmeneTCRnBrGQYBjUsHeZMQsumHBe1cV88srkhlYH-mvjPliBO7i7GvGG7pib54a0oId1eNYHc4G0NKOP+M:T0R8DLeJzpMnxCBgoF1mcf+yK8wpfdwP2Z3ST44XBjse-Qny-HkF8KXV6Ne139kSnUnanfBCk4nCw9Upn5WspVrSt9GG4KiTSf0WNRax4x6r2PHqqunuGOIauCdPvWEvJ3FmYAngBp-jzpvNCno5o2r0zoAf2nRYIXQsRIINuvY
GWiAjMKJKQk3OvWXuLYbubbMsm7Jhxurj3YEDomC2YGqe50Moqsj3Tk9G6hC4mZvIaPjysNOIk-gMOHBgs0kv7yhis9lXEU8toWL+IwM9TK184G2OOIUiG9DxZ84ZG7V+NC3vlRGgVzmIiuj6Rk819MlpogoZnHJBgOiNDdYaq+
0100113E >   BD B2000000         MOV EBP,0B2
01001143     BF 00200001         MOV EDI,systray.01002000
01001148     8D543D 04           LEA EDX,[DWORD SS:EBP+EDI+4]
0100114C     8BC5                MOV EAX,EBP
0100114E     D1E0                SHL EAX,1
01001150     D0E8                SHR AL,1
01001152     80C4 20             ADD AH,20
01001155     04 20               ADD AL,20
01001157     86C4                XCHG AH,AL
01001159     66:8902             MOV [WORD DS:EDX],AX
0100115C     33DB                XOR EBX,EBX
0100115E     8BCB                MOV ECX,EBX
01001160     0FB6043B            MOVZX EAX,[BYTE DS:EBX+EDI]
01001164     2BC8                SUB ECX,EAX
01001166     83E9 03             SUB ECX,3
01001169     79 02               JNS SHORT systray.0100116D
0100116B     03CD                ADD ECX,EBP
0100116D     34 1F               XOR AL,1F
0100116F     807C11 02 00        CMP [BYTE DS:ECX+EDX+2],0
01001174     74 04               JE SHORT systray.0100117A
01001176     03CD                ADD ECX,EBP
01001178    ^EB F5               JMP SHORT systray.0100116F
0100117A     884411 02           MOV [BYTE DS:ECX+EDX+2],AL
0100117E     3B4A FC             CMP ECX,[DWORD DS:EDX-4]
01001181     7C 03               JL SHORT systray.01001186
01001183     894A FC             MOV [DWORD DS:EDX-4],ECX
01001186     43                  INC EBX
01001187     3BDD                CMP EBX,EBP
01001189    ^72 D3               JB SHORT systray.0100115E
0100118B     8342 FC 03          ADD [DWORD DS:EDX-4],3
0100118F     8B5A FC             MOV EBX,[DWORD DS:EDX-4]
01001192     43                  INC EBX
01001193     4B                  DEC EBX
01001194     83FB 02             CMP EBX,2
01001197     76 27               JBE SHORT systray.010011C0        ; 退出进程,CALL [DWORD DS:<&KERNEL32.ExitProcess>]
01001199     807C1A FF 00        CMP [BYTE DS:EDX+EBX-1],0
0100119E     74 0D               JE SHORT systray.010011AD
010011A0     0FB6441A FF         MOVZX EAX,[BYTE DS:EDX+EBX-1]
010011A5     34 1F               XOR AL,1F
010011A7     03C3                ADD EAX,EBX
010011A9     8BC8                MOV ECX,EAX
010011AB    ^EB E6               JMP SHORT systray.01001193
010011AD     2BCB                SUB ECX,EBX
010011AF     80F1 1F             XOR CL,1F
010011B2     884C1A FF           MOV [BYTE DS:EDX+EBX-1],CL
010011B6    ^EB E8               JMP SHORT systray.010011A0
010020B0        0A 02 00 00 21 52 53 49 49 2D 2E 2F 2D 4D    ....!RSII-./-M
010020C0  4E 79 7A 6C 2A 4B 44 45 46 4D 5C 7A 31 32 45 4E  Nyzl*KDEFM\z12EN
010020D0  76 77 2E 2F 69 74 75 5C 29 4E 2D 5D 52 34 57 5C  vw./itu\)N-]R4W\
010020E0  5D 45 46 54 55 56 57 57 58 59 5A 5B 5C 5D 7D 4D  ]EFTUVWWXYZ[\]}M
010020F0  4E 4F 7E 7B 57 4F 50 66 67 7B 7C 26 27 27 2C 2D  NO~{WOPfg{|&'',-
01002100  2E 5C 5D 6C 6D 58 6C 6D 78 79 65 50 51 67 6C 6D  .\]lmXlmxyePQglm
01002110  7D 79 69 6B 57 74 28 48 58 52 7E 66 67 47 48 53  }yikWt(HXR~fgGHS
01002120  54 46 47 48 49 58 59 5A 7D 7D 2B 57 76 7B 68 5D  TFGHIXYZ}}+Wv{h]
01002130  5E 67 68 25 46 47 72 2D 2E 2E 4A 4C 34 34 46 47  ^gh%FGr-..JL44FG
01002140  6D 68 69 2E 2F 58 29 2A 6B 6C 6D 6E 2E 52 2B 2C  mhi./X)*klmn.R+,
01002150  26 4F 50 51 52 53 45 46 50 51 72 5A 47 48 6D 58  &OPQRSEFPQrZGHmX
01002160  2C 30 31 32 6C 7A 5D 4F 2E 6A 6C 46 58 59 5A 5B  ,012lz]O.jlFXYZ[
01002170  4A 4B 4C 69 6A 6B 6C 6D 66 67 68 69 71 72 73 74  JKLijklmfghiqrst
01002180  73 4A 71 72 6F 70 71 72 73 57 58 75 76 47 48 49  sJqropqrsWXuvGHI
01002190  76 6F 70 71 72 73 74 75 76 6D 6E 6F 70 71 72 73  vopqrstuvmnopqrs
010021A0  74 75 76 77 78 79 7A 4B 4C 4D 4E 4F 50 51 52 53  tuvwxyzKLMNOPQRS
010021B0  54 55 56 57 58 57 58 4E 4F 50 51 52 53 54 55 56  TUVWXWXNOPQRSTUV
010021C0  27 28 69 28 50 51 50 52 53 54 26 27 28 29 2A 64  '(i(PQPRST&'()*d
010021D0  65 2A 2B 2C 2D 2E 2F 2C 2D 2E 75 76 77 78 70 4E  e*+,-./,-.uvwxpN
010021E0  4F 50 51 66 67 68 69 6A 6B 6C 6D 59 7C 44 45 46  OPQfghijklmY|DEF
010021F0  25 26 27 28 29 2A 2B 67 22 23 24 25 26 27 28 7B  %&'()*+g"#$%&'({
01002200  4F 50 41 42 43 44 45 46 6F 70 71 72 73 74 6D 6E  OPABCDEFopqrstmn
01002210  6F 70 71 78 79 7A 54 55 56 57 58 73 74 75 6C 6D  opqxyzTUVWXstulm
01002220  6E 6F 70 71 72 6E 6F 70 71 72 73 74 75 76 77 78  nopqrnopqrstuvwx
01002230  79 7A 7B 7C 61 62 63 64 65 66 67 68 69 6A 6B 6C  yz{|abcdefghijkl
01002240  6D 6E 6F 69 6A 6B 6C 6D 6E 6F 70 6B 6C 6D 6E 6F  mnoijklmnopklmno
01002250  70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F  pqrstuvwxyz{|}~.
01002260  40 41 42 43 44 45 46 25 26 27 28 29 2A 2B 2C 2D  @ABCDEF%&'()*+,-
01002270  2E 2F 30 31 32 4C 4D 4E 4F 22 23 24 25 26 27 28  ./012LMNO"#$%&'(
01002280  29 2A 2B 9A 9B 9C 9D 9E 9F 60 61 62 63 64 65 66  )*+殯湞灍`abcdef
01002290  67 2C 2D 2E 2F 74 75 76 77 78 79 7A 7B 7C 34 6D  g,-./tuvwxyz{|4m
010022A0  6E 6F 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D  nopqrstuvwxyz{|}
010022B0  7E 71 72 73 76 77 78 79 7A 7B 6C 6D 6E 6F 70 71  ~qrsvwxyz{lmnopq
Public Key:
++2++E:giW+QMdQFlBIuRioyBIoZYjT+m9t+hCnfFPH3DkAG+ShTSn7f68O1PknjIPxiTQ4dDu+2DL96tz4jhWpYfkyinAOSiNSlF3t3SJ5sMAiJXCA3qPHpRNEiBYR30MruKOQqyEkctvA-sirUrY-1JEyR-wfTlwvfxRPokv6COM4xRc
Private Key:
giW+QMdQFlBIuRioyBIoZYjT+m9t+hCnfFPH3DkAG+ShTSn7f68O1PknjIPxiTQ4dDu+2DL96tz4jhWpYfkyinAOSiNSlF3t3SJ5sMAiJXCA3qPHpRNEiBYR30MruKOQqyEkctvA-sirUrY-1JEyR-wfTlwvfxRPokv6COM4xRc:y7eIRP2BTM6SAZNkc+kKOAdRIg7KSj92HPgu268Fi5HO5LGx0M-WyZwRCBnLj5x8zC2hYhR8ESlp5uJvpG0PqHxkvjQA4v-yvxXFvj+XabZMuOwNfbT0ZHwj6hXKp1Vf3i7zhyzHrkRCVD36B3GxHxxz654NSGKxg+BUg2B7hC+
openssl genrsa -out privkey.pem 1024
openssl rsa -in privkey.pem -pubout -out pubkey.pem

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 6
支持
分享
最新回复 (14)
雪    币: 1489
活跃值: (1093)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
2
沙发,好久没有见到这样的好文章了。
2012-7-30 19:52
0
雪    币: 221
活跃值: (2326)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
好文章!!!
2012-7-30 20:17
0
雪    币: 1024
活跃值: (240)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
4
学习学习 123456
2012-7-30 20:45
0
雪    币: 27
活跃值: (127)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
5
很有范,占坐观看。
2012-7-30 21:33
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
6
不错,学习学习
2012-7-30 21:43
0
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
不错,好文。。
2012-7-31 10:59
0
雪    币: 50
活跃值: (47)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
呵呵,俺又来顶啦。谢谢Hmily大侠无私奉献~
2012-7-31 19:49
0
雪    币: 149
活跃值: (101)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
9
好文章!学习学习
2012-12-1 19:20
0
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
谁个百度网盘英文版的
2014-5-19 10:40
0
雪    币: 156
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
好文章!!! 感谢分享!!
2014-11-29 20:26
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
Thank you very much for the post, was looking for this long time ago
2015-5-13 23:20
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
的fhhfhjfhh
2015-5-14 00:00
0
雪    币: 260
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
感谢分享!!!
2016-1-29 19:06
0
雪    币: 102
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
感谢大神分享,学习了
2016-12-3 11:12
0
游客
登录 | 注册 方可回帖
返回
//