水晶报表4.6 注册码的破解

    这是我注册看雪技术论坛时写的学习心得,现在贴上来,以给破解新手们学习使用。本篇破解文章写的十分详细,加了很多注释,可学习些破解知识,也能学习些汇编语言知识。
    对于破解,我还算新手,因为工作繁忙,只能在业余时间学习了,现在啊,老板把我们的业务时间都快占完了,唉,没办法!

一、破解简述

    我是一名软件工程师,很喜欢在业务时间内做软件的反向工程(我觉得这个
词语比破解听起来柔和),为了进一步学习,很想注册看雪技术论坛的帐号,发
现停止注册了。看了你们的注册条件,我觉得自己基本可以达到要求,所以就连
夜做了这篇破解文章做为心得,希望能通过。
虽然我做过很多破解,但一般基本上都是急切使用的国内商业软件(控件
多),为做私活使用,所以一般不能张扬,也不能发表破解心得。我对汇编语言
和基本的反汇编以及跟踪工具都很熟悉,目前正在详细学习PE格式的规范和加
壳脱壳的原理。因为我以前都是使用脱壳工具做,最近想玩一个游戏,发现它是
用AsProtect v1.23 RC4 加的壳,搜索了互联网,才发现即使手工脱壳也很难,
但我还没手工脱壳的经验。这个游戏是Animal Attack v1.03。
    写这篇心得,我考虑了很多因素,一方面希望能通过注册,另一方面希望能
交流学习,发表在看雪技术论坛上,所以很细心,加上了详细的注释和说明。VB
是我使用的一种编程工具,里面有个水晶报表4.6(Crystal Reports 4.6),
我以前使用其做报表,现在基本不用了。那天晚上我思索做什么软件的破解好点,
如果做流行软件的,恐怕有抄袭嫌疑,所以就选了这个偏门的软件做破解了。
水晶报表4.6 虽然要求注册,但不注册也可以全功能使用,只是每次使用要
弹出注册窗口而已。它是VB6.0 附带的报表制作工具,在VB60 安装盘的
“\COMMON\TOOLS\VB\CRYSREPT”目录下,安装后在开始-程序菜单有ITEM,可
单独运行,报表做完了再挂到VB中使用。
好了,下面开始我的破解说明。
这里先讲一讲其检测密码的方法,然后再针对程序来作说明。
这个软件不需要安装者其他的信息,只要你输入密码即可,所以不存在由其
他信息得到密码的方法,而就是在你输入的密码上做文章,一般是密码固定或者
由密码的某些位计算其他位,密码只要满足这个规律即可。经分析,水晶报表就
是采用后一种方法来检测密码的。
虽然输入密码框最多可输入11位字符,但经分析程序,其密码长度固定为
10 位。这在以后再作详细分析。
1、随意输入密码4848484848(这里我一直继承如枫大虾的习惯了)。
2、程序将你输入密码的1、8、9、2、7、3、6 位字符按顺序取出组成另外
一个字符串4848448,以后分析可知,它就是利用这7位字符来计算其他3位字
符的。
3、程序计算其它3位字符时需要用到一个查询表,这个表是执行程序内置
的,程序计算正确密码时查阅使用,我把这个表弄了下来,见下附表(一)。
4、将字符4848448(ASCII 码为34383438343438)第一位数34*2 得68,查
表68位置得76D7。
5、76D7右移两位得76,第2个数38 异或76得4E;76D7左移两位得D700,
4E*2 得9C,查表9C 位置得A90A,异或D700 得7E0A。
6、7E0A右移两位得7E,第3个数34 异或7E得4A;7E0A左移两位得0A00,
4A*2 得94,查表94 位置得E98E,异或0A00 得E38E。
7、E38E右移两位得E3,第4个数38 异或E3得DB;E38E左移两位得8E00,
DB*2 得1B6,查表1B6 位置得7A16,异或8E00 得F416。
8、F416右移两位得F4,第5个数34 异或F4得C0;F416左移两位得1600,
C0*2 得180,查表180 位置得D94C,异或1600 得CF4C。
9、CF4C右移两位得CF,第6个数34 异或CF得FB;CF4C左移两位得4C00,
FB*2 得1F6,查表1F6 位置得5E74,异或4C00 得1274。
10、1274右移两位得12,第7 个数38异或12 得2A;1274左移两位得7400,
2A*2 得54,查表54 位置得8528,异或7400 得F128。
11、F128 取非得0ED7,除3E8,取整得3,余数为31F。
12、31F 对A 取模,得9,加30 得39(即数字9),判断所得数是否小于等
于39,如小于等于39,则定出第一个数;否则再加27。从而得出第一个数39,
即数字9。
13、31F除A取整得4F,程序判断取整后是否得0,如不为0,重复第12
步。
14、4F对A取模,得9,加30得39(即数字9),所得数小于等于39 吗,
如小于等于39,定出第一个数;否则再加27。从而得出第二个数39,即数字9。
15、4F除A取整得7,程序判断取整后是否得0,如不为0,重复第12 步。
16、7对A取模,得7,加30 得37(即数字7),所得数小于等于39吗,
如小于等于39,定出第一个数;否则再加27。从而得出第二个数37,即数字7。
17、7 除A 取整得0,程序判断取整后是否得0,为0,得出三个数串997。
18、将997 的倒数第N 位与正数第N 位交换,得数串799。
19、将数串799 依次替换你输入的密码的第4、5、10 位,即程序以前抽取
7 位后剩下的那3 位。如下:4848484848-> 4847984849,从而密码验证结束。
20、从上可知,密码4847984849 满足验证规律,从而得出我们的注册码:
4847984849。根据以上规律我们将知,水晶报表4.6 的注册码是几乎无穷尽的。
如以3737373737注册,可测得得密码为:3739673730;以YAOXIAOJUN 注册,可
测得密码为:YAO98AOJU2。YAOXIAOJUN 是我的名字的拼音,我叫姚晓军。

