首页
社区
课程
招聘
[原创]CDspace5.0(虚拟光驱大师)注册算法分析+注册机代码
发表于: 2005-11-25 07:44 12365

[原创]CDspace5.0(虚拟光驱大师)注册算法分析+注册机代码

4nil 活跃值
13
2005-11-25 07:44
12365

[目标]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应用上架合规检测服务,协助应用顺利上架!

收藏
免费 7
支持
分享
最新回复 (18)
雪    币: 6047
活跃值: (2852)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
好啊 学习了!
2005-11-25 08:10
0
雪    币: 212
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
的确不错,写得挺详细的。
2005-11-25 08:20
0
雪    币: 313
活跃值: (440)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
4
呵呵,好久没来论坛了,昨天为了安装游戏,下载了这个软件,15天限制的,多不爽,遂破之,想想好久没为论坛做贡献就写篇破文吧
2005-11-25 08:24
0
雪    币: 236
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
很好。

我正想研究呢。
2005-11-25 09:38
0
雪    币: 226
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
#include <stdafx.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdio.h>

int main()
{
  unsigned long number;
  unsigned long gen;
  char serial[17];
  serial[16]='\0';
  
  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");
  return 0;
}
2005-11-25 12:06
0
雪    币: 332
活跃值: (479)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
7
作者没这么弱智吧,就是说同一用户可以有无数注册码!
最后6位随机!看看还有检测吗?感觉最后6位应与用户名有关呢,否则算法太垃圾了!
2005-11-25 12:15
0
雪    币: 421
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
支持了  好好学习
2005-11-25 13:46
0
雪    币: 313
活跃值: (440)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
9
最初由 laoqian 发布
作者没这么弱智吧,就是说同一用户可以有无数注册码!
最后6位随机!看看还有检测吗?感觉最后6位应与用户名有关呢,否则算法太垃圾了!


你可以去他的主页试着注册,他会提示你输入序列号而不需要提供用户名,这就说明是与用户名无关的
2005-11-25 13:49
0
雪    币: 332
活跃值: (479)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
10
哦,算我废话了,呵呵。只是觉得他的算法过于简单了。另外注册成功后,功能全吧?所有功能没有限制吧,
产生一个想法:序列号的最后6位数字看来是在作者那里生成,然后放在数据库(也很可能是算法),这样网上注册就能知道是否是非法用户!这想法到不错呢!如果没有作者的注册机(或数据库),虽然可以本地注册,但无法通过联网注册!
2005-11-25 14:04
0
雪    币: 313
活跃值: (440)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
11
不简单的话我就不会破了哈哈
2005-11-25 14:05
0
雪    币: 260
活跃值: (81)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
支持!学习!
2005-11-25 21:00
0
雪    币: 61
活跃值: (160)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
13
2005-11-25 21:48
0
雪    币: 214
活跃值: (15)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
最初由 萝卜 发布
支持!学习!
2005-11-25 22:43
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
2005-11-25 23:02
0
雪    币: 231
活跃值: (465)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
不错 想不到现在还有那么弱的软件
2005-11-27 16:34
0
雪    币: 236
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
再学习。。。
2005-11-27 19:34
0
雪    币: 273
活跃值: (250)
能力值: ( LV9,RANK:410 )
在线值:
发帖
回帖
粉丝
18
学习哦。!!!
2005-11-27 22:32
0
雪    币: 236
活跃值: (46)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
忠实的支持者
2005-12-4 03:25
0
游客
登录 | 注册 方可回帖
返回
//