• 标 题:Revival 的算法跟踪
  • 作 者:fxyang
  • 时 间:2003/03/02 00:02am
  • 链 接:http://bbs.pediy.com

Revival 的算法跟踪, yqmjch兄弟的一个题目


软件名称:   revive3.1
下载地址:  ftp://www.newhua.com/revive31.zip
软件大小:  1079 KB
软件语言:  国外软件
软件类别:  国外软件 / 共享版 /
应用平台:  Win9x/NT/2000/XP
破解工具:   olldbg-cn v1.09
【作者声明】:初学Crack,只是感兴趣,没有其它目的。可能我的描述有不到之处,请大家指正

 程序是vc++编的,没有壳.在0lldbg中下getwindowtexta中断就能到核心.前面部分就不写了.

 加载后用户名和单位名软件填好了,就填试验码 789456123012 .运行中断后不久就到:

****************************************************************

004032A0  SUB     ESP, 24
004032A3  PUSH    EBX
004032A4  PUSH    ESI
004032A5  MOV     ESI, DWORD PTR SS:[ESP+30]    ;  ESI<== 0093292C,(ASCII "789456123012")      
004032A9  PUSH    EDI
004032AA  MOVSX   EAX, BYTE PTR DS:[ESI]        ;  EAX <==DS:[0093292C]=37 ('7')
004032AD  PUSH    EAX
004032AE  CALL    Revival.0041F880              ;  这个CALL把hex值-20
004032B3  ADD     ESP, 4
004032B6  CMP     EAX, 52                       ;  比较第一位是不是52+20=72 ('r')
004032B9  JNZ     Revival.0040340F              ;  注册码的第二个条件:注册码的第一位是('r'), 把第一位改为r再试
004032BF  MOVSX   EAX, BYTE PTR DS:[ESI+1]      ;  EAX <== DS:[0093292D] = 61 ('a')
004032C3  PUSH    EAX
004032C4  CALL    Revival.0041F880              ;  这个CALL把hex值-20
004032C9  ADD     ESP, 4
004032CC  CMP     EAX, 56                       ;  注册码的第3个条件:注册码的第一位是56+20=76 ('v'), 把第2位改为v再试
004032CF  JNZ     Revival.0040340F
----------------------
CALL    Revival.0041F880
|
|
0041F880  CMP     DWORD PTR DS:[45DC20], 0
0041F887  PUSH    ESI
0041F888  PUSH    EDI
0041F889  JNZ     SHORT Revival.0041F89F
0041F88B  MOV     EAX, DWORD PTR SS:[ESP+C]    ;  这一段是比较注册码第一位的取值范围hex=61-7A (小写字母)
0041F88F  CMP     EAX, 61                      ;  注册码的第一个条件(把试验码改为asdfghjklzxcvbnm后继续)
0041F892  JL      SHORT Revival.0041F8EB
0041F894  CMP     EAX, 7A
0041F897  JG      SHORT Revival.0041F8EB
0041F899  SUB     EAX, 20                      ;  EAX =61-20=41  
0041F89C  POP     EDI
0041F89D  POP     ESI                          ;  ESI <== 0093266C,(ASCII"asdfghjklzxcvbnm")
0041F89E  RETN
*********************************************
下面继续分析:

