Revival 的算法跟踪, yqmjch兄弟的一个题目
软件名称: revive3.1 软件大小: 1079 KB软件语言: 国外软件软件类别: 国外软件 / 共享版 /应用平台: Win9x/NT/2000/XP破解工具: olldbg-cn v1.09【作者声明】:初学Crack,只是感兴趣,没有其它目的。可能我的描述有不到之处,请大家指正
程序是vc++编的,没有壳.在0lldbg中下getwindowtexta中断就能到核心.前面部分就不写了.
加载后用户名和单位名软件填好了,就填试验码 789456123012 .运行中断后不久就到:
****************************************************************
004032A0 SUB ESP, 24004032A3 PUSH EBX004032A4 PUSH ESI004032A5 MOV ESI, DWORD PTR SS:[ESP+30] ; ESI<== 0093292C,(ASCII "789456123012") 004032A9 PUSH EDI004032AA MOVSX EAX, BYTE PTR DS:[ESI] ; EAX <==DS:[0093292C]=37 ('7')004032AD PUSH EAX004032AE CALL Revival.0041F880 ; 这个CALL把hex值-20004032B3 ADD ESP, 4004032B6 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 EAX004032C4 CALL Revival.0041F880 ; 这个CALL把hex值-20004032C9 ADD ESP, 4004032CC CMP EAX, 56 ; 注册码的第3个条件:注册码的第一位是56+20=76 ('v'), 把第2位改为v再试004032CF JNZ Revival.0040340F----------------------CALL Revival.0041F880||0041F880 CMP DWORD PTR DS:[45DC20], 00041F887 PUSH ESI0041F888 PUSH EDI0041F889 JNZ SHORT Revival.0041F89F0041F88B MOV EAX, DWORD PTR SS:[ESP+C] ; 这一段是比较注册码第一位的取值范围hex=61-7A (小写字母)0041F88F CMP EAX, 61 ; 注册码的第一个条件(把试验码改为asdfghjklzxcvbnm后继续)0041F892 JL SHORT Revival.0041F8EB0041F894 CMP EAX, 7A0041F897 JG SHORT Revival.0041F8EB0041F899 SUB EAX, 20 ; EAX =61-20=41 0041F89C POP EDI0041F89D POP ESI ; ESI <== 0093266C,(ASCII"asdfghjklzxcvbnm")0041F89E RETN*********************************************下面继续分析:
004032D5 CMP BYTE PTR DS:[ESI+7], 2D ; 注册码的第4个条件:注册码的第8位2d ('-a'), 把第8位改为-再试004032D9 JNZ Revival.0040340F004032DF PUSH ESI ; /ESI = 0093266C,(ASCII "rvasdfg-jklzxcv")004032E0 CALL DWORD PTR DS:[<&kernel32.lstr>; \lstrlenA004032E6 CMP EAX, 0F ; EAX = 0F (注册码的长度=15位),条件5004032E9 JNZ Revival.0040340F004032EF MOV EDI, 2 ; EDI=2 (下面从第三位计算起)004032F4 /MOVSX EAX, BYTE PTR DS:[ESI+EDI] ; EAX <== DS:[0093266E]=61 ('a')004032F8 |PUSH EAX004032F9 |CALL Revival.0041F810 ; 比较条件CALL004032FE |ADD ESP, 400403301 |TEST EAX, EAX00403303 |JE Revival.004033F400403309 |INC EDI0040330A |CMP EDI, 70040330D \JL SHORT Revival.004032F40040330F MOV EDI, 800403314 /MOVSX EAX, BYTE PTR DS:[ESI+EDI]00403318 |PUSH EAX00403319 |CALL Revival.0041F8100040331E |ADD ESP, 400403321 |TEST EAX, EAX00403323 |JE Revival.004033FD00403329 |INC EDI0040332A |CMP EDI, 0F0040332D \JL SHORT Revival.00403314
-----------------------------------------------------
CALL Revival.0041F810 ||
0041F810 CMP DWORD PTR DS:[45D9DC], 10041F817 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, EAX0041F831 MOV ECX, DWORD PTR SS:[ESP+4] ; ECX <== SS:[0012F500]=61 ('a')0041F835 MOV AX, WORD PTR DS:[EDX+ECX*2] ; 用ECX的值做指针,来寻址.计算方法=基址+各位hex*20041F839 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 不等于00045D840 84 00 84 00 84 00 84 00 ???? //84的偏移量=45D83A-45D7DA=60H++2 ==>6AH0045D848 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], 000403341 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 ; 计算的CALL0041F80A ADD ESP, 40041F80D RETN-----------------------CALL Revival.0041F750||0041F750 PUSH EBX0041F751 PUSH ESI0041F752 MOV ESI, DWORD PTR SS:[ESP+C] ; ESI =0012F514,(ASCII "01") 第三 四位0041F756 PUSH EDI0041F757 PUSH EBP0041F758 MOV EDI, 1 ; EDI=10041F75D /CMP DWORD PTR DS:[45D9DC], EDI0041F763 |JLE SHORT Revival.0041F7760041F765 |PUSH 80041F767 |XOR EAX, EAX0041F769 |MOV AL, BYTE PTR DS:[ESI]0041F76B |PUSH EAX0041F76C |CALL Revival.004236100041F771 |ADD ESP, 80041F774 |JMP SHORT Revival.0041F7890041F776 |XOR EDX, EDX0041F778 |MOV ECX, DWORD PTR DS:[45D7D0] ; ECX <== DS:[0045D7D0] (参数的基地址)0041F77E |MOV DL, BYTE PTR DS:[ESI] ; DL <== DS:[0012F514]=30 ('0')0041F780 |XOR EAX, EAX0041F782 |MOV AX, WORD PTR DS:[ECX+EDX*2] ; 用DL值做寻值的指针,偏移量=DL*20041F786 |AND EAX, 8 ; 计算方法0041F789 |TEST EAX, EAX ; 注册码的判断条件,即DL*2偏移处的值AND 8 不能等于00041F78B |JE SHORT Revival.0041F790 ; 条件不成立就跳0041F78D |INC ESI0041F78E \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, EBX0041F792 MOV BL, BYTE PTR DS:[ESI] ; BL <== DS:[0012F514]=30 ('0') || =33 ||=370041F794 INC ESI ; ESI ++0041F795 MOV EDI, EBX ; EDI <== 300041F797 CMP EBX, 2D0041F79A JE SHORT Revival.0041F7A10041F79C CMP EBX, 2B0041F79F JNZ SHORT Revival.0041F7A60041F7A1 XOR EBX, EBX0041F7A3 MOV BL, BYTE PTR DS:[ESI]0041F7A5 INC ESI0041F7A6 XOR EBP, EBP0041F7A8 /CMP DWORD PTR DS:[45D9DC], 1 ; DS:[45D9DC]=010041F7AF |JLE SHORT Revival.0041F7BE0041F7B1 |PUSH 40041F7B3 |PUSH EBX0041F7B4 |CALL Revival.004236100041F7B9 |ADD ESP, 80041F7BC |JMP SHORT Revival.0041F7CD0041F7BE |MOV ECX, DWORD PTR DS:[45D7D0] ; 如果上面的条件都不成立,就跳到这里 ECX <== DS:[00457D0] (基地址)0041F7C4 |XOR EAX, EAX0041F7C6 |MOV AX, WORD PTR DS:[ECX+EBX*2] ; EBX =30 还是用第三位的hex值来做指针寻址0041F7CA |AND EAX, 4 ; 计算方法0041F7CD |TEST EAX, EAX ; 注册码的判断条件,即DL*2偏移处的值AND 4 不能等于00041F7CF |JE SHORT Revival.0041F7E10041F7D1 |LEA EAX, DWORD PTR SS:[EBP+EBP*4] ; EBP=0 ,第二次它就是把试验码*5==>EAX中,这个值有用0041F7D5 |INC ESI ; //EAX =0 ;EAX =HEX*50041F7D6 |LEA EBP, DWORD PTR DS:[EBX+EAX*2->; EBP <== 01 |<==03 这个计算是把十六进制转化为ASCII值,因为EAX=0||第二次计算的时候0041F7DA |XOR EBX, EBX ; //就是把后一位的hex+前一位值*A-300041F7DC |MOV BL, BYTE PTR DS:[ESI-1] ; BL <== DS:[0012F515]=31 ('1')0041F7DF \JMP SHORT Revival.0041F7A80041F7E1 MOV EAX, EBP ; EAX <==EBP (经过上面计算的值) ||(78901) =13435|||(56)=380041F7E3 CMP EDI, 2D0041F7E6 JNZ SHORT Revival.0041F7EF0041F7E8 NEG EAX0041F7EA POP EBP0041F7EB POP EDI0041F7EC POP ESI0041F7ED POP EBX0041F7EE RETN-----------------这一段要分析一下: 下面要的四个关键值的计算1.第一次用试验码的第三位,第四位进行如下计算:后一位值+前一位值*A 例如:(01)==>1+0*A=012.第二次用试验码的第六位,第七位进行相同计算:后一位值+前一位值*A 例如:(34)==>4+3*A=223.第三次用试验码的最后五位进行如下计算:前一位值*A+后一位值 ,然后把前面的值*A+后一位的值例如(78901)==>1+(0+(9+(8+7*a)*a)*a)*a=134354.第四次用试验码的第九位,第十位进行如下计算:前一位值*A+后一位值 例如:(56)==>6+5*A=38
======================================================================================
00403347 MOV CX, WORD PTR DS:[ESI+5] ; CX = 3433 ("34")0040334B ADD ESP, 40040334E MOV WORD PTR SS:[ESP+10], CX ; CX ==>SS:[0012F514]00403353 SUB AL, 13 ; AL =01 SUB 13=EE |这里把第一组值-1300403355 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], 000403362 PUSH ECX00403363 CALL Revival.0041F800 *********第二次调用00403368 LEA EDX, DWORD PTR SS:[ESP+14] ; EDX <== 0012F514,(ASCII "34")0040336C ADD ESP, 40040336F LEA EBX, DWORD PTR DS:[EAX-25] ; EBX <== EAX(上面CALL计算的值)-25=FFFFFFFD |第二组计算的值-2500403372 LEA ECX, DWORD PTR DS:[ESI+A] ; ECX <== DS:[ESI+A]=00932676,(ASCII "78901"). 试验码的后五位00403375 PUSH EDX ; EDX =3400403376 MOV EAX, DWORD PTR DS:[ECX] ; EAX <== DS:[00932676]=3039383700403378 MOV DWORD PTR DS:[EDX], EAX ; DS:[0012F514] <== 033938370040337A 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], 000403385 CALL Revival.0041F800 *********第三次调用0040338A ADD ESP, 40040338D 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], AX0040339D LEA EAX, DWORD PTR SS:[ESP+10] ; EAX <== SS:[ESP+10]=0012F514,(ASCII "56901")004033A1 MOV BYTE PTR SS:[ESP+12], 0004033A6 MOVZX EDI, DI ; EDI<==605D004033A9 PUSH EAX004033AA CALL Revival.0041F800 *********第四次调用004033AF MOV BYTE PTR SS:[ESP+14], AL ; SS:[0012F514]=38 ,第四次的值004033B3 ADD ESP, 4004033B6 XOR EAX, EAX004033B8 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 CDQ004033C9 IDIV ECX ; ECX = 64 IDIV EAX = 615D ==>EAX =F9 EDX=19004033CB MOV CL, DL ; CL <== 19004033CD XOR EAX, EAX004033CF MOV AL, BYTE PTR SS:[ESP+C] ; AL <== SS:[0012F510]=EE ,第一次的值004033D3 LEA EAX, DWORD PTR DS:[EAX+EDI+3] ; EAX =EE+605D+3= 614E004033D7 CDQ004033D8 IDIV EBX ; EAX =614E IDIV EBX=A ==>EAX=9BB EDX=000004033DA SUB DL, BYTE PTR DS:[ESI+4] ; DL =DL-32 ('2') ,试验码的第五位004033DD CMP DL, 0D0 ; DL =CE004033E0 JNZ SHORT Revival.00403406 ; 注册码的正确条件7004033E2 CMP CL, BYTE PTR SS:[ESP+10] ; CL = 19 SS:[ESP+10] =SS:[0012F514]=38004033E6 JNZ SHORT Revival.00403406 ; 注册码的正确条件8004033E8 MOV EAX, 1004033ED POP EDI004033EE POP ESI004033EF POP EBX004033F0 ADD ESP, 24004033F3 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