附表一

地址 字节内容
位置 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0    00 00 21 10 42 20 63 30 84 40 A5 50 C6 60 E7 70
1    08 81 29 91 4A A1 6B B1 8C C1 AD D1 CE E1 EF F1
2    31 12 10 02 73 32 52 22 B5 52 94 42 F7 72 D6 62
3    39 93 18 83 7B B3 5A A3 BD D3 9C C3 FF F3 DE E3
4    62 24 43 34 20 04 01 14 E6 64 C7 74 A4 44 85 54
5    6A A5 4B B5 28 85 09 95 EE E5 CF F5 AC C5 8D D5
6    53 36 72 26 11 16 30 06 D7 76 F6 66 95 56 B4 46
7    5B B7 7A A7 19 97 38 87 DF F7 FE E7 9D D7 BC C7
8    C4 48 E5 58 86 68 A7 78 40 08 61 18 02 28 23 38
9    CC C9 ED D9 8E E9 AF F9 48 89 69 99 0A A9 2B B9
A    F5 5A D4 4A B7 7A 96 6A 71 1A 50 0A 33 3A 12 2A
B    FD DB DC CB BF FB 9E EB 79 9B 58 8B 3B BB 1A AB
C    A6 6C 87 7C E4 4C C5 5C 22 2C 03 3C 60 0C 41 1C
D    AE ED 8F FD EC CD CD DD 2A AD 0B BD 68 8D 49 9D
E    97 7E B6 6E D5 5E F4 4E 13 3E 32 2E 51 1E 70 0E
F    9F FF BE EF DD DF FC CF 1B BF 3A AF 59 9F 78 8F
10   88 91 A9 81 CA B1 EB A1 0C D1 2D C1 4E F1 6F E1
11   80 10 A1 00 C2 30 E3 20 04 50 25 40 46 70 67 60
12   B9 83 98 93 FB A3 DA B3 3D C3 1C D3 7F E3 5E F3
13   B1 02 90 12 F3 22 D2 32 35 42 14 52 77 62 56 72
14   EA B5 CB A5 A8 95 89 85 6E F5 4F E5 2C D5 0D C5
15   E2 34 C3 24 A0 14 81 04 66 74 47 64 24 54 05 44
16   DB A7 FA B7 99 87 B8 97 5F E7 7E F7 1D C7 3C D7
17   D3 26 F2 36 91 06 B0 16 57 66 76 76 15 46 34 56
18   4C D9 6D C9 0E F9 2F E9 C8 99 E9 89 8A B9 AB A9
19   44 58 65 48 06 78 27 68 C0 18 E1 08 82 38 A3 28
1A   7D CB 5C DB 3F EB 1E FB F9 8B D8 9B BB AB 9A BB
1B   75 4A 54 5A 37 6A 16 7A F1 0A D0 1A B3 2A 92 3A
1C   2E FD 0F ED 6C DD 4D CD AA BD 8B AD E8 9D C9 8D
1D   26 7C 07 6C 64 5C 45 CD AA BD 8B AD E8 9D C9 8D
1E   1F EF 3E FF 5D CF 7C DF 8B AF BA BF D9 8F F8 9F