004032D5  CMP     BYTE PTR DS:[ESI+7], 2D       ;  注册码的第4个条件:注册码的第8位2d ('-a'), 把第8位改为-再试
004032D9  JNZ     Revival.0040340F
004032DF  PUSH    ESI                           ; /ESI = 0093266C,(ASCII "rvasdfg-jklzxcv")
004032E0  CALL    DWORD PTR DS:[<&KERNEL32.lstr>; \lstrlenA
004032E6  CMP     EAX, 0F                       ;  EAX = 0F (注册码的长度=15位),条件5
004032E9  JNZ     Revival.0040340F
004032EF  MOV     EDI, 2                        ;  EDI=2 (下面从第三位计算起)
004032F4  /MOVSX   EAX, BYTE PTR DS:[ESI+EDI]   ;  EAX <== DS:[0093266E]=61 ('a')
004032F8  |PUSH    EAX
004032F9  |CALL    Revival.0041F810             ;  比较条件CALL
004032FE  |ADD     ESP, 4
00403301  |TEST    EAX, EAX
00403303  |JE      Revival.004033F4
00403309  |INC     EDI
0040330A  |CMP     EDI, 7
0040330D  \JL      SHORT Revival.004032F4
0040330F   MOV     EDI, 8
00403314  /MOVSX   EAX, BYTE PTR DS:[ESI+EDI]
00403318  |PUSH    EAX
00403319  |CALL    Revival.0041F810
0040331E  |ADD     ESP, 4
00403321  |TEST    EAX, EAX
00403323  |JE      Revival.004033FD
00403329  |INC     EDI
0040332A  |CMP     EDI, 0F
0040332D  \JL      SHORT Revival.00403314

-----------------------------------------------------

CALL    Revival.0041F810
|
|

0041F810  CMP     DWORD PTR DS:[45D9DC], 1
0041F817  JLE     SHORT Revival.0041F829        ;这里一定跳
0041F819  MOV     ECX, DWORD PTR SS:[ESP+4]          |
0041F81D  PUSH    4                                  |
0041F81F  PUSH    ECX                                |
0041F820  CALL    Revival.00423610                   |
0041F825  ADD     ESP, 8                            \|/
0041F828  RETN                                       .
0041F829  MOV     EDX, DWORD PTR DS:[45D7D0]    ;  Revival.0045D7DA (寻址的基址)
0041F82F  XOR     EAX, EAX
0041F831  MOV     ECX, DWORD PTR SS:[ESP+4]     ;  ECX <== SS:[0012F500]=61 ('a')
0041F835  MOV     AX, WORD PTR DS:[EDX+ECX*2]   ;  用ECX的值做指针,来寻址.计算方法=基址+各位hex*2
0041F839  AND     EAX, 4                        ;  EAX =EAX AND 4  寻址得到的值再计算
0041F83C  RETN                                  ;  条件6--EAX AND 4 不等于0 ,就正确.

++++++++++++++++++++++++++++++++++++++++++++++++++++++
这是内存中数组的值:

  0045D7DA ==> 20 00 20 00 20 00  .. . . .
0045D7E0  20 00 20 00 20 00 20 00   . . . .
0045D7E8  20 00 20 00 28 00 28 00   . .(.(.                        
0045D7F0  28 00 28 00 28 00 20 00  (.(.(. .
0045D7F8  20 00 20 00 20 00 20 00   . . . .
0045D800  20 00 20 00 20 00 20 00   . . . .
0045D808  20 00 20 00 20 00 20 00   . . . .
0045D810  20 00 20 00 20 00 20 00   . . . .
0045D818  20 00 48 00 10 00 10 00   .H...
0045D820  10 00 10 00 10 00 10 00  ....
0045D828  10 00 10 00 10 00 10 00  ....
0045D830  10 00 10 00 10 00 10 00  ....
0045D838  10 00 84 00 84 00 84 00  .???      ;经过分析发现内存中的值只有84 AND 4 不等于0
0045D840  84 00 84 00 84 00 84 00  ????       //84的偏移量=45D83A-45D7DA=60H++2 ==>6AH
0045D848  84 00 84 00 84 00 10 00  ???.      //那么第三位值应该=60/2=30 ('0')++ ==>39 ('9')
0045D850  10 00 10 00 10 00 10 00  ....   ;上面的计算告诉我们从第三位开始取值的范围(0-9)
0045D858  10 00 10 00 81 00 81 00  ..??      //把试验码改为:rv01234-5678901 后继续
0045D860  81 00 81 00 81 00 81 00  ????
0045D868  01 00 01 00 01 00 01 00  ....
0045D870  01 00 01 00 01 00 01 00  ....
0045D878  01 00 01 00 01 00 01 00  ....
0045D880  01 00 01 00 01 00 01 00  ....
0045D888  01 00 01 00 01 00 01 00  ....
0045D890  10 00 10 00 10 00 10 00  ....
0045D898  10 00 10 00 82 00 82 00  ..??
0045D8A0  82 00 82 00 82 00 82 00  ????
0045D8A8  02 00 02 00 02 00 02 00  ....
0045D8B0  02 00 02 00 02 00 02 00  ....
0045D8B8  02 00 02 00 02 00 02 00  ....
0045D8C0  02 00 02 00 02 00 02 00  ....
0045D8C8  02 00 02 00 02 00 02 00  ....
0045D8D0  10 00 10 00 10 00 10 00  ....

=======================================================================================

下面继续我们的

0040332F  MOV     AX, WORD PTR DS:[ESI+2]       ;  AX <==DS:[ESI+2](取二位)=DS:[0093266E]=3130 ('01')
00403333  MOV     WORD PTR SS:[ESP+10], AX      ;  AX ==>SS:[0012F514]
00403338  LEA     EAX, DWORD PTR SS:[ESP+10]
0040333C  MOV     BYTE PTR SS:[ESP+12], 0
00403341  PUSH    EAX                           ;  EAX =0012F514,(ASCII "01") 第三 四位
00403342  CALL    Revival.0041F800             *********第一次调用


------------------------
CALL    Revival.0041F800
|
|

0041F800  MOV     EAX, DWORD PTR SS:[ESP+4]
0041F804  PUSH    EAX                           ;  EAX =0012F514,(ASCII "01") 第三 四位
0041F805  CALL    Revival.0041F750              ;  计算的CALL
0041F80A  ADD     ESP, 4
0041F80D  RETN
-----------------------
CALL    Revival.0041F750
|
|
0041F750  PUSH    EBX
0041F751  PUSH    ESI
0041F752  MOV     ESI, DWORD PTR SS:[ESP+C]     ;  ESI =0012F514,(ASCII "01") 第三 四位
0041F756  PUSH    EDI
0041F757  PUSH    EBP
0041F758  MOV     EDI, 1                        ;  EDI=1
0041F75D  /CMP     DWORD PTR DS:[45D9DC], EDI
0041F763  |JLE     SHORT Revival.0041F776
0041F765  |PUSH    8
0041F767  |XOR     EAX, EAX
0041F769  |MOV     AL, BYTE PTR DS:[ESI]
0041F76B  |PUSH    EAX
0041F76C  |CALL    Revival.00423610
0041F771  |ADD     ESP, 8
0041F774  |JMP     SHORT Revival.0041F789
0041F776  |XOR     EDX, EDX
0041F778  |MOV     ECX, DWORD PTR DS:[45D7D0]   ;  ECX <== DS:[0045D7D0] (参数的基地址)
0041F77E  |MOV     DL, BYTE PTR DS:[ESI]        ;  DL <== DS:[0012F514]=30 ('0')
0041F780  |XOR     EAX, EAX
0041F782  |MOV     AX, WORD PTR DS:[ECX+EDX*2]  ;  用DL值做寻值的指针,偏移量=DL*2
0041F786  |AND     EAX, 8                       ;  计算方法
0041F789  |TEST    EAX, EAX                     ;  注册码的判断条件,即DL*2偏移处的值AND 8 不能等于0
0041F78B  |JE      SHORT Revival.0041F790       ;  条件不成立就跳
0041F78D  |INC     ESI
0041F78E  \JMP     SHORT Revival.0041F75D

++++++++++++++++++++++++++++++++++++++++++++++++++++++
这是内存中数组的值:

0045D7D0  DA D7 45 00 DA D7 45 00  谧E.谧E.
0045D7D8  00 00 20 00 20 00 20 00  .. . . .
0045D7E0  20 00 20 00 20 00 20 00   . . . .
0045D7E8  20 00 20 00 28 00 28 00   . .(.(.
0045D7F0  28 00 28 00 28 00 20 00  (.(.(. .
0045D7F8  20 00 20 00 20 00 20 00   . . . .
0045D800  20 00 20 00 20 00 20 00   . . . .
0045D808  20 00 20 00 20 00 20 00   . . . .
0045D810  20 00 20 00 20 00 20 00   . . . .
0045D818  20 00 48 00 10 00 10 00   .H...
0045D820  10 00 10 00 10 00 10 00  ....
0045D828  10 00 10 00 10 00 10 00  ....
0045D830  10 00 10 00 10 00 10 00  ....
0045D838  10 00 84 00 84 00 84 00  .???           ;由于偏移量最小是从45D83A开始的.
0045D840  84 00 84 00 84 00 84 00  ????            ;分析下面的各个值没有符合条件的.
0045D848  84 00 84 00 84 00 10 00  ???.
0045D850  10 00 10 00 10 00 10 00  ....
0045D858  10 00 10 00 81 00 81 00  ..??
0045D860  81 00 81 00 81 00 81 00  ????
0045D868  01 00 01 00 01 00 01 00  ....
0045D870  01 00 01 00 01 00 01 00  ....
0045D878  01 00 01 00 01 00 01 00  ....
0045D880  01 00 01 00 01 00 01 00  ....
0045D888  01 00 01 00 01 00 01 00  ....
0045D890  10 00 10 00 10 00 10 00  ....
0045D898  10 00 10 00 82 00 82 00  ..??
0045D8A0  82 00 82 00 82 00 82 00  ????
0045D8A8  02 00 02 00 02 00 02 00  ....
0045D8B0  02 00 02 00 02 00 02 00  ....
0045D8B8  02 00 02 00 02 00 02 00  ....
0045D8C0  02 00 02 00 02 00 02 00  ....
0045D8C8  02 00 02 00 02 00 02 00  ....
0045D8D0  10 00 10 00 10 00 10 00  ....
0045D8D8  20 00 00 00 00 00 00 00   .......
--------------
这一段只是为下面服务的

==============================================
继续:
-----
|
|
0041F790  XOR     EBX, EBX
0041F792  MOV     BL, BYTE PTR DS:[ESI]          ;  BL <== DS:[0012F514]=30 ('0') || =33 ||=37
0041F794  INC     ESI                            ;  ESI ++
0041F795  MOV     EDI, EBX                       ;  EDI <== 30
0041F797  CMP     EBX, 2D
0041F79A  JE      SHORT Revival.0041F7A1
0041F79C  CMP     EBX, 2B
0041F79F  JNZ     SHORT Revival.0041F7A6
0041F7A1  XOR     EBX, EBX
0041F7A3  MOV     BL, BYTE PTR DS:[ESI]
0041F7A5  INC     ESI
0041F7A6  XOR     EBP, EBP
0041F7A8  /CMP     DWORD PTR DS:[45D9DC], 1      ;  DS:[45D9DC]=01
0041F7AF  |JLE     SHORT Revival.0041F7BE
0041F7B1  |PUSH    4
0041F7B3  |PUSH    EBX
0041F7B4  |CALL    Revival.00423610
0041F7B9  |ADD     ESP, 8
0041F7BC  |JMP     SHORT Revival.0041F7CD
0041F7BE  |MOV     ECX, DWORD PTR DS:[45D7D0]    ;  如果上面的条件都不成立,就跳到这里 ECX <== DS:[00457D0] (基地址)
0041F7C4  |XOR     EAX, EAX
0041F7C6  |MOV     AX, WORD PTR DS:[ECX+EBX*2]   ;  EBX =30 还是用第三位的hex值来做指针寻址
0041F7CA  |AND     EAX, 4                        ;  计算方法
0041F7CD  |TEST    EAX, EAX                      ;  注册码的判断条件,即DL*2偏移处的值AND 4 不能等于0
0041F7CF  |JE      SHORT Revival.0041F7E1
0041F7D1  |LEA     EAX, DWORD PTR SS:[EBP+EBP*4] ; EBP=0 ,第二次它就是把试验码*5==>EAX中,这个值有用
0041F7D5  |INC     ESI                           ;  //EAX =0 ;EAX =HEX*5
0041F7D6  |LEA     EBP, DWORD PTR DS:[EBX+EAX*2->;  EBP <== 01 |<==03  这个计算是把十六进制转化为ASCII值,因为EAX=0||第二次计算的时候
0041F7DA  |XOR     EBX, EBX                      ;  //就是把后一位的hex+前一位值*A-30
0041F7DC  |MOV     BL, BYTE PTR DS:[ESI-1]       ;  BL <== DS:[0012F515]=31 ('1')
0041F7DF  \JMP     SHORT Revival.0041F7A8
0041F7E1  MOV     EAX, EBP                       ;  EAX <==EBP (经过上面计算的值) ||(78901) =13435|||(56)=38
0041F7E3  CMP     EDI, 2D
0041F7E6  JNZ     SHORT Revival.0041F7EF
0041F7E8  NEG     EAX
0041F7EA  POP     EBP
0041F7EB  POP     EDI
0041F7EC  POP     ESI
0041F7ED  POP     EBX
0041F7EE  RETN
-----------------
这一段要分析一下: 下面要的四个关键值的计算
1.第一次用试验码的第三位,第四位进行如下计算:后一位值+前一位值*A  例如:(01)==>1+0*A=01
2.第二次用试验码的第六位,第七位进行相同计算:后一位值+前一位值*A  例如:(34)==>4+3*A=22
3.第三次用试验码的最后五位进行如下计算:前一位值*A+后一位值 ,然后把前面的值*A+后一位的值
例如(78901)==>1+(0+(9+(8+7*a)*a)*a)*a=13435
4.第四次用试验码的第九位,第十位进行如下计算:前一位值*A+后一位值  例如:(56)==>6+5*A=38

======================================================================================

00403347   MOV     CX, WORD PTR DS:[ESI+5]        ;  CX = 3433 ("34")
0040334B   ADD     ESP, 4
0040334E   MOV     WORD PTR SS:[ESP+10], CX       ;  CX ==>SS:[0012F514]
00403353   SUB     AL, 13                         ;  AL =01 SUB 13=EE  |这里把第一组值-13
00403355   LEA     ECX, DWORD PTR SS:[ESP+10]     ;  ECX <==0012F514, (ASCII "34")
00403359   MOV     BYTE PTR SS:[ESP+C], AL        ;  AL =EE  ==>SS:[0012F510]  |第一组的值保存在这里
0040335D   MOV     BYTE PTR SS:[ESP+12], 0
00403362   PUSH    ECX
00403363   CALL    Revival.0041F800               *********第二次调用
00403368   LEA     EDX, DWORD PTR SS:[ESP+14]     ;  EDX <== 0012F514,(ASCII "34")
0040336C   ADD     ESP, 4
0040336F   LEA     EBX, DWORD PTR DS:[EAX-25]     ;  EBX <== EAX(上面CALL计算的值)-25=FFFFFFFD  |第二组计算的值-25
00403372   LEA     ECX, DWORD PTR DS:[ESI+A]      ;  ECX <== DS:[ESI+A]=00932676,(ASCII "78901"). 试验码的后五位
00403375   PUSH    EDX                            ;  EDX =34
00403376   MOV     EAX, DWORD PTR DS:[ECX]        ;  EAX <== DS:[00932676]=30393837
00403378   MOV     DWORD PTR DS:[EDX], EAX        ;  DS:[0012F514] <== 03393837
0040337A   MOV     CL, BYTE PTR DS:[ECX+4]        ;  CL <== DS:[ECX+4]=31 ('1') 试验码的最后一位
0040337D   MOV     BYTE PTR DS:[EDX+4], CL        ;  第五位也转移过来
00403380   MOV     BYTE PTR SS:[ESP+19], 0
00403385   CALL    Revival.0041F800               *********第三次调用
0040338A   ADD     ESP, 4
0040338D   MOV     EDI, EAX                       ;  EDI <==13435 (后五位经过上面计算的值)
0040338F   XOR     DI, 5468                       ;  DI=3435 XOR 5468=605D  (只取这个值的后四位计算)
00403394   MOV     AX, WORD PTR DS:[ESI+8]        ;  AX <== DS:[00932674]=3635 ("56") ,试验码的第九第十位
00403398   MOV     WORD PTR SS:[ESP+10], AX
0040339D   LEA     EAX, DWORD PTR SS:[ESP+10]     ;  EAX <== SS:[ESP+10]=0012F514,(ASCII "56901")
004033A1   MOV     BYTE PTR SS:[ESP+12], 0
004033A6   MOVZX   EDI, DI                        ;  EDI<==605D
004033A9   PUSH    EAX
004033AA   CALL    Revival.0041F800               *********第四次调用
004033AF   MOV     BYTE PTR SS:[ESP+14], AL       ;  SS:[0012F514]=38  ,第四次的值
004033B3   ADD     ESP, 4
004033B6   XOR     EAX, EAX
004033B8   MOV     ECX, 64                        ;  ECX =64    <--参数
004033BD   MOV     AL, BL                         ;  AL =FD     ,第二次的值
004033BF   MOV     EBX, 0A                        ;  EBX <=0A   <--参数
004033C4   LEA     EAX, DWORD PTR DS:[EAX+EDI+3]  ;  EAX <==FD+6150D+3 ,第三次的值
004033C8   CDQ
004033C9   IDIV    ECX                            ;  ECX = 64  IDIV  EAX = 615D ==>EAX =F9 EDX=19
004033CB   MOV     CL, DL                         ;  CL <== 19
004033CD   XOR     EAX, EAX
004033CF   MOV     AL, BYTE PTR SS:[ESP+C]        ;  AL <== SS:[0012F510]=EE ,第一次的值
004033D3   LEA     EAX, DWORD PTR DS:[EAX+EDI+3]  ;  EAX =EE+605D+3= 614E
004033D7   CDQ
004033D8   IDIV    EBX                            ;  EAX =614E IDIV EBX=A ==>EAX=9BB EDX=000
004033DA   SUB     DL, BYTE PTR DS:[ESI+4]        ;  DL =DL-32 ('2') ,试验码的第五位
004033DD   CMP     DL, 0D0                        ;  DL =CE
004033E0   JNZ     SHORT Revival.00403406         ;  注册码的正确条件7
004033E2   CMP     CL, BYTE PTR SS:[ESP+10]       ;  CL = 19    SS:[ESP+10] =SS:[0012F514]=38
004033E6   JNZ     SHORT Revival.00403406         ;  注册码的正确条件8
004033E8   MOV     EAX, 1
004033ED   POP     EDI
004033EE   POP     ESI
004033EF   POP     EBX
004033F0   ADD     ESP, 24
004033F3   RETN

#####################################################################################
以上算法分析已经完成,下面来总结注册码的计算方法: 注册码的长度=15位

  1.首先看注册码的前二位比较容易固定值rv
  2.注册码的第八位是 2D('-')
  3.注册码的其他几位必须是数字
  4.其他几位正确的条件:设第一次计算的值为M ,第二次的值为N ,第三次值的后四位为J ,第四次计算的值为K

          1).(M+(J XOR 5468)+3) MOD A + D0 = 注册码的第五位
          2).(N+(J XOR 5468)+3) MOD 64 = k

  5.假如我们知道M N J K

    这样注册码的这几位可以知道假设了: rv01?34-??78901

  6.为了使上式成立,我们做如下分析:

  从 K 分析: 设K=19 ,第九位为T1 ,第十位为T2
               则:T2=19-T1*A >=0 ; T1 的取值范围只能是 2  那么 T2 =19-2*A=5
  这样把注册码设成:rv01???-2578901
  现在来分析一下它对第一个条件能不能成立:
          1).(M+(J XOR 5468)+3) MOD A = 注册码的第五位  
             上式改为注册码的第五位=6145 MOD A =0

  把注册码改为:rv01034-2578901
 
几点说明:  
  1.这个软件的注册码如果不进行假设的话,可能很难知道结果.
  2.SUB     DL, BYTE PTR DS:[ESI+4]        ;  DL =DL-32 ('2') ,试验码的第五位
    (M+(J XOR 5468)+3) MOD A = 注册码的第五位,这个我是怎么知道的
    原来 MOD A 得到的值是<A -30以上的值是负数,我无法用计算器计算,只好用sice的计算功能才
   知道0-30=D0 ,因此上面式子就是:
    SUB     DL, BYTE PTR DS:[ESI+4]  
    CMP     DL, 0D0  
    JNZ     SHORT Revival.00403406   <== 不能跳
   成立的描述.
 3.以上算法得到的注册码,能注册成功,但是重新启动时不能通过,请老师们斧正


                                                              fxyang

                                                            2003.3.1