[目标]CDspace 5.0(虚拟光驱大师)
[软件简介]可以模拟您电脑中的光盘机的运作状况,最多可以在您的电脑中模拟高达23台光盘机,而且执行速度可以到达200倍速以上,并且还支持网络的功能。最重要的是支持LCD格式。
[软件下载]中文主页
http://cn.cdspace.com/c_htm/c_home.asp
[工具]W32ASM无级版+OD
[保护方式] 序列号自校验
[加入时间] 2005-11-25
首先拿来一个软件我们当然是先试着注册一下,看看有什么错误提示的。
打开软件点注册后
我输入
姓名:4nil[NCG]
序列号:abcd123456789
点确定后,提示“无效的注册码,请重试!”
既然有提示就好,查壳发现是VC++的,没壳,用W32ASM无级版载入,查字符串,乱码,
没办法,只好硬上了。
打开OllyDbg110
既然有对话框出来提示,我们就先下个断点
bp MessageBoxA
运行,重复前面步骤,果然断下。
回到OD,一直按F8知道对话框出来,出去点确认,又断下,然后我们就可以一直按ctrl+F9,回到CDspace领空。
往上翻翻看,如下这个样子。
那我们就在这一段代码开头下个断点吧。
00416CF0 /$ 6A FF PUSH -1 //就是这里下个断点
好了,我们就F9让他跑完这个错误的一趟把。
出来继续点确认,断下。
按F8一个一个看有没有什么线索。。。
.....
00416D95 |. 83E1 03 AND ECX,3
00416D98 |. F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
00416D9A |. 8D4C24 70 LEA ECX,DWORD PTR SS:[ESP+70]
00416D9E |. 51 PUSH ECX ; /IniFileName = "D:\Program Files\SPACE INTERNATIONAL\CDSpace 5\CDS5CHS.INI"
//注意看这,是一个文件,直觉告诉我里面肯定有花样。我们就去打开看看里面到底是什么。
00416D9F |. 68 04010000 PUSH 104 ; |BufSize = 104 (260.)
00416DA4 |. 52 PUSH EDX ; |ReturnBuffer
00416DA5 |. 68 EC924400 PUSH CDSpaceV.004492EC ; |Default = "_______"
00416DAA |. 8D4C24 1C LEA ECX,DWORD PTR SS:[ESP+1C] ; |
00416DAE |. 50 PUSH EAX ; |Key=MSG_SHAREWARE_SHORTSERIAL
//还有这里,这个是键的名字,重那个文件里找到这一项,发现后面就是出错的提示。
00416DAF |. 51 PUSH ECX ; |Section
00416DB0 |. FF15 D4C14300 CALL DWORD PTR DS:[<&KERNEL32.GetPrivate>; \GetPrivateProfileStringA
00416DB6 |. 8B9424 8C02000>MOV EDX,DWORD PTR SS:[ESP+28C]
00416DBD |. 53 PUSH EBX
00416DBE |. 8D8424 7801000>LEA EAX,DWORD PTR SS:[ESP+178]
00416DC5 |. 52 PUSH EDX
00416DC6 |. 50 PUSH EAX
00416DC7 |. E8 C4F90100 CALL <JMP.&MFC42.#1200> //出错提示的CALL
00416DCC |. 8D8C24 8802000>LEA ECX,DWORD PTR SS:[ESP+288]
00416DD3 |. 8BF0 MOV ESI,EAX
00416DD5 |. C78424 8002000>MOV DWORD PTR SS:[ESP+280],-1
00416DE0 |. E8 5FF40100 CALL <JMP.&MFC42.#800>
00416DE5 |. 8B8C24 7802000>MOV ECX,DWORD PTR SS:[ESP+278]
00416DEC |. 8BC6 MOV EAX,ESI
00416DEE |. 5F POP EDI
00416DEF |. 5E POP ESI
00416DF0 |. 5B POP EBX
00416DF1 |. 64:890D 000000>MOV DWORD PTR FS:[0],ECX
00416DF8 |. 81C4 78020000 ADD ESP,278
00416DFE \. C3 RETN
既然有这些线索,我们先分析下,就是说,我们在断点的前面以近被判死刑了,所以,断点后面只是执行哪个死法,死法就是
MSG_SHAREWARE_SHORTSERIAL,shortserial意思就是序列号太短,这个怎么来,肯定还有类似的名字太短或者其他的提示,我们就在OD的reference里面搜索下看,有没有这些字符串。
代码区域点右键->search for->all referenced text string
来到字符串表,点右键->search for text,输入MSG_SHAREWARE_SHORTSERIAL。
找到了,果然旁边还有
ASCII "MSG_SHAREWARE_SHORTNAME"
ASCII "MSG_SHAREWARE_REGISTERED"
REGISTERED,哈哈,仿佛我们差不多成功了,呵呵,先下个断点在最前面的ASCII "MSG_SHAREWARE_SHORTSERIAL"上吧。
好,新的一轮又开始了,运行,点确定。断下!
如下
0042D5B5 . 6A 01 PUSH 1
0042D5B7 . E8 8A930000 CALL <JMP.&MFC42.#6334>
0042D5BC . 8B87 AC100000 MOV EAX,DWORD PTR DS:[EDI+10AC]
0042D5C2 . 8378 F8 01 CMP DWORD PTR DS:[EAX-8],1//这个看你名字是不是空的,空的就执行了
0042D5C6 . 7D 1F JGE SHORT CDSpaceV.0042D5E7
0042D5C8 . 6A 00 PUSH 0
0042D5CA . 51 PUSH ECX
0042D5CB . 8BCC MOV ECX,ESP
0042D5CD . 896424 10 MOV DWORD PTR SS:[ESP+10],ESP
0042D5D1 . 68 90A64400 PUSH CDSpaceV.0044A690 ; ASCII "MSG_SHAREWARE_SHORTNAME"
0042D5D6 . E8 D58C0000 CALL <JMP.&MFC42.#537>
0042D5DB . E8 1097FEFF CALL CDSpaceV.00416CF0
0042D5E0 . 83C4 08 ADD ESP,8
0042D5E3 . 5F POP EDI
0042D5E4 . 5E POP ESI
0042D5E5 . 59 POP ECX
0042D5E6 . C3 RETN
0042D5E7 > 8DB7 B0100000 LEA ESI,DWORD PTR DS:[EDI+10B0]//名字当然不空,走这里
0042D5ED . 68 E0AF4400 PUSH CDSpaceV.0044AFE0
0042D5F2 . 68 8CA64400 PUSH CDSpaceV.0044A68C
0042D5F7 . 8BCE MOV ECX,ESI
0042D5F9 . E8 7E930000 CALL <JMP.&MFC42.#6877>
0042D5FE . 68 E0AF4400 PUSH CDSpaceV.0044AFE0
0042D603 . 68 F8914400 PUSH CDSpaceV.004491F8
0042D608 . 8BCE MOV ECX,ESI
0042D60A . E8 6D930000 CALL <JMP.&MFC42.#6877>
0042D60F . 8B36 MOV ESI,DWORD PTR DS:[ESI]
0042D611 . 837E F8 10 CMP DWORD PTR DS:[ESI-8],10
0042D615 . 74 1F JE SHORT CDSpaceV.0042D636
0042D617 . 6A 00 PUSH 0
0042D619 . 51 PUSH ECX
0042D61A . 8BCC MOV ECX,ESP
0042D61C . 896424 10 MOV DWORD PTR SS:[ESP+10],ESP
0042D620 . 68 70A64400 PUSH CDSpaceV.0044A670 ; ASCII "MSG_SHAREWARE_SHORTSERIAL"
//这里断下,看看前面的代码,我们就在0042D5E7下个断,因为一看就知道这段是判断序列号够不够长的,前面是判断名字是不是空的。
重新运行重新断过
发现0042D611 . 837E F8 10 CMP DWORD PTR DS:[ESI-8],10
这一句是判断是不是长度有16个字符。
那我们重新运行,补齐16个。接着走。。。
我把序列号改成了ABCDEF1234567890
接下去就是判断序列号的过程了
0042D625 . E8 868C0000 CALL <JMP.&MFC42.#537>
0042D62A . E8 C196FEFF CALL CDSpaceV.00416CF0
0042D62F . 83C4 08 ADD ESP,8
0042D632 . 5F POP EDI
0042D633 . 5E POP ESI
0042D634 . 59 POP ECX
0042D635 . C3 RETN
0042D636 > 56 PUSH ESI ; /Arg1 这里的参数是你的序列号
0042D637 . 8BCF MOV ECX,EDI ; |
0042D639 . E8 82080000 CALL CDSpaceV.0042DEC0 ; \CDSpaceV.0042DEC0
这个CALL过后他就TEST EAX,EAX,检查是不是等于0,这就说明里面肯定有细节,而且要和真的比较过。
0042DEC0 /$ 6A FF PUSH -1
0042DEC2 |. 68 A8B04300 PUSH CDSpaceV.0043B0A8 ; SE handler installation
0042DEC7 |. 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
0042DECD |. 50 PUSH EAX
0042DECE |. 64:8925 000000>MOV DWORD PTR FS:[0],ESP
0042DED5 |. 83EC 20 SUB ESP,20
0042DED8 |. 56 PUSH ESI
0042DED9 |. 57 PUSH EDI
0042DEDA |. 8B7C24 38 MOV EDI,DWORD PTR SS:[ESP+38]
0042DEDE |. 8D47 0A LEA EAX,DWORD PTR DS:[EDI+A] //取你的序列号的最后6位数字“567890”
0042DEE1 |. 50 PUSH EAX ; /s
0042DEE2 |. FF15 10C94300 CALL DWORD PTR DS:[<&MSVCRT.atoi>] ; \atoi//转换成整数0x8AA52
0042DEE8 |. 83C4 04 ADD ESP,4
0042DEEB |. 8D4C24 38 LEA ECX,DWORD PTR SS:[ESP+38]
0042DEEF |. 50 PUSH EAX ; /Arg2//就是这个整数0x8AA52
0042DEF0 |. 51 PUSH ECX ; |Arg1 = 0012A61C ASCII "XF;"//这个不知道干什么用的,先不管
0042DEF1 |. B9 70B04400 MOV ECX,CDSpaceV.0044B070 ; |
0042DEF6 |. E8 A5C8FEFF CALL CDSpaceV.0041A7A0 ; \CDSpaceV.0041A7A0
0042DEFB |. 8B5424 38 MOV EDX,DWORD PTR SS:[ESP+38]
0042DEFF |. 57 PUSH EDI ; /s2 ASCII "ABCDEF1234567890"
0042DF00 |. 52 PUSH EDX ; |s1 ASCII "SE56821478567890"
一看就知道是比较序列号
那就是说前面的call应该是产生序列号把。爆破到这里结束,不过我们追求的是注册机。重新运行,在那个CALL下一个断点
0042DEF6 |. E8 A5C8FEFF CALL CDSpaceV.0041A7A0 ; \CDSpaceV.0041A7A0
如下
0041A7A0 /$ 6A FF PUSH -1
0041A7A2 |. 68 AF944300 PUSH CDSpaceV.004394AF ; SE handler installation
0041A7A7 |. 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
0041A7AD |. 50 PUSH EAX
0041A7AE |. 64:8925 000000>MOV DWORD PTR FS:[0],ESP
0041A7B5 |. 83EC 08 SUB ESP,8
0041A7B8 |. 56 PUSH ESI
0041A7B9 |. 8D4C24 04 LEA ECX,DWORD PTR SS:[ESP+4]
0041A7BD |. C74424 08 0000>MOV DWORD PTR SS:[ESP+8],0
0041A7C5 |. E8 86BA0100 CALL <JMP.&MFC42.#540>
0041A7CA |. 8B4C24 20 MOV ECX,DWORD PTR SS:[ESP+20]
0041A7CE |. C74424 14 0100>MOV DWORD PTR SS:[ESP+14],1
{
0041A7D6 |. 51 PUSH ECX //现在是十进制的567890,十六进制0x8AA52
0041A7D7 |. 8D04C9 LEA EAX,DWORD PTR DS:[ECX+ECX*8] //EAX=ECX*9
0041A7DA |. C1E0 05 SHL EAX,5 //EAX左移
0041A7DD |. 03C1 ADD EAX,ECX //EAX+ECX
0041A7DF |. 8D0440 LEA EAX,DWORD PTR DS:[EAX+EAX*2]//EAX*3
0041A7E2 |. 8D0481 LEA EAX,DWORD PTR DS:[ECX+EAX*4]//EAX=ECX+EAX*4
0041A7E5 |. 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8]//ECX=0x8AA52
0041A7E9 |. C1E0 03 SHL EAX,3 //EAX左移3位
0041A7EC |. 35 66660000 XOR EAX,6666
0041A7F1 |. 2D 081B0000 SUB EAX,1B08
0041A7F6 |. 35 5B80FFFF XOR EAX,FFFF805B
0041A7FB |. 25 A5FF0000 AND EAX,0FFA5
0041A800 |. 83C0 53 ADD EAX,53
}
核心部分,从你输入的最后6位数字算出,6位数字前面的4位16进制数字。
0041A803 |. 50 PUSH EAX //我出来是0x1478
0041A804 |. 68 AA020000 PUSH 2AA
0041A809 |. 68 E5000000 PUSH 0E5
0041A80E |. 6A 53 PUSH 53
0041A810 |. 68 1C974400 PUSH CDSpaceV.0044971C
; ASCII "%c%0.2X%0.3d%0.4X%0.6d"
这个格式对应就是 53(S),E5,2AA=682(dec),0x1478,567890(dec)
连起来序列号就是SE56821478567890
0041A815 |. 51 PUSH ECX
0041A816 |. E8 EFBA0100 CALL <JMP.&MFC42.#2818>
0041A81B |. 8B7424 38 MOV ESI,DWORD PTR SS:[ESP+38]
0041A81F |. 83C4 1C ADD ESP,1C
0041A822 |. 8D5424 04 LEA EDX,DWORD PTR SS:[ESP+4]
0041A826 |. 8BCE MOV ECX,ESI
0041A828 |. 52 PUSH EDX
0041A829 |. E8 1EBB0100 CALL <JMP.&MFC42.#535>
0041A82E |. C74424 08 0100>MOV DWORD PTR SS:[ESP+8],1
0041A836 |. 8D4C24 04 LEA ECX,DWORD PTR SS:[ESP+4]
0041A83A |. C64424 14 00 MOV BYTE PTR SS:[ESP+14],0
0041A83F |. E8 00BA0100 CALL <JMP.&MFC42.#800>
0041A844 |. 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
0041A848 |. 8BC6 MOV EAX,ESI
0041A84A |. 5E POP ESI
0041A84B |. 64:890D 000000>MOV DWORD PTR FS:[0],ECX
0041A852 |. 83C4 14 ADD ESP,14
0041A855 \. C2 0800 RETN 8
OK,大公告成。关于算法我已经分析的很清楚了。
如果想做注册机,可以用一个随即数产生算法产生一个6位数字,然后经过核心部分的代码,
算出那个4位数字,连接起来就是一个有效的序列号了。
这里是一段C代码,没有图形界面的,谁有好的注册机模版(VC++的)
希望能发个给我,我会非常感激的。
E-mail:4nil@163.com
VC++6.0编译通过。
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
int main()
{
unsigned long number;
unsigned long gen;
srand((unsigned int)time((time_t *)NULL));
number=(unsigned long)((double)rand() / ((double)RAND_MAX + 1.0) * 1000000.0);
/*直接从反编译拷贝过来,稍微修改下参数。很有用的。*/
__asm
{
MOV ECX,number
LEA EAX,DWORD PTR DS:[ECX+ECX*8]
SHL EAX,0x5
ADD EAX,ECX
LEA EAX,DWORD PTR DS:[EAX+EAX*2]
LEA EAX,DWORD PTR DS:[ECX+EAX*4]
LEA ECX,DWORD PTR SS:[ESP+8]
SHL EAX,0x3
XOR EAX,0x6666
SUB EAX,0x1B08
XOR EAX,0xFFFF805B
AND EAX,0xFFA5
ADD EAX,0x53
MOV gen,EAX
}
printf("one valid serial: SE5682%0.4X%0.6d\nthank u for using!\n",gen,number);
printf("\t\t\t--crack by 4nil");
getch();
return 0;
}
[注意]APP应用上架合规检测服务,协助应用顺利上架!