本文部分代码的HTML文件格式不太好,你也可以查看文本格式:点击查看.
一、前言
好久没有写破解心得了,前不久在完善了自己的两个软件后(重写了核心代码),终于想找一个软件来练练了,在一张最新D版光盘上找到了这个 File Protector 2000,版本旧了点,于是去作者的主页下了一个最新版本2001 v2.05,用了一下,感觉挺不错的,于是就将它CRACK了,另外也为了丰富一下我的网站, 于是就写下了这篇详细的破解过程。总的来说,这个软件还是很好破的,首先它没有压缩,更没用ASprotect之类的反CRACK加密,所以拿到手就可动手去Tracking,说了这些,那就让我们切入正题,Let's goooooooo~!
对了,别忘了去我的主页看看,那里有精彩的软件破解心得,软件汉化,以及本人自己写的实用软件呦!
二、TRACK工具
这次用到了TRW2000 v1.23,还有W32DASM、HIEW。
三、破解实录
每次我们在拿到一个软件之前,首先用FS、FI、GT2000之类的分析工具去分析一下该软件是被什么压缩软件压缩的,(本人最喜欢用的PEiDentifier,目前版本为0.7B,用它大都数经压缩软件压缩的都能查到),这次也不例外,经用PEiD分析后,发现这个软件是VC++写的,没有用压缩软件压缩。
没有压缩就好办,免得我们还要将它剥壳(麻烦)。
启动File Protector 2001(以下简称FP),弹出注册窗口,发现有注册名称,公司名称,以及注册序列号三项。胡乱填一下,Name:BitRanger,Commpany:BitRanger(Bit巡逻兵),Serial:123456789,注册,弹出“Registration failed !”,(好办,不像有点软件,注册序列号填入后,是在启动时验证,而不给出任何的错误提示信息),既然这个软件有错误信息框弹出,那我们就先用W32DASM打开它。
(1) 用W32DASM破获 --==>>假破
用W32DASM打开后,“串式参考”,查找到"Registration failed !",看以下代码:
:0040D2D4 85C0 test eax, eax
:0040D2D6 751E jne 0040D2F6
:0040D2D8 50 push eax
* Possible StringData Ref from Data Obj ->"Error"
:0040D2D9 686C964100 push 0041966C
* Possible StringData Ref from Data Obj ->"Registration failed !" <=-
向上看,有一句判断语句:
test eax,eax ,jne ...,
if ( eax == 0 )
弹出错误
else
跳转正确执行 --=>> 即弹出"Registration sucessfully!"注册成功
好吧,那就让我们改 jne 为 je ,借助HIEW 的F3,F2可直接修改ASM语句。
继续返回软件注册窗口,注册,弹出"Registration sucessfully!",好高兴呀,难道就这样给破了吗?;-)嘻,也太...
别高兴的太早了,进入程序主界面后,发现还有Unregisted!字样,;-(怎样,不是显示已注册了吗?进入“关于”,发现软件还是没有被注册!:(
怒发冲冠(有冠吗?)!立即操起倚天剑TRW,砍它!!!
(2) 用TRW2000破 --==>>彻底搞定
打开TRW2000,Browse找到这个FP,Load,OK,进入TRW2000窗口了吧,F4,返回进入FP的注册窗口。
按照常理,我们填入Name:BitRanger,Commpanny:BitRanger(Bit巡逻兵),Serial:123456789。
Ctrl+N,进入TRW,下 bpx hmemcpy (内存复制) ,F4,返回软件注册窗口,“注册”啦,OK,被TRW正常拦截。
bd 1 别忘了;),别告诉我不知道他的意思;-)
F12 9次,F10几次吧,我们来到这个地址(为什么要到这个地址,你从这个地址往下再F10几次看看):
015F:0040D2C6 LEA ECX,[ESP+18]
015F:0040D2CA PUSH ECX
015F:0040D2CB LEA ECX,[ESP+10]
015F:0040D2CF CALL 0040F290 <<==-- 解密算法
015F:0040D2D4 TEST EAX,EAX <<==-- 比较EAX
015F:0040D2D6 JNZ 0040D2F6 <<==-- 不等,跳,否则出错
Ok, 在 0040D2CF 处,我们F8直接进入,下面,让我们进入神奇的bit世界吧~!去领略BILL构筑的天堂,去感悟人们智慧的结晶!
以下代码,我直接写了一些注释,具体算法分析附在代码之后。
还需要清楚一点的是,以下分析中,* 号代替 30 < * < 46 ,至于为什么,以下分析中我会讲到,还有序列号,我以具体位数代替,譬如第1位序列号,我以0代替,第10位,我以A代替,类推。
015F:0040F290 MOV ECX,[ESP+04] <<=-- ECX 密码存放地址
015F:0040F294 SUB ESP,BYTE +08
015F:0040F297 MOV AL,2D <<=-- AL = 2D = '-'
015F:0040F299 MOV DL,[ECX+04] <<=-- DL = 4 = 第4位序列号
015F:0040F29C PUSH EBX
015F:0040F29D CMP DL,AL <<=-- 4 = '-' ?
015F:0040F29F JNZ NEAR 0040F54F <<=-- 不等错
015F:0040F2A5 CMP [ECX+07],AL <<=-- 7 = '-' ?
015F:0040F2A8 JNZ NEAR 0040F54F
015F:0040F2AE CMP [ECX+0B],AL <<=-- B = '-' ?
015F:0040F2B1 JNZ NEAR 0040F54F
015F:0040F2B7 CMP [ECX+0D],AL <<=-- D = '-' ?
015F:0040F2BA JNZ NEAR 0040F54F
015F:0040F2C0 CMP [ECX+1C],AL <<=-- 1C = '-' ?
015F:0040F2C3 JNZ NEAR 0040F54F
------------------------------==============>>>>>>^^^由以上已看出:
序列号的4,7,B,D,1C位必须为'-'
继续...
015F:0040F2C9 MOV AL,[ECX+0F] <<=-- AL = 0F
015F:0040F2CC CMP AL,30 <<=-- OF < 30 ?
015F:0040F2CE JL NEAR 0040F54F
015F:0040F2D4 CMP AL,46
015F:0040F2D6 JG NEAR 0040F54F <<=-- OF > 46 ?
-------------------------------===========>>>>>>>>^^^^现在知道了吧,我 为什么为 * 号代替 30 < * < 46了
继续...
所以序列号0F为 *
015F:0040F2DC MOV AL,[ECX+10]
015F:0040F2DF CMP AL,30
015F:0040F2E1 JL NEAR 0040F54F
015F:0040F2E7 CMP AL,46
015F:0040F2E9 JG NEAR 0040F54F <<=-- 10 = *
015F:0040F2EF MOV AL,[ECX+11]
015F:0040F2F2 CMP AL,30
015F:0040F2F4 JL NEAR 0040F54F
015F:0040F2FA CMP AL,46
015F:0040F2FC JG NEAR 0040F54F <<=-- 11 = *
015F:0040F302 MOV AL,[ECX+12]
015F:0040F305 CMP AL,30
015F:0040F307 JL NEAR 0040F54F
015F:0040F30D CMP AL,46
015F:0040F30F JG NEAR 0040F54F <<=-- 12 = *
015F:0040F315 MOV AL,[ECX+15]
015F:0040F318 CMP AL,30
015F:0040F31A JL NEAR 0040F54F
015F:0040F320 CMP AL,46
015F:0040F322 JG NEAR 0040F54F <<=-- 15 = *
015F:0040F328 MOV AL,[ECX+16]
015F:0040F32B CMP AL,30
015F:0040F32D JL NEAR 0040F54F
015F:0040F333 CMP AL,46
015F:0040F335 JG NEAR 0040F54F <<=-- 16 = *
015F:0040F33B MOV AL,[ECX+17]
015F:0040F33E CMP AL,30
015F:0040F340 JL NEAR 0040F54F
015F:0040F346 CMP AL,46
015F:0040F348 JG NEAR 0040F54F <<=-- 17 = *
015F:0040F34E MOV AL,[ECX+19]
015F:0040F351 CMP AL,30
015F:0040F353 JL NEAR 0040F54F
015F:0040F359 CMP AL,46
015F:0040F35B JG NEAR 0040F54F <<=-- 19 = *
015F:0040F361 CMP BYTE [ECX],46 <<=-- 序列号第 0 位 ?= 46
015F:0040F364 JNZ NEAR 0040F54F
015F:0040F36A CMP BYTE [ECX+01],50<<=-- 1 ?= 50
015F:0040F36E JNZ NEAR 0040F54F
015F:0040F374 CMP BYTE [ECX+02],31<<=-- 2 ?= 31
015F:0040F378 JNZ NEAR 0040F54F
015F:0040F37E CMP BYTE [ECX+03],38<<=-- 3 ?= 38
015F:0040F382 JNZ NEAR 0040F54F
-----------------------------------==========>>>>>>>>>^^OK,序列号第 1,2,3,4位必须为 46,50,31,38,对应的ASCII码为: FP18
继续...
015F:0040F388 MOV DL,[ECX+05] <<=-- 注意:从此处开始算法
015F:0040F38B MOV BL,[ECX+08] <<=-- 具体算法附后,就不注释了
015F:0040F38E MOV [ESP+10],DL
015F:0040F392 MOV DL,[ECX+17]
015F:0040F395 ADD AL,DL
015F:0040F397 MOV DL,[ECX+16]
015F:0040F39A ADD AL,DL
015F:0040F39C MOV DL,[ECX+15]
015F:0040F39F ADD AL,DL
015F:0040F3A1 MOV DL,[ECX+12]
015F:0040F3A4 ADD AL,DL
015F:0040F3A6 MOV DL,[ECX+11]
015F:0040F3A9 ADD AL,DL
015F:0040F3AB MOV DL,[ECX+10]
015F:0040F3AE ADD AL,DL
015F:0040F3B0 MOV DL,[ECX+0F]
015F:0040F3B3 ADD AL,DL
015F:0040F3B5 MOV DL,[ESP+10]
015F:0040F3B9 XOR AL,DL
015F:0040F3BB MOV DL,[ECX+0C]
015F:0040F3BE XOR AL,BL
015F:0040F3C0 XOR AL,DL
015F:0040F3C2 XOR AL,23
015F:0040F3C4 MOV DL,AL
015F:0040F3C6 SHR DL,04
015F:0040F3C9 ADD DL,30
015F:0040F3CC CMP DL,39
015F:0040F3CF MOV [ESP+04],DL
015F:0040F3D3 JNA 0040F3DC
015F:0040F3D5 ADD DL,07
015F:0040F3D8 MOV [ESP+04],DL
015F:0040F3DC AND AL,0F
015F:0040F3DE ADD AL,30
015F:0040F3E0 CMP AL,39
015F:0040F3E2 MOV [ESP+08],AL
015F:0040F3E6 JNA 0040F3EE
015F:0040F3E8 ADD AL,07
015F:0040F3EA MOV [ESP+08],AL
015F:0040F3EE MOVSX EAX,BYTE [ECX+13] <<=-- 此处注意
015F:0040F3F2 MOV EDX,[ESP+04]
015F:0040F3F6 AND EDX,FF
015F:0040F3FC CMP EAX,EDX <<=-- 13 = [ESP+04] and FF
015F:0040F3FE JNZ NEAR 0040F54F
015F:0040F404 MOV DL,[ECX+14] <<=--
015F:0040F407 PUSH ESI
015F:0040F408 MOV ESI,[ESP+0C]
015F:0040F40C MOVSX EAX,DL
015F:0040F40F AND ESI,FF
015F:0040F415 CMP EAX,ESI <<=-- 14 = [ESP+0C] and FF
015F:0040F417 POP ESI
015F:0040F418 JNZ NEAR 0040F54F
015F:0040F41E MOV AL,[ECX+0A]
015F:0040F421 ADD AL,46
015F:0040F423 XOR AL,[ECX+09]
015F:0040F426 XOR AL,DL
015F:0040F428 MOV DL,[ECX+13]
015F:0040F42B XOR AL,DL
015F:0040F42D XOR AL,BL
015F:0040F42F XOR AL,41
015F:0040F431 MOV DL,AL
015F:0040F433 SHR DL,04
015F:0040F436 ADD DL,30
015F:0040F439 CMP DL,39
015F:0040F43C MOV [ESP+04],DL
015F:0040F440 JNA 0040F449
015F:0040F442 ADD DL,07
015F:0040F445 MOV [ESP+04],DL
015F:0040F449 AND AL,0F
015F:0040F44B ADD AL,30
015F:0040F44D CMP AL,39
015F:0040F44F MOV [ESP+08],AL
015F:0040F453 JNA 0040F45B
015F:0040F455 ADD AL,07
015F:0040F457 MOV [ESP+08],AL
015F:0040F45B MOVSX EDX,BYTE [ECX+1A] <<=--
015F:0040F45F MOV EAX,[ESP+04]
015F:0040F463 AND EAX,FF
015F:0040F468 CMP EDX,EAX <<=-- 1A = [ESP+4] and FF
015F:0040F46A JNZ NEAR 0040F54F
015F:0040F470 MOV BL,[ECX+1B] <<=--
015F:0040F473 MOV EAX,[ESP+08]
015F:0040F477 MOVSX EDX,BL
015F:0040F47A AND EAX,FF
015F:0040F47F CMP EDX,EAX <<=-- 1B = [ESP+08] and FF
015F:0040F481 JNZ NEAR 0040F54F
015F:0040F487 MOV AL,[ECX+06]
015F:0040F48A MOV DL,[ECX+14]
015F:0040F48D XOR AL,DL
015F:0040F48F MOV DL,[ECX+13]
015F:0040F492 XOR AL,DL
015F:0040F494 MOV DL,[ESP+10]
015F:0040F498 XOR AL,DL
015F:0040F49A XOR AL,AB
015F:0040F49C MOV DL,AL
015F:0040F49E SHR DL,04
015F:0040F4A1 ADD DL,30
015F:0040F4A4 CMP DL,39
015F:0040F4A7 MOV [ESP+04],DL
015F:0040F4AB JNA 0040F4B4
015F:0040F4AD ADD DL,07
015F:0040F4B0 MOV [ESP+04],DL
015F:0040F4B4 AND AL,0F
015F:0040F4B6 ADD AL,30
015F:0040F4B8 CMP AL,39
015F:0040F4BA MOV [ESP+08],AL
015F:0040F4BE JNA 0040F4C6
015F:0040F4C0 ADD AL,07
015F:0040F4C2 MOV [ESP+08],AL
015F:0040F4C6 MOVSX EDX,BYTE [ECX+0E] <<=--
015F:0040F4CA MOV EAX,[ESP+04]
015F:0040F4CE AND EAX,FF
015F:0040F4D3 CMP EDX,EAX <<=-- 0E = [ESP+04] and FF
015F:0040F4D5 JNZ 0040F54F
015F:0040F4D7 MOVSX EDX,BYTE [ECX+18] <<=--
015F:0040F4DB MOV EAX,[ESP+08]
015F:0040F4DF AND EAX,FF
015F:0040F4E4 CMP EDX,EAX <<=-- 18 = [ESP+08] and FF
015F:0040F4E6 JNZ 0040F54F
015F:0040F4E8 MOV AL,[ECX+1A]
015F:0040F4EB MOV DL,[ECX+0C]
015F:0040F4EE XOR BL,AL
015F:0040F4F0 XOR BL,DL
015F:0040F4F2 XOR BL,63
015F:0040F4F5 MOV DL,BL
015F:0040F4F7 MOV AL,DL
015F:0040F4F9 SHR AL,04
015F:0040F4FC ADD AL,30
015F:0040F4FE CMP AL,39
015F:0040F500 MOV [ESP+04],AL
015F:0040F504 JNA 0040F50C
015F:0040F506 ADD AL,07
015F:0040F508 MOV [ESP+04],AL
015F:0040F50C AND DL,0F
015F:0040F50F ADD DL,30
015F:0040F512 CMP DL,39
015F:0040F515 MOV [ESP+08],DL
015F:0040F519 JNA 0040F522
015F:0040F51B ADD DL,07
015F:0040F51E MOV [ESP+08],DL
015F:0040F522 MOVSX EDX,BYTE [ECX+1D] <<=--
015F:0040F526 MOV EAX,[ESP+04]
015F:0040F52A AND EAX,FF
015F:0040F52F CMP EDX,EAX <<=-- 1D = EAX
015F:0040F531 JNZ 0040F54F
015F:0040F533 MOVSX ECX,BYTE [ECX+1E] <<=-- 注意,快结束啦
015F:0040F537 MOV EDX,[ESP+08]
015F:0040F53B XOR EAX,EAX <<=-- EAX = 0
015F:0040F53D AND EDX,FF
015F:0040F543 POP EBX
015F:0040F544 CMP ECX,EDX <<=-- 根据比较的值,设置EAX
015F:0040F546 SETZ AL <<=-- 相等,则 EAX = 1
015F:0040F549 ADD ESP,BYTE +08
015F:0040F54C RET 04
015F:0040F54F XOR EAX,EAX <<=-- 错误,返回模块
015F:0040F551 POP EBX
015F:0040F552 ADD ESP,BYTE +08
015F:0040F555 RET 04
(3) 算法分析
(注:1,2,3...1A,1B...指的是序列号的位数,而a,b,...是我用的变量)
[1], 19 + 17 = a
[2], a + 16 = b
[3], b + 15 = c
[4], c + 12 = d
[5], d + 11 = e
[6], e + 10 = f
[7], f + OF = g
================= <<==---重置
[8], g xor 5 = a
[9], a xor 8 = b
[10], b xor 0c = c
[11], c xor 23 = d ----------
[12], d SHR 4 |
[13], d + 30 = e |
[14], if e<= 39 |
[esp+04] = e + 7 |
else |
[esp+04] = e |
================= <<==-- 重置 |
[15], a = d <--|
[16], a and 0F = b
[17], b + 30 = c
[18], if c <= 39
[esp+08] = c + 7
else
[esp+08] = c
=====================<<==--重置
[19], [esp+04] and OFF = a
[20], 13 = a <<==-- 第13位序列号
=====================<<==--重置
[21], [esp+0c] and oFF = a
[22], 14 = a <<==-- 第14位序列号
================== <<==-- 重置
[23], 0A and 46 = a
[24], a xor 9 = b
[25], b xor 14 = c
[26], c xor 13 = d
[27], d xor 8 = e
[28], e xor 41 = f ---------
[29], f shr 4 |
[30], f +30 = g |
[31], if g <= 39 |
[esp+04] = g + 07 |
else |
[esp+04] = g |
================= <<==-- 重置 |
[32], a = f <--------|
[33], a and 0F = b
[34], b + 30 = c
[35], if c <= 39
[esp+08] = c + 07
else
[esp+08] = c
================= <<==-- 重置
[36], a = [esp+04]
[37], a and 0FF = b
[38], 1A = b <<==-- 第1A位序列号
================= <<==-- 重置
[39], a = [esp+08]
[40], a and 0FF = b
[41], 1B = b <<==-- 第1B位序列号
================ <<==-- 重置
[42], 6 xor 14 = a
[43], a xor 13 = b
[44], b xor 5 = c
[45], c xor AB = d -----------
=============== <<==-- 重置 |
[46], a = d |
[47], a shr 4 |
[48], a + 30 = b |
[49], if b <= 39 |
[esp+04] = b+07 |
else |
[esp+04] = b |
=============== <<==-- 重置 |
[50], a = d <-----------------|
[51], a and 0F = b
[52], if c <= 39
[esp+08] = c + 7
else
[esp+08] = c
============== <<==-- 重置
[53], [esp+04] and 0FF = a
[54], 0E = a <<==-- 第0E位序列号
============= <<==-- 重置
[55], [esp+08] and 0FF = a
[56], 18 = a <<==--- 第18位序列号
================ <<==-- 重置
[57], 1A xor 1B = a
[58], a xor 0c = b
[59], b xor 63 = c -----------
================ <<==-- 重置 |
[60], a = c |
[61], a shr 4 |
[62], a + 30 = b |
[63], if b <= 39 |
[esp+04] = b+07 |
else |
[esp+04] = b |
================ <<==-- 重置 |
[64], a = c <---------------|
[65], a and 0F = b
[66], b + 30 = c
[67], if c <= 39
[esp+08] = c + 07
else
[esp+08] = c
=============== <<==-- 重置
[68], [esp+04] and 0FF = a
[69], 1D = a <<==-- 第1D位序列号
=============== <<==-- 重置
[70], [esp+08] and 0FF = a
[71], 1E = a <<==-- 第1E位序列号
Ok,写了这么长,手都有点写累了,看上去是不是很复杂呀,其实,自己实际的跟一下,再画一张草图就什么都明白了,CRACK = 毅力 + ...
以下是我跟的一组数据,大家如果还没有眼花的话就看看吧。
看时,最好最大化浏览。
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , A , B , C , D , E , F , 10 , 11 , 12 , 13 , 14 , 15 , 16
'F' 'P' '1' '8' '-' '-' '-' '-' * * * * * *
17 , 18 , 19 , 1A , 1B , 1C , 1D , 1E , 1F
* * '-'
首先虚拟一组注册序列号,其中的 * 号,我用 9 来代替,你也完全可用其他数据,但要注意: 30 < * < 46 呦!
FP18-00-000-0-0****00***0*00-000
(1) FP18-00-000-0-09999009990900-000 --=>> 13 = 44 (D)
FP18-00-000-0-09999D09990900-000
(2) FP18-00-000-0-09999D09990900-000 --=>> 14 = 42 (B)
FP18-00-000-0-09999DB9990900-000
(3) FP18-00-000-0-09999DB9990900-000 --=>> 1A = 33 (3)
FP18-00-000-0-09999DB9990930-000
(4) FP18-00-000-0-09999DB9990930-000 --=>> 1B = 31 (1)
FP18-00-000-0-09999DB9990931-000
(5) FP18-00-000-0-09999DB9990931-000 --=>> 0E = 41 (A)
FP18-00-000-0-A9999DB9990931-000
(6) FP18-00-000-0-A9999DB9990931-000 --=>> 18 = 44 (D)
FP18-00-000-0-A9999DB999D931-000
(7) FP18-00-000-0-A9999DB999D931-000 --=>> 1D = 35 (5)
FP18-00-000-0-A9999DB999D931-500
(8) FP18-00-000-0-A9999DB999D931-500 --=>> 1E = 31 (1)
FP18-00-000-0-A9999DB999D931-510 <<=-- 密码在此,终于搞定 ;-)
最后一句:DSQ,你在上海理工大一切还好吗?我爱你!,但天涯海角,终究注定此生无缘!
BitRanger 小笔于 2002.1.9