主要目标:
不脱壳的情况下解除Delphi Application Peeper Pro v2.3.1.9的时间限制,并找到通用的方法(有待验证).
程序简介:
主要用来查看Borland Delphi (versions 2-6) and Borland
C++ Builder (versions 1-5)程序的窗口,控件信息,这个版本已经可以查看加壳了的程序,可能还有其它实用功能.
使用工具:
Trw2000,SuperBPM,ASProtect v1.2注册版,纸&笔
此软件分Pro版和Lite版,Pro是完整版,但要注册,程序用ASProtect 1.22加壳(Fi 2.49报告),注册方式完全采用ASProtect加壳时的30天试用选项,不注册会显示NAG提示剩下天数,过期后也能使用,但程序会不定时出现过期窗口.此软件已经由fwnl脱过壳,论坛精华里有,脱壳后程序同时去掉时间保护,因为ASProtect的注册保护都是在壳里的,但程序脱壳后热键Ctrl同时失去,About菜单也不能显示.
刚开始破解时我没想到它的注册是由ASProtect来保护的,因为ASProtect 1.2的过期对话框只是一个简单的MessageBox,于是先去找Keyfile保护,再找注册表,经过连日苦战才找到重点,因为本人水平有限,请大家指正!
我们先来看看用ASProtect加壳时的一些保护选项,主要有:天数限制,次数限制,未注册提示等,另外有个注册表选项,可以生成注册名对应的注册码,可选注册码的保存地址,生成注册码应该是用RSA的算法,随机生成一些数来参与运算,以保证每个程序不会重复.它在注册表里的保存的信息只有两个,一个是保存时间信息,一个是保存注册码,用ASProtect加壳后的程序在第一次运行时会生成保存时间的键值,保存注册码的键值要用户加入,程序第一次运行先检查注册码,如果没有就读时间信息,经过复杂运算得出剩下时间.所以我们的破解要从这两个地方入手.那怎么找到它们呢,对于注册码的保存就比较好找,因为ASProtect在加壳时注册码保存的地方有限制,它一定要保存在HKEY_CURRENT_USER\SOFTWARE\下,而且是保存在字符串值"Key"里的,所以用RegMon很容易就能找到.而时间标志的保存就没这么好找了,且来看看我是怎样找到的.
先用SuperBPM,用TRW载入主程序DAP_Pro.exe,下bpx regqueryvalueexa,F5,程序被拦下,F12退出系统CALL以后下d
edi看看程序读了什么内容,其中被我看到了53321-005-6928712-14614,这个看来是有用的东西,先到注册表里查找一下发现原来是我的ProductId,那就bpm来看看程序在干什么,程序先是用它做了个标准的MD5算法,再经过复杂的算法得到一个数据:AC
19 BC F0 4F F0 E7 29 6B 18 DB 35 EB 92 D5 F8,然后这串数据经过几个Call后得到了一个字符串"F0BC19AC-F04F-29E7-186B-35DBF8D592EB",好了,这个我还以为是注册码,谁知它最后变成了...CLSID\{.....}的字符串,呵呵,这不就是注册表里的键值吗,果然程序跟着就以此键值读取,中断在我下的断点里,读出键值"ltwZlD7mov/qsLc3",我们再下bpm设断,经过漫长的运算,发现这个键值算出的是现在的日期和安装日期,程序拿数据一比较,就得出了使用的天数.如果将此键值删除你会发现程序又可以使用30天了,当然这个主键你也可以用RegMon来找,只要找到以上形式的字符串就对了,另外过期后的形式类似这样:V4UTu+16
来个总结:受保护的程序先用ProductId(这个每台机都不会一样)来算出一组数,将此数转成字符,用它做为保存时间标志的主键,此主键保存在HKEY_LOCAL_MACHINE\SOFTWARE\CLASSES\CLSID\下,不好找,但可以用RegMon
找再以主键里的内容来判断.其实这里对于这次的目的来说已经是错误的了,因为程序只有没找到注册码或注册码错误才会运行到这里来的,这里我浪费了太多时间,但至少知道了ASProtect保护的时间标志是如何产生的.
既然我们知道注册码保存地址的限制,那么用RegMon很容易就找到程序在读HKEY_CURRENT_USER\Software\SecondDream\DAP_Pro这个主键,我们自己建立一个,并在里面建一个字符串值Key,为了保证调试过程顺利,我用ASProtect生成了一个长度和形式都应该正确的注册码填入,当然这个注册码对于DAP_Pro来说是假的,用TRW载入程序下bpx
regqueryvalueexa,很快发现程序用假注册码查表得到了一组数据,经过运算后得到一个128位的数据,然后再与其它两个128位的数据运算,然后......我就晕掉了,搞不懂程序的判断在何处,它的算法太复杂了,我只能跟着它运算的结果慢慢找!!
差点就放弃了,抱着试一试的态度决定调试一下ASProtect 1.2是怎样生成注册码和如何验证注册码的,看看能不能找到一点线索.当然为了方便观察内存里的数据我用了和刚才一样的注册名Sam.com生成了同样的注册码,然后发现程序是这样验证注册码的,下面是ASProtect的代码:
==Part I====================================================
0187:00449268
LEA ESI,[EBP+FFFFD800]
0187:0044926E INC
ESI
0187:0044926F MOV EDI,ESI
0187:00449271 PUSH EDI
0187:00449272 MOV
EAX,[EBX+04]
0187:00449275 PUSH EAX
0187:00449276
MOV EAX,[EBX+08]
0187:00449279 PUSH
EAX
0187:0044927A PUSH EDI
0187:0044927B CALL
00448894 <---变形后数据的运算--重点
0187:00449280 MOV
EAX,[EBX] <---位数80h
0187:00449282 MOV
AL,[EDI+EAX-01] <---结果的最后一位
0187:00449286 MOV
EDX,[EBX]
0187:00449288 MOV CL,[EDI]
<---结果的第一位
0187:0044928A MOV
[EDI+EDX-01],CL <---放到最后
0187:0044928E MOV
[EDI],AL <---最后一位放到第一
0187:00449290 MOV
EAX,[EBP+FFFFD7FC] <---结果首地址
0187:00449296 MOV
AX,[EAX]
0187:00449299 CMP AX,[00462814]
<---[00462814]==0
0187:004492A0 JZ 004492B9
<---跳就对啦
运算的结果:
0030:006CCFC5 00 00 02
00 2B 00 01 00-02 00 01 00 10 00 07 00 ....+...........
0030:006CCFD5 53
61 6D 2E 63 6F 6D 20-00 10 00 5C 58 84 9D 8A Sam.com ...\X劃?
0030:006CCFE5
EB 7E 26 E8 D3 76 57 9C-16 33 25 FF FF 00 00 00 雫&栌vW?3%...
.....后面全0共128位
总结:
如果在ASProtect中生成注册码时没有输入Hardware ID的话最后结果我的注册名是明码显示的,经过分析它的内容是这样的:数据前两位必须为0,最后一位也为0,第三个字节应该是标志,第5个字节2B表示后面有多少个字节的有用数据,有用数据以FF
FF结尾,第15字节7表示注册名的个数,注册名后的20应该是注册名结束的标志,再后面的数据应该是提供给程序用的,后面还要用到这16个数做运算,但用处何在我未搞清楚,DAP_Pro破解的不完全也就栽倒在这些数里,以上结果里的2个10应该是数据的开始标志.再接着往下看你会发现程序在复制我的注册名和16个字节的数据,如果这时你将内存里的Sam.com改成Sam
Von,ASProtect会显示对应此注册码的注册名是Sam Von,那么我们可以基本确定这就是最终结果了.到此我有一个想法,如果在DAP_Pro中,等程序运算完后我就它的结果改成以上结果会怎样呢?结果请看后部分.另外如果在生成注册码时输入了Hardware
ID的话,以上结果不会看到明码的注册名,数据也有变化,但ASProtect在这部分就做得比较简单,它只是用Hardware ID与上面的数据做xor运算而已.
我们先进入上面的Call看看它是怎样运算的:
0187:00448894 PUSH
EBP
0187:00448895 MOV EBP,ESP
0187:00448897
PUSH EBX
0187:00448898 PUSH ECX
0187:00448899
PUSH EDX
0187:0044889A PUSH ESI
0187:0044889B
PUSH EDI
0187:0044889C CLD
0187:0044889D
MOV ESI,[EBP+08] <---注册码的变形
0187:004488A0
LEA EDI,[00465B48]
0187:004488A6 MOV
ECX,80
0187:004488AB SHR ECX,02
0187:004488AE
MOV EDX,ECX
0187:004488B0 REP MOVSD
0187:004488B2
MOV ESI,[EBP+0C] <---数据1
0187:004488B5 LEA
EDI,[00465AC8]
0187:004488BB MOV
ECX,EDX
0187:004488BD REP MOVSD
0187:004488BF MOV
ESI,[EBP+10] <---数据2
0187:004488C2 LEA
EDI,[00465BC8]
0187:004488C8 MOV ECX,EDX
0187:004488CA REP MOVSD
0187:004488CC LEA
ESI,[00465B48]<---注册码的变形
0187:004488D2 LEA EDI,[00465C48]
0187:004488D8 MOV ECX,EDX
0187:004488DA
REP MOVSD
0187:004488DC MOV [00465DDC],EDX
0187:004488E2 MOV EAX,[00465AC8]
下面复杂的算法就不贴了,这里我们看到ASProtect将这3个数据连在一起去运算,它以这样的形式保存:
数据1
注册码变形
数据2
注册码变形
共512位,用它们来运算得到以上结果,如果你在上面的44889D处设一个断点,再按生成注册码,你会发现程序断下了,看esi的内容,原来注册码的变形变成了Part
I里的结果,也就是说生成注册码和验证注册码用到了同一个CALL,按F12退出来到下面的地方:
==Part II===============================================
0187:00449129 CALL 00448894
0187:0044912E MOV
ECX,[EBP-0C]
0187:00449131 MOV ECX,[ECX]
0187:00449133 LEA EDX,[EBP+FFFFD7C4] <---edx指向结果
0187:00449139 MOV EAX,[EBP-08]
0187:0044913C
CALL 004052AC
0187:00449141 MOV EAX,[EBP-10]
0187:00449144 POP EDI
0187:00449145
POP ESI
0187:00449146 POP EBX
0187:00449147 MOV ESP,EBP
0187:00449149
POP EBP
0187:0044914A RET
得到:
0030:006CA7D9 E2 D5 91 A8 1A 50 51 3A-58 7A 15 8D 3A 5D F6 6A 庹懆.PQ:Xz.?]鰆
0030:006CA7E9 63 96 BA C8 6B 49 81 EA-F4 B2 A4 FD CB F8 BB 76 c柡萲I侁舨锁籿
0030:006CA7F9 7B 85 D2 3C 8C 5B F7 6A-9F 86 C7 F6 B7 86 CA AB {呉<孾鱦焼泅穯诗
......共128位
这个结果好眼熟呀,原来这个就是注册码的变形,在DAP_Pro我也看到过,程序后面会用此数据查表得到注册码.好了,原来它生成注册码不是直接用用户名的,程序之前就用注册名做了一些运算,Part
I里的结果就是算注册码的数据,它们都用了同一个CALL,两个结果能否可逆呢?如果我找到DAP_Pro里的两个数据,将它复制到这里来,生成的注册码不就是正确的吗?于是我做了个试验,在生成注册码时我将数据1里的一个字节修改,生成另外一个注册码,在验证此注册码时同样修改数据1里的同一字节,结果....."错误的注册码",呵呵,看来我的想法是行不通的,程序应该还有其它的数据参与运算,这部分我就没精力再追了,这么强劲的算法应该是不可逆的.
既然软的不行我们就来硬的,我刚才讲过,如果在加壳的程序验证注册码算出结果后将内存里的结果改成Part I里的结果会怎样呢,因为它可以算是一个正确的结果呀,于是用了一些小程序来做试验,结果是完全可以的,它的判断很简单,只要结果里的格式符合标准就行了,后面那16个数据对一般程序一点影响也没有,程序就和已经注册的一模一样,这就是我所说的通用的方法.现在我们回到DAP_Pro中,方法是可行的,问题是如何找到Part
I中的代码,因为算法CALL后的一大段代码都是比较用的,还必须跳到很远的地方,也就是说我们有足够的地方来利用,我的想法是做一个Loader.
下面是DAP_Pro的代码,和Part I是否很相似,其它凡用ASProtect保护的程序都会有这一段,要注意的是因为这一段是壳解压缩后产生的,每台机都不一样,但同一台机第次运行都是一样的,这一段是不在任何领空的.
0187:0114EA2A 8B4304 MOV
EAX,[EBX+04]
0187:0114EA2D 8A4407FF MOV
AL,[EDI+EAX-01]
0187:0114EA31 8B5304
MOV EDX,[EBX+04]
0187:0114EA34 8A0F
MOV CL,[EDI]
0187:0114EA36
884C17FF MOV [EDI+EDX-01],CL
0187:0114EA3A 8807 MOV
[EDI],AL
0187:0114EA3C 8B85FC6FFEFF MOV
EAX,[EBP+FFFE6FFC]
0187:0114EA42 668B00
MOV AX,[EAX]
0187:0114EA45 663B0530231501 CMP
AX,[01152330]
0187:0114EA4C 7417
JZ 0114EA65 <---必须跳
0187:0114EA4E
C785F06FFEFF02000000 MOV DWORD [EBP+FFFE6FF0],02
0187:0114EA58
33C0 XOR EAX,EAX
0187:0114EA5A 5A POP
EDX
0187:0114EA5B 59
POP ECX
0187:0114EA5C 59
POP ECX
0187:0114EA5D 648910
MOV [FS:EAX],EDX
0187:0114EA60
E976010000 JMP 0114EBDB
0187:0114EA65
8B8DF46FFEFF MOV ECX,[EBP+FFFE6FF4]
0187:0114EA6B
49 DEC ECX
0187:0114EA6C 8B7B04 MOV
EDI,[EBX+04]
0187:0114EA6F 3BCF
CMP ECX,EDI
0187:0114EA71 7E25
JNG 0114EA98 <---一定跳,就是说我们至少有
0187:0114EA73
8D0431 LEA EAX,[ECX+ESI]
114EA2A<->114EA98这一段
0187:0114EA76 8BF0
MOV ESI,EAX 是可以拿来Patch的
0187:0114EA78 8BC1 MOV
EAX,ECX
0187:0114EA7A 99
CDQ
0187:0114EA7B F7FF
IDIV EDI
0187:0114EA7D 85C0
TEST EAX,EAX
0187:0114EA7F 7E17
JNG 0114EA98
0187:0114EA81 89C7
MOV EDI,EAX
0187:0114EA83
2B7304 SUB ESI,[EBX+04]
0187:0114EA86 56 PUSH
ESI
0187:0114EA87 8B4308 MOV
EAX,[EBX+08]
0187:0114EA8A 50
PUSH EAX
0187:0114EA8B 8B430C
MOV EAX,[EBX+0C]
0187:0114EA8E 50
PUSH EAX
0187:0114EA8F
56 PUSH ESI
0187:0114EA90 E8B7F7FFFF CALL 0114E24C
0187:0114EA95
4F DEC EDI
0187:0114EA96 75EB JNZ
0114EA83
我用了注册机编写器的内存补丁,补完后运行,哈哈!程序的NAG没有了,不过~~~~~~~倒是出现了一个提示框,显示Access
violation at address 0114C6F3. Write of address 8D07E07F.唉,写内存错误,于是下bpx 114C6F3
0187:0114C6C8 PUSH EBP
0187:0114C6C9 MOV
EBP,ESP
0187:0114C6CB PUSH EBX
0187:0114C6CC
PUSH ESI
0187:0114C6CD PUSH EDI
0187:0114C6CE
MOV EDI,01153554
0187:0114C6D3 MOV
EBX,[01153654]<---指向16位数据运算的结果
0187:0114C6D9 MOV
EAX,[01153658]
0187:0114C6DE MOV ECX,0C
0187:0114C6E3 CDQ
0187:0114C6E4 IDIV
ECX
0187:0114C6E6 MOV ESI,EAX
0187:0114C6E8
TEST ESI,ESI
0187:0114C6EA JNG 0114C733
0187:0114C6EC MOV EAX,[EDI]
0187:0114C6EE
MOV EAX,[EAX] <---eax=40000
0187:0114C6F0
ADD EAX,[EBX] <---eax+[ebx]=8D07E07F
0187:0114C6F2 INC EAX
0187:0114C6F3 MOV
DWORD [EAX],01<---错误在这里,[eax]等于8D07E07F
0187:0114C6F9
MOV EAX,[EDI]
0187:0114C6FB MOV
EAX,[EAX]
0187:0114C6FD ADD EAX,[EBX+04]
0187:0114C700
MOV EDX,[EBX+08]
0187:0114C703 CALL
0114C68C
也就是说Part I里的结果最后的16位数据被程序利用了,如果这里修改一下代码跳过的话出了这个CALL就到了DAP_Pro的领空,分析它的代码,是DAP_Pro在调用解压后的一个子程序,也许那16位数据是指向我们的注册信息或者某个窗体的数据,因为我们的数据和原定的不同,所以指针乱了,可能程序在启动时会显示一些信息,应该影响不大,因为关掉提示框后程序一切正常,只是About选项没了,这个情形和fwnl脱掉壳以后是一样的,还好这些数据不是拿来做功能限制的.由于我没有ASProtect的高版本,这一步只能跳过(谁能提供???),于是想办法跳过这个提示框.
出现提示框后下bpx lockmytask,分析代码:
0187:0044E46D
MOV EDX,[00407C60] <---指向提示框的标题
0187:0044E473
CALL 00402FA4 <---比较是否是发生错误的提示框
0187:0044E478
TEST AL,AL
0187:0044E47A JNZ 0044E4BF
<---跳就没事
0187:0044E47C CMP WORD
[EBX+BA],BYTE +00
Patch的时候把这里也改掉,问题是以后再有错误就没有提示啦!方法如下,用注册机编写器的内存补丁:
地址 长度 原码
修改
114EA2A 6 8B43048A4407
C70700000200
114EA30 7 FF8B53048A0F88
C747042B000100
114EA37 7 4C17FF88078B85
C7470802000100
114EA3E 7 FC6FFEFF668B00
C7470C10000700
114EA45 7 663B0530231501
C7471053616D2E <---此行原码各机不同,请自行修改
114EA4C
7 7417C785F06FFE C74714636F6D20
其它的照搬
114EA53 7 FF0200000033C0
C747180010005C
114EA5A 7 5A5959648910E9
C7471C58849D8A
114EA61 7 760100008B8DF4
C74720EB7E26E8
114EA68 7 6FFEFF498B7B04
C74724D376579C
114EA6F 7 3BCF7E258D0431
C74728163325FF
114EA76 7 8BF08BC199F7FF
C7472CFF000000
114EA7D 7 85C07E1789C72B
C7477C00000000
114EA84 7 7304568B430850
C6057AE44400EB <---Patch提示框
114EA8B 2
8B43 EB0B
现在,整个世界清静了,用此方法DAP_Pro的热键可用,其它功能未发现缺少,虽然此法对此程序破解并不算完美,但相信此方法对ASProtect
1.2以上加壳的程序破解时间限制都有效,至少我试过好几个都行.请大家帮忙测试.但此方法有个问题就是难以找到以上要修改的代码,我总结了个方法:先找到程序注册码保存的主键,输入任意大于8位的注册码,用TRW载入,下bpx
regqueryvalueexa,中断后下d *(esp+8),当看到内存里出现"Key"时,查找8A 0F 88 4C 17 FF或33 C0 5A 59
59 64 89 10 E9,附近就是了.如果找不到的话就只能慢慢跟了----痛苦呀.如果你想用你自己的注册名可以用ASProtect生成,方法参阅Part
I&II
另外在追注册码时经常会碰到一些SEH,这东西我不大懂,如下:
0187:0114FDE9
PUSH BYTE +10
0187:0114FDEB PUSH DWORD 0115366C
0187:0114FDF0 MOV EAX,[EBX+02] <---EBX=0
0187:0114FDF3 PUSH EAX
0187:0114FDF4 LEA
EAX,[EBX+06]
0187:0114FDF7 PUSH EAX
0187:0114FDF8 CALL 0114BFF4
F8或F12的话就完了,如果不幸来到此只能重来,记住这个Call不要进入,只能F10代过,真是所谓的步步为营呀,所以我对脱壳不感冒:-)
-=End=-
_/_/_/
_/ _/_/_/ _/_/_/ _/_/
_/_/ _/ _/ _/ _/ _/
_/ _/ _/ _/ _/
_/
_/_/_/ _/_/_/ _/ _/
_/
Sam.com
6:15 2002-4-27
- 标 题:破解用ASProtect v1.2x加壳后程序使用限制的通用方法 (15千字)
- 作 者:Sam.com
- 时 间:2002-4-27 6:25:57
- 链 接:http://bbs.pediy.com