一个VB程序SpeedFlash的破解
下载地址:http://www.relaxsoft.net/SoftDown/SoftView.asp?SoftID=25
有同学请我帮忙破这个软件(可惜不是MM ),当时我二话没说答应了,结果花了二十分钟才把个这个4M的大家伙DOWN下来(我只有56K小猫).先用PEiD检测,是ASPACK2.11,手头正好有这个版本的脱壳机,轻松搞定.再检测,是VB6.0 .以前我对VB程序一直是敬而远之的,但这次为了在哥们面前显露一把,只好硬着头皮试试了.
这个软件很狡猾,点注册后根本没有任何提示.先下断点BPX HMEMCPY看看,点击,断了下来,按了五十来次F12还在VB DLL里转悠,只好换人: BPX MSVBVM60!__vbaVarTstEq .第二次中断后再走一段就来到这里:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004982F2(C)
|
:00498251 8B03 mov eax, dword ptr [ebx]
:00498253 50 push eax
:00498254 8B4D14 mov ecx, dword ptr [ebp+14]
:00498257 8B11 mov edx, dword ptr [ecx]
:00498259 52 push edx
* Reference To: MSVBVM60.__vbaStrCat, Ord:0000h
|
:0049825A FF1580104000 Call dword ptr [00401080] <--把机器码和NAME合并为串S
:00498260 8945A4 mov dword ptr [ebp-5C], eax
:00498263 C7459C08000000 mov [ebp-64], 00000008
:0049826A 0FBFC6 movsx eax, si
:0049826D 50 push eax
:0049826E 8D4D9C lea ecx, dword ptr [ebp-64]
:00498271 51 push ecx
:00498272 8D558C lea edx, dword ptr [ebp-74]
:00498275 52 push edx
* Reference To: MSVBVM60.rtcLeftCharVar, Ord:0269h
|
:00498276 FF15B4124000 Call dword ptr [004012B4]
:0049827C 6A01 push 00000001
:0049827E 8D458C lea eax, dword ptr [ebp-74]
:00498281 50 push eax
:00498282 8D8D7CFFFFFF lea ecx, dword ptr [ebp+FFFFFF7C]
:00498288 51 push ecx
* Reference To: MSVBVM60.rtcRightCharVar, Ord:026Bh
|
:00498289 FF15D0124000 Call dword ptr [004012D0]
:0049828F 8D957CFFFFFF lea edx, dword ptr [ebp+FFFFFF7C]
:00498295 52 push edx
:00498296 8D45C8 lea eax, dword ptr [ebp-38]
:00498299 50 push eax
* Reference To: MSVBVM60.__vbaStrVarVal, Ord:0000h
|
:0049829A FF15EC114000 Call dword ptr [004011EC] <--依次得到S中的字符
:004982A0 50 push eax
* Reference To: MSVBVM60.rtcAnsiValueBstr, Ord:0204h
|
:004982A1 FF1560104000 Call dword ptr [00401060] <--把字符转为ASCII码
:004982A7 0FBFC8 movsx ecx, ax
:004982AA 03CF add ecx, edi <--把结果累加起来
:004982AC 0F80BB0D0000 jo 0049906D
:004982B2 8BF9 mov edi, ecx
:004982B4 8D4DC8 lea ecx, dword ptr [ebp-38]
* Reference To: MSVBVM60.__vbaFreeStr, Ord:0000h
|
:004982B7 FF1508134000 Call dword ptr [00401308]
:004982BD 8D957CFFFFFF lea edx, dword ptr [ebp+FFFFFF7C]
:004982C3 52 push edx
:004982C4 8D458C lea eax, dword ptr [ebp-74]
:004982C7 50 push eax
:004982C8 8D4D9C lea ecx, dword ptr [ebp-64]
:004982CB 51 push ecx
:004982CC 6A03 push 00000003
* Reference To: MSVBVM60.__vbaFreeVarList, Ord:0000h
|
:004982CE FF1540104000 Call dword ptr [00401040]
:004982D4 83C410 add esp, 00000010
:004982D7 6683C601 add si, 0001
:004982DB 0F808C0D0000 jo 0049906D
:004982E1 668B55E0 mov dx, word ptr [ebp-20]
:004982E5 6683C201 add dx, 0001
:004982E9 0F807E0D0000 jo 0049906D
:004982EF 663BF2 cmp si, dx
:004982F2 0F8559FFFFFF jne 00498251 <--这里循环结束;EDI处是各个字符累加的结果
:004982F8 6800000840 push 40080000
:004982FD 6A00 push 00000000
:004982FF 6BFF05 imul edi, 00000005 <--EDI=EDI*5
:00498302 0F80650D0000 jo 0049906D
:00498308 B856555555 mov eax, 55555556 <--EAX=55555556$
:0049830D F7EF imul edi <--EAX=EAX*EDI的低32位,EDX=EAX*EDI的高32位
:0049830F 8BC2 mov eax, edx
:00498311 C1E81F shr eax, 1F <--得到高32位的最高1位
:00498314 03D0 add edx, eax <--加到原来的高32位上去
:00498316 83C201 add edx, 00000001 <--结果再加1,我们把结果记为R
:00498319 0F804E0D0000 jo 0049906D <--上面这一段还是比较好懂的
到了这里以后,我以为已经接近目标了,没想到后面一直风平浪静,到下面那个vbaStrR8处突然哗啦一下出来一个老长的数转成了字符串,而后面的vbaStrCmp也是把假码与这个字符串比较,可见这就是真正的注册码了.唯一一个可疑的就是49833F处的CALL MSVBVM60!__vbaPowerR8,但我又跟了好几遍也不知道那个大数是怎么算出来的.赶紧再翻开<<Crack Tutorial>>,这才明白下面那些f开头的命令都是浮点计算,也就是说根本不在我们可爱的通用寄存器EAX,EBX中 . OK!明白以后我们在SOFTICE中输入WF打开浮点显示窗口,里面ST0,ST1,ST2之类就是浮点寄存器了.仔细盯着点,我们继续...
:0049831F 899500FFFFFF mov dword ptr [ebp+FFFFFF00], edx
:00498325 DB8500FFFFFF fild dword ptr [ebp+FFFFFF00]
:0049832B DD9DF8FEFFFF fstp qword ptr [ebp+FFFFFEF8]
:00498331 8B8DFCFEFFFF mov ecx, dword ptr [ebp+FFFFFEFC]
:00498337 51 push ecx
:00498338 8B95F8FEFFFF mov edx, dword ptr [ebp+FFFFFEF8]
:0049833E 52 push edx
* Reference To: MSVBVM60.__vbaPowerR8, Ord:0000h
|
:0049833F FF1558124000 Call dword ptr [00401258] <--这个CALL就是计算了
:00498345 DC05C0284000 fadd qword ptr [004028C0] <--这句会把ST0+1(见后面)
:0049834B DFE0 fstsw ax
:0049834D A80D test al, 0D
:0049834F 0F85130D0000 jne 00499068
:00498355 83EC08 sub esp, 00000008
:00498358 DD1C24 fstp qword ptr [esp]
* Reference To: MSVBVM60.__vbaStrR8, Ord:0000h
|
:0049835B FF1580114000 Call dword ptr [00401180] <--这里是把上面的ST0+1变为字串
:00498361 8BD0 mov edx, eax
:00498363 8D4DC8 lea ecx, dword ptr [ebp-38]
* Reference To: MSVBVM60.__vbaStrMove, Ord:0000h
|
:00498366 FF15C4124000 Call dword ptr [004012C4]
:0049836C 50 push eax <--EAX为真码
:0049836D 8B4510 mov eax, dword ptr [ebp+10]
:00498370 8B08 mov ecx, dword ptr [eax]
:00498372 51 push ecx <--ECX为假码
* Reference To: MSVBVM60.__vbaStrCmp, Ord:0000h
|
:00498373 FF153C114000 Call dword ptr [0040113C] <--这个CALL就是比较了
:00498379 8BF0 mov esi, eax
:0049837B F7DE neg esi
:0049837D 1BF6 sbb esi, esi
:0049837F 46 inc esi
:00498380 F7DE neg esi
在CALL __vbaPowerR8处进入: (现在我们到了MSVBVM60.DLL里面)
MSVBVM60!__vbaPowerR8
0167:73475767 PUSH EBP
0167:73475768 MOV EBP,ESP
0167:7347576A FLD REAL8 PTR [733C0700]
0167:73475770 FLD REAL8 PTR [EBP+08]
0167:73475773 FCOMP ST(1)
0167:73475775 FSTSW AX
0167:73475777 SAHF
0167:73475778 JNZ 73475790
0167:7347577A FLD REAL8 PTR [EBP+10]
0167:7347577D FCOMP ST(1)
0167:7347577F FSTSW AX
0167:73475781 SAHF
0167:73475782 JNZ 73475790
0167:73475784 FSTP ST(0)
0167:73475786 FLD REAL8 PTR [733C0718]
0167:7347578C POP EBP
0167:7347578D RET 0010
0167:73475790 FLD REAL8 PTR [EBP+08]
0167:73475793 FCOMP ST(1)
0167:73475795 FSTSW AX
0167:73475797 SAHF
0167:73475798 JNZ 734757A4
0167:7347579A FLD REAL8 PTR [EBP+10]
0167:7347579D FCOMP ST(1)
0167:7347579F FSTSW AX
0167:734757A1 SAHF
0167:734757A2 JB 734757CE
0167:734757A4 FLD REAL8 PTR [EBP+08]
0167:734757A7 FCOMP ST(1)
0167:734757A9 FSTSW AX
0167:734757AB SAHF
0167:734757AC FSTP ST(0)
0167:734757AE JAE 734757D2
0167:734757B0 FLD REAL8 PTR [EBP+10]
0167:734757B3 PUSH ECX
0167:734757B4 PUSH ECX
0167:734757B5 FSTP REAL8 PTR [ESP]
0167:734757B8 CALL 73480307
0167:734757BD FCOMP REAL8 PTR [EBP+10]
0167:734757C0 POP ECX
0167:734757C1 POP ECX
0167:734757C2 FSTSW AX
0167:734757C4 SAHF
0167:734757C5 JZ 734757D2
0167:734757C7 PUSH 05
0167:734757C9 CALL 733B5359
0167:734757CE FSTP ST(0)
0167:734757D0 JMP 734757C7
0167:734757D2 CALL 733A68B8
0167:734757D7 FLD REAL8 PTR [EBP+08]
0167:734757DA FLD REAL8 PTR [EBP+10]
0167:734757DD AND DWORD PTR [EAX],00
0167:734757E0 CALL 73480400 <--上面的一堆都没什么用,不过是把上面的EDX结果放入ST0中,但带过这个CALL后发现那个大数出现了,所以要进入这个CALL
0167:734757E5 FST REAL8 PTR [EBP+10]
0167:734757E8 PUSH ECX
0167:734757E9 PUSH ECX
进入734757E0处的CALL:
0167:73480400 SUB ESP,10
0167:73480403 FXCH ST(1)
0167:73480405 FSTP REAL8 PTR [ESP]
0167:73480408 FST REAL8 PTR [ESP+08]
0167:7348040C MOV EAX,[ESP+0C]
0167:73480410 CALL 73480419 <--进入这个CALL
0167:73480415 ADD ESP,10
0167:73480418 RET
进入73480419处的CALL:
0167:73480419 MOV ECX,EAX
0167:7348041B PUSH EAX
0167:7348041C WAIT
0167:7348041D FSTCW WORD PTR [ESP]
0167:73480420 CMP WORD PTR [ESP],027F
0167:73480426 JZ 7348042D
0167:73480428 CALL 73483C17
0167:7348042D AND ECX,7FF00000
0167:73480433 LEA EDX,[ESP+08]
0167:73480437 CMP ECX,7FF00000
0167:7348043D JZ 7348058D
0167:73480443 CALL 73483C47
0167:73480448 JZ 73480586
0167:7348044E TEST EAX,7FF00000
0167:73480453 JZ 734805AC
0167:73480459 MOV CL,[ESP+0F]
0167:7348045D AND CL,80
0167:73480460 JNZ 73480622
0167:73480466 FYL2X <--前面ST0=R(上面的结果),ST1=3(好像是常数)
<--该句是ST0<-ST1*(log2(ST0))
0167:73480468 CALL 73483C02 <--进入这个CALL
0167:7348046D CMP CL,01
0167:73480470 JNZ 73480474
0167:73483C02 FLD ST(0)
0167:73483C04 FRNDINT <--将ST0取整
0167:73483C06 FSUBR ST(1),ST <--相减求出小数部分
0167:73483C08 FXCH ST(1) <--ST0与ST1交换
0167:73483C0A FCHS <--ST0变为正数.此时ST0=上面结果的小数部分,ST1=整数部分
0167:73483C0C F2XM1 <-- ST0<-(2^ST0)+1
0167:73483C0E FLD1 <-- ST0<-ST0-1
0167:73483C10 FADDP ST(1),ST <-- ST0<-ST0+ST1
0167:73483C12 FSCALE <-- ST0<-ST0*(2^ST1) 到这里终于计算完了
0167:73483C14 FSTP ST(1)
0167:73483C16 RET
本来想写个注册机,在汇编里挺清楚的语句,到了高级语言里面一堆数据类型全乱了 .请各位高手写个注册机贴出来学习一下,我的编程实在太烂了...
后记:
因为从来没有见到过浮点计算的指令,上面的许多运算都是在看雪老师的<<Crack Tutorial>>中浮点运算一节中查到的,但里面对FSCALE命令的解释有误,说是求2的ST(0)次方,即ST(0) <- 2^ST(0). 而我却怎么也算不对,在网上查了一下,发现应该是ST(0) <- ST(0)*(2^ST(1)). 下面是我找到的资料,请各位看一下对不对.
<tr>
引用:
tr>
<tr>
tr>
_____________________________________________________________________________
FSCALE Scale by a power of 2 Exceptions: I O U
C3 C2 C1 C0: ? ? * ?
FSCALE
Logic ST . ST * 2**ST(1)
FSCALE interprets the contents of ST(1) as an integer, and uses it
as an exponent of 2 with which to multiply the contents of ST. Thus,
FSCALE provides a quick way to multiply or divide by a power of 2.
The number in ST(1) must be -2**15 <= ST(1) < 2**15. It is truncated
before the operation is performed. If 0 < ST(1) < 1, the result is
undefined (and no exception is generated).
Opcode Format
D9 FD FSCALE
Timing
Operand 8087 287 387 486 Pentium
- 32-38 32-38 67-86 30-32 20-31 NP
_____________________________________________________________________________