二、详细说明

破解工具使用的是WINSOFTICE,破解环境是WIN98,2000 下黑屏太小,看
不清楚。
以下为详细跟踪的步骤:
1、启动水晶报表执行程序,如未注册,则弹出要求注册窗口,随意输入密码:YAOXIAOJUN
2、按CTRL+D,进入WINSOFTICE 画面,键入:S 30:0 LFFFFFFFF ‘YAOXIAOJUN’,
可得一地址:0030:802D2A52。
3、下断点,BPM 30:802D2A52
4、F5 返回程序界面,按Done 进行注册,程序被中断。中断处代码见下:
0117:9EAA REPZ REPZ MOVSD
0117:9EAE POP ECX
0117:9EB0 AND ECX,03
0117:9EB4 REPZ MOVSB
这段代码将你输入的密码转储到ES:EDI 处,即地址:2E67:0,与程序访问地址:013F:008CEF0C 是同一块内存空间。
5、F10 单步运行追踪至:
0137:00DDD84B CALL 00DDEC60 ;测试输入密码的CALL 语句,它返回将影响EAX 值
0137:00DDD84B TEST EAX,EAX ;测试EAX 寄存器值是否为0,为0 将错误
0137:00DDD84B JNZ 00DDD86F ;如果不为0,则跳转至注册程序,否则将弹出错误窗口
根据分析知,如果你输入的密码不正确,EAX 值为0;密码正确,EAX 值将为1。
好了,F8 追入CALL 00DDEC60 看看程序是如何进行注册码验证的。
6、追入CALL 程序后,按F10 单步运行直至下列代码:
0137:00DDEC6A CALL [00DF2454] ;接收并计算密码的长度,并将值返回EAX 寄存器。
0137:00DDEC70 CMP EAX,0A ;测试密码长度是否为10 位
0137:00DDEC73 JZ 00DDEC7F ;如果是10 位,则跳转,继续判断其他项。
0137:00DDEC75 XOR EAX,EAX ;如果不是10 位,则将EAX 直接清0
0137:00DDEC77 POP EDI ;由上面分析大家知,EAX 为0 将错误,导致程序跳转
0137:00DDEC78 POP ESI ;注册失败窗口。
0137:00DDEC79 ADD ESP,1C ;
0137:00DDEC7C RET 0004 ;返回,不再作其他判断。
计算密码长度的CALL 就不作详细分析了,代码很简单。
7、如果密码长度为10 位,程序将跳至00DDEC7F(参见步骤6),这段代码将你输入密
码的第1、8、9、2、7、3、6 位抽取出来形成另外一个字符串,即将013F:008CEF0C处的
测试密码YAOXIAOJUN的1、8、9、2、7、3、6 位抽取出来放在013F:008CEEE0处,为YJUAOOA。
以下为00DDEC7F 处代码:
0137:00DDEC7F MOV AL,[ESI] ;密码的第1 位,“Y”->AL
0137:00DDEC81 MOV CL,[ESI+07] ;密码的第8 位,“J”->CL
0137:00DDEC84 MOV DL,[ESI+08] ;密码的第9 位,“U”->DL
0137:00DDEC87 MOV [ESP+10],AL ;存放第一位“Y”至目的串(013F:008CEEE0)
0137:00DDEC8B MOV AL,[ESI+01] ;密码的第2 位,“A”->AL
0137:00DDEC8E MOV [ESP+11],CL ;存放第二位“J”至目的串
0137:00DDEC92 MOV CL,[ESI+06] ;密码的第7 位,“O”->CL
0137:00DDEC95 MOV [ESP+12],DL ;存放第三位“U”至目的串
0137:00DDEC99 MOV DL,[ESI+02] ;密码的第3 位,“O”->DL
0137:00DDEC9C MOV [ESP+13],AL ;存放第四位“A”至目的串
0137:00DDECA0 MOV AL,[ESI+05] ;密码的第6 位,“A”->AL
0137:00DDECA3 PUSH 07 ;所取目的字符串长度07 入栈
0137:00DDECA5 MOV [ESP+18],CL ;存放第五位“O”至目的串
0137:00DDECA9 MOV [ESP+19],DL ;存放第六位“O”至目的串
0137:00DDECAD LEA ECX,[ESP+14] ; 将目的串{YJUAOOA}地址装入ECX 寄存器
0137:00DDECB1 MOV [ESP+1A],AL ;存放第七位“A”至目的串
0137:00DDECB5 MOV BYTE PTR [ESP+1B],00 ;目的串尾加串结束标志“00”
0137:00DDECBA PUSH ECX ;将目的串的内存地址入栈
0137:00DDECBB CALL 00DD6730 ;调用其他判断程序,第8 步将详细跟踪
8、接下来的CALL 00DD6730 主要是针对字符串“YJUAOOA”逐位进行运算、查表,从而
最后得出一个运算值,然后在此值基础上再进行别的运算。先看代码:
0137:00DD6730 XOR AX,AX ;AX 清0
0137:00DD6733 PUSH ESI ;原密码串“YAOXIAOJUN”地址先入栈
0137:00DD6734 MOV EDX,[ESP+0C] ;串“YJUAOOA”的长度07 送EDX
0137:00DD6738 PUSH EDI ;EDI 入栈
0137:00DD6739 MOV ECX,EDX ;长度07 送ECX
0137:00DD673B DEC EDX ;EDX 减1
0137:00DD673C TEST ECX,ECX ;测试ECX 是否为0
0137:00DD673E JLE 00DD6770 ;如果为0,则跳转
以上代码只是一个类似容错的处理,可不深究,以下代码是对串“YJUAOOA”的每位进
行运算及查表的,大家得仔细分析一下。
0137:00DD6740 MOV ESI,[ESP+0C] ;串“YJUAOOA”的首地址送ESI。
运算循环开始,共7 次,即程序在倒计数,直至为0 结束循环。
0137:00DD6744 MOV DI,AX ;这里AX 存放上一位运算得出的值,对于第1 位为0
0137:00DD6747 INC ESI ;ESI 增1,指向串“YJUAOOA”当前位的下1 位
0137:00DD6748 SHR DI,08 ;对上一位运算得出的值进行右移两位
0137:00DD674C MOVZX CX,BYTE PTR[ESI-01] ;取出当前位,送CX
0137:00DD6751 XOR CX,DI ;将当前位与DI 进行异或运算,DI 值见前SHR DI,08
0137:00DD6754 SHL AX,08 ;将上一位运算得出的值进行左移两位
0137:00DD6758 MOVZX EDI,CX ;将CX 的值由16 位转换为32 位
0137:00DD675B MOV CX,[EDI*2+00DEF1E0] ;根据EDI*2 的值查表,查出的值送CX
0137:00DD6763 MOV EDI,EDX ;将计数存于EDI
0137:00DD6765 XOR CX,AX ;查表值与AX 值异或,值送CX,AX 值见SHL AX,08
0137:00DD6768 DEC EDX ;EDX 预减1
0137:00DD6769 MOV AX,CX ;将本位运算得值送AX
0137:00DD676C TEST EDI,EDI ;测试计数是否为0
0137:00DD676E JG 00DD6744 ;不为0 则跳回循环。
以上完成7 位的处理最后得值“778F”,下面完成取非运算
0137:00DD6770 NOT AX ;对“778F”取非得“8870”
0137:00DD6773 POP EDI ;弹出EDI
0137:00DD6774 POP ESI ;弹出ESI
0137:00DD6775 RET ;返回调用处下一语句
9、程序返回后按F10 单步运行直至以下代码处,这段代码完成除3E8并取余数运算。
具体如下:
0137:00DDECC0 ADD ESP,08
0137:00DDECC3 MOV ECX,000003E8 ;置除数“3E8”送ECX
0137:00DDECC8 MOVZX EAX,AX ;将“8870”存为32 位数字
0137:00DDECCB SUB EDX,EDX ;清除“除运算”时余数存储寄存器
0137:00DDECCD DIV ECX ;EAX / ECX,商送EAX,余数送EDX(为3A0)
0137:00DDECCF PUSH EDX ;将“3A0”入栈
0137:00DDECD0 PUSH 00DEFB0C ;
0137:00DDECD5 LEA EDX,[ESP+10] ;
0137:00DDECD9 PUSH EDX ;
0137:00DDECDA CALL [00DF25D8] ;
以上的CALL 根据“3A0”计算其它3 位字符,即第4、5、10 位,为了完整的查看源代
码,我们先不追进去(见第10步),直接按F10 运行完此CALL 语句,得一字符串“928”,
存放于[ESP+08]内容区域。注意,程序将在字符串“YJUAOOA”后即013F:008CEEE8 处存放
正确的密码,键入:D 013F:008CEEE0 将数据窗口切换此处,睁大眼睛看看程序如何得出
正确密码!
0137:00DDECE0 LEA ECX,[ESP+24] ;将正确密码开始地址存入ECX,即008CEEE8
0137:00DDECE4 ADD ESP,0C
0137:00DDECE7 MOV EAX,[ESI] ;将原密码串的前4 位“YAOX”存入EAX
0137:00DDECE9 MOV EDX,[ESI+04] ;将原密码串的中间4 位“IAOJ”存入EDX
0137:00DDECEC MOV [ECX],EAX ;将“YAOX”搬至正确密码处,即013F:008CEEE8
0137:00DDECEE MOV EAX,[ESI+08] ;将原密码串的后2 位“UN”存入EAX(含结束符00)
0137:00DDECF1 MOV [ECX+04],EDX ;将“IAOJ”搬至正确密码处,即013F:008CEEEC
0137:00DDECF4 MOV DL,[ESP+09] ;将字符串“928”的第2 位“2”存入DL
0137:00DDECF8 MOV LEA EDI,[ESP+18] ;正确密码存储位置存入EDI,即:008CEEE8
0137:00DDECFC MOV [ECX+08],EAX ;将“UN”及结束符搬至正确密码处,即013F:008CEEF0
0137:00DDECFF MOV CL,[ESP+08] ;将字符串“928”的第1 位“9”存入DL
0137:00DDED03 MOV AL,[ESP+0A] ;将字符串“928”的第3 位“8”存入DL
0137:00DDED07 MOV [ESP+1B],CL ;用“9”替换掉正确密码存储位置第4 位
0137:00DDED0B MOV [ESP+21],DL ;用“2”替换掉正确密码存储位置第10 位
0137:00DDED0F MOV ECX,0000000C ;
0137:00DDED14 MOV [ESP+1C],AL ;用“8”替换掉正确密码存储位置第5 位
至此,大家在013F:008CEEE8 处应能看到正确密码:“YAO98AOJU2”,至此,你可以
停止跟踪了,因为,知道它的一个密码就可完成注册。不过,为了交作业,我要追踪到程序
的各层代码。下来看他如何比较并置标志寄存器EAX,密码正确,EAX 置为1,密码错误,
EAX 置为0,好了,往下看吧。
0137:00DDED18 SUB EAX,EAX ;EAX 清0,将存放密码正确与否的标志位
0137:00DDED1A REPZ CMPSB ;将计算出的正确密码与输入的密码比较
0137:00DDED1C JZ 00DDED23 ;如果相等则跳至00DDED23
0137:00DDED1E SBB EAX,EAX ;如果不相等,则强行置EAX 为1
0137:00DDED20 SBB EAX,-01 ;
0137:00DDED23 TEST EAX,EAX ;测试EAX 是否为0,密码正确时,为0,否则为1
0137:00DDED25 MOV EAX,00000001 ;将EAX 强行置为1
0137:00DDED2A JZ 00DDED2E ;如果上上一步EAX 为0,则跳至00DDED2E
0137:00DDED2C XOR EAX,EAX ;如果上上一步EAX 为1,则强行至EAX 为0
0137:00DDED2E POP EDI ;弹出EDI
0137:00DDED2F POP ESI ;弹出ESI
0137:00DDED30 ADD ESP,1C ;
0137:00DDED33 RET 0004 ;返回
至此,整个CALL 00DDEC60 将告结束,参见步骤5。
10、别忘了,还有一个CALL咱们在前面跳过了的,就是CALL [00DF25D8],见第9 步,
这个CALL 语句,将根据“3A0”计算其它3 位字符,即第4、5、10 位,得一字符串“928”,
存放于[ESP+08]内容区域。跟我进入吧(需要重新跟踪到此处停下)。
F8 追入此CALL,F10 单步运行至:
0137:BFF7A39F CALL BFF79753
此CALL 将对“3A0”进行处理。按F8 再追进去,按F10 单步运行至以下代码处:
0137:BFF79770 MOV EDI,[ESP+14] ;所得出的3 位字符位置送EDI,即:013F;008CEED8
0137:BFF79774 MOV EBX,[ESP+18] ;即“3A0”送EBX
0137:BFF79778 MOV EBP,[ESP+20] ;“0A”送EBP
循环计算3 位中每位的字符,共3 次
0137:BFF7977C MOV EAX,EBX ;上次循环结果送EAX,对于第一次,EAX 等于“3A0”
0137:BFF7977E SUB EDX,EDX ; 清除除法运算的余数寄存器
0137:BFF79780 DIV EBP ;EAX / EBP,商送EAX,余数送EDX
0137:BFF79782 MOV ECX,EDX ;取余数转送ECX
0137:BFF79784 MOV EAX,EBX ;重新将上次循环结果送EAX,对于第一次,EAX 等于“3A0”
0137:BFF79786 SUB EDX,EDX ;清除除法运算的余数寄存器
0137:BFF79788 ADD ECX,30 ;计算得的余数加以“30”
0137:BFF7978B DIV EBP ;EAX / EBP,商送EAX,余数送EDX
0137:BFF7978D MOV EBX,EAX ;取商送EBX
0137:BFF7978F CMP ECX,39 ;比较余数是否大于39,即数字“9”
0137:BFF79792 JBE BFF79798 ;如果不大于39,则跳
0137:BFF79794 ADD ECX,[ESP+24] ;如果大于39,则再加以27 (注:[ESP+24]值为27)
0137:BFF79798 INC ESI ;增加ESI
0137:BFF79799 MOV [EDI],CL ;将得到的余数计算值存于013F:008CEED8,做为1
个数
0137:BFF7979B INC EDI ;指针指向第2 个字符位置
0137:BFF7979C CMP ESI,[ESP+1C] ;用处不明
0137:BFF797A0 JG BFF797A6 ;用处不明
0137:BFF797A2 TEST EBX,EBX ;判断所除的商是否为0
0137:BFF797A4 JNZ BFF7977C ;不为0,再次进入循环,直至为0。
经过以上运算,在内存地址013F:008CEED8 处得一字符串:“829”
继续往下走,直至返回调用处。
11、还没完成呢,应该还有一步,就是将所得值“829”的最后一位与第一位的值交换,
得“928”。接上一步,按F10 单步运行至以下代码:
0137:BFF7A4D8 CALL BFF797AF ;这个CALL 完成以上功能,F8 追进去
见以下代码:
0137:BFF797AF MOV EAX,[ESP+08] ;“829”中最后一个字符“9”的内存地址送EAX
0137:BFF797B3 PUSH EBX
0137:BFF797B4 MOV ECX,[ESP+08] ;“829”中第一个字符“8”的内存地址送EAX
0137:BFF797B8 CMP EAX,ECX ;比较是否比较完毕,即将首尾地址比较。
0137:BFF797BA JBE BFF797CA ;如果比较完毕,则跳转
循环开始,共1 次
0137:BFF797BC MOV DL,[ECX] ;将正数第N 个字符送DL
0137:BFF797BE MOV BL,[EAX] ;将倒数第N 个字符送BL
0137:BFF797C0 MOV [ECX],BL ;将倒数第N 个字符填入正数第N 个位置
0137:BFF797C2 INC ECX ;正数指针加1,定位于正数第N+1 位
0137:BFF797C3 MOV [EAX],DL ;将正数第N 个字符填入倒数第N 个位置
0137:BFF797C5 DEC EAX ;倒数指针减1,定位于倒数第N-1 位
0137:BFF797C6 CMP EAX,ECX ;比较倒数指针是否大于正数指针,即比较完否
0137:BFF797C8 JA BFF797BC ;如果尚未比较完毕,则跳转BFF797BC
0137:BFF797CA POP EBX
0137:BFF797CB RET 0008
完成以上程序后,原来的“829”变成了“928”。

三、结束语

经过以上分析,水晶报表密码计算方法是算麻烦的,它由输入密码的某些位来计算其它位,中间使用了查表的方法,必须找到这个表才可以明确跟踪。不过,由于其计算密码的方法每次启动是固定的,所以逐步跟踪下去也比较容易,关键是要有一定的汇编语言基础。
我深刻地知道,要作为一名真正的Crack 高手,就应该多看别人的破解心得,多尝试一些破解工作,总结一些经验,更知道破解往往是以小时为单位的,得到一个密码容易,但要了解它的整个过程,将要付出更多的时间和精力,而对于Cracker 来说,应该打破沙锅干到底,否则,永远不会进步!