首页
社区
课程
招聘
7
[原创]给大家个好玩的CM。考算法
发表于: 2011-2-10 18:15 13511

[原创]给大家个好玩的CM。考算法

2011-2-10 18:15
13511

给大家一个好玩的cm, VC  无壳 无Anti 加了简单自校验防爆破 主要考算法
所以尽量不要爆破。

由于注册码有关联性    我就先不给注册码了
我会在2周内给出制作方法及源码   成功后如下图

19楼公布本CM制作过程和源码


[注意]看雪招聘,专注安全领域的专业人才平台!

上传的附件:
收藏
免费 7
支持
分享
赞赏记录
参与人
雪币
留言
时间
Youlor
为你点赞~
2024-5-31 05:37
伟叔叔
为你点赞~
2024-3-15 00:57
心游尘世外
为你点赞~
2024-1-29 00:10
QinBeast
为你点赞~
2024-1-22 00:15
shinratensei
为你点赞~
2024-1-17 01:39
飘零丶
为你点赞~
2024-1-16 00:06
PLEBFE
为你点赞~
2023-3-11 05:55
最新回复 (21)
雪    币: 233
活跃值: (285)
能力值: ( LV12,RANK:270 )
在线值:
发帖
回帖
粉丝
2
好帖留名,下载下来看看,对破解不熟悉……
2011-2-10 18:57
0
雪    币: 85
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
等待答案嘻嘻
2011-2-10 19:34
0
雪    币: 458
活跃值: (426)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
4
突然发现  防暴做的太烂了。。。谁能给点防爆的方法   跪求。。。
2011-2-10 20:49
0
雪    币: 27
活跃值: (122)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
5
看到这篇帖子,我正想学习一下防爆呢?
2011-2-10 21:04
0
雪    币: 4022
活跃值: (97)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
搞不定,等待高手出现。。。
2011-2-11 00:02
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
7
5D429430D5297C29A9CF309740
2011-2-11 03:29
0
雪    币: 2105
活跃值: (594)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
拜模.1234
2011-2-11 09:17
0
雪    币: 458
活跃值: (426)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
9
我勒个去~~~膜拜。。。
没想到s牛   这么速度。
记得12点睡觉那会还没见s牛下载。。。
2011-2-11 09:22
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
10
我命苦, 作息很乱, 看来是活不过2100年了....

推箱子,这关很难, 我昨天推了很久

初始:
▓▓▓□♀□▓
▓▓▓☆☆☆▓
▓▓▓□□□▓
□□□□□☆▓
□☆□☆□□□
□□▓□▓□▓

达阵:
▓▓▓□□□▓
▓▓▓□□□▓
▓▓▓□□□▓
□□□☆□□▓
□□☆□☆□☆
□□▓☆▓☆▓
2011-2-11 10:11
0
雪    币: 8209
活跃值: (4559)
能力值: ( LV15,RANK:2473 )
在线值:
发帖
回帖
粉丝
11
从上图得知s是雌性的
2011-2-11 10:40
0
雪    币: 2105
活跃值: (594)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
♀ ~123345
2011-2-11 10:47
0
雪    币: 458
活跃值: (426)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
13
求交往。。。。
上传的附件:
2011-2-11 10:48
0
雪    币: 291
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14

后面的就很好推了~!blu大牛也喜欢推啊~!
2011-2-11 11:31
0
雪    币: 291
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
看不出来~!
2011-2-11 11:34
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
16
我本来是画 ♂
改成♀是要勾你出来
2011-2-11 11:55
0
雪    币: 69
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
话说无法下载 难道是我的问题?
2011-2-11 18:40
0
雪    币: 212
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
都是来画画的?
2011-2-13 14:41
0
雪    币: 458
活跃值: (426)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
19
先看一张图片和一个函数



推箱子图片  推箱子程序37关   然后我想设计一个函数  参数就是推箱子的路线。
好了 我规定
2进制的  
00   向上走一步
01   向下走一步
10   向左走一步
11   向右走一步
刚好4步组成一个byte  假如最后一个byte的前2步刚好走完全程  那么后面的2步都清零 (也就是向上走)

好了  设计函数如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#define STONE   0
#define EMPTY   1
#define BOX     2
 
#define UP      0
#define DOWN    1
#define LEFT    2
#define RIGHT   3
 
#define MAX_I   6
#define MAX_J   7
 
//次函数返回 (100 - 一共花费的步数)
int __stdcall IsRightKey(PBYTE buf, int iLength)
{
    int iCountStep = 0;
    //棋盘
    BYTE bChessBoard[MAX_I][MAX_J] =
    {
        {STONE, STONE, STONE, EMPTY, EMPTY, EMPTY, STONE},
        {STONE, STONE, STONE, BOX, BOX, BOX, STONE},
        {STONE, STONE, STONE, EMPTY, EMPTY, EMPTY, STONE},
        {EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BOX, STONE},
        {EMPTY, BOX, EMPTY, BOX, EMPTY, EMPTY, EMPTY},
        {EMPTY, EMPTY, STONE, EMPTY, STONE, EMPTY, STONE}
    };
    //当前小孩的位置
    int iChild_i = 0;
    int iChild_j = 4;
     
    int     iPos = 0;
    PBYTE   pCur = buf;
    //遍历取得每一个字节,然后解析每个字节的4小步
    while(iPos < iLength)
    {
        BYTE bTemp = *(pCur + iPos);
        //分解成4小步
        BYTE b4[4] = {0,0,0,0};
        b4[0] = (bTemp>>6) & 0x03;
        b4[1] = (bTemp>>4) & 0x03;
        b4[2] = (bTemp>>2) & 0x03;
        b4[3] = bTemp & 0x03;
         
        //一共是4步
        for (int i=0; i<4; i++)
        {
            switch(b4[i])
            {
            case UP:
                //先判断是否越界
                if (iChild_i == 0)
                {
                    return 0;
                }
                //如果是石头
                if (bChessBoard[iChild_i-1][iChild_j] == STONE)
                {
                    return 0;
                }
                //如果是空地
                if (bChessBoard[iChild_i-1][iChild_j] == EMPTY)
                {
                    iChild_i--;
                    break;
                }
                //现在肯定是箱子了
                //判断箱子上面是否是边界
                if (iChild_i-1 == 0)
                {
                    return 0;
                }
                //判断箱子上方是否有空位置
                if (bChessBoard[iChild_i-2][iChild_j] != EMPTY)
                {
                    return 0;
                }
                else
                {
                    bChessBoard[iChild_i-2][iChild_j] = BOX;
                    bChessBoard[iChild_i-1][iChild_j] = EMPTY;
                    iChild_i--;
                    break;
                }
                __asm int 3;
                break;
            case DOWN:
                //先判断是否越界
                if (iChild_i == MAX_I-1)
                {
                    return 0;
                }
                //如果是石头
                if (bChessBoard[iChild_i+1][iChild_j] == STONE)
                {
                    return 0;
                }
                //如果是空地
                if (bChessBoard[iChild_i+1][iChild_j] == EMPTY)
                {
                    iChild_i++;
                    break;
                }
                //现在肯定是箱子了
                //判断箱子下面是否是边界
                if (iChild_i+1 == MAX_I-1)
                {
                    return 0;
                }
                //判断箱子下方是否有空位置
                if (bChessBoard[iChild_i+2][iChild_j] != EMPTY)
                {
                    return 0;
                }
                else
                {
                    bChessBoard[iChild_i+2][iChild_j] = BOX;
                    bChessBoard[iChild_i+1][iChild_j] = EMPTY;
                    iChild_i++;
                    break;
                }
                __asm int 3;
                break;
            case LEFT:
                //先判断是否越界
                if (iChild_j == 0)
                {
                    return 0;
                }
                //如果是石头
                if (bChessBoard[iChild_i][iChild_j-1] == STONE)
                {
                    return 0;
                }
                //如果是空地
                if (bChessBoard[iChild_i][iChild_j-1] == EMPTY)
                {
                    iChild_j--;
                    break;
                }
                //现在肯定是箱子了
                //判断箱子左面是否是边界
                if (iChild_j-1 == 0)
                {
                    return 0;
                }
                //判断箱子左方是否有空位置
                if (bChessBoard[iChild_i][iChild_j-2] != EMPTY)
                {
                    return 0;
                }
                else
                {
                    bChessBoard[iChild_i][iChild_j-2] = BOX;
                    bChessBoard[iChild_i][iChild_j-1] = EMPTY;
                    iChild_j--;
                    break;
                }
                __asm int 3;
                break;
            case RIGHT:
                //先判断是否越界
                if (iChild_j == MAX_J-1)
                {
                    return 0;
                }
                //如果是石头
                if (bChessBoard[iChild_i][iChild_j+1] == STONE)
                {
                    return 0;
                }
                //如果是空地
                if (bChessBoard[iChild_i][iChild_j+1] == EMPTY)
                {
                    iChild_j++;
                    break;
                }
                //现在肯定是箱子了
                //判断箱子右面是否是边界
                if (iChild_j+1 == MAX_J-1)
                {
                    return 0;
                }
                //判断箱子右方是否有空位置
                if (bChessBoard[iChild_i][iChild_j+2] != EMPTY)
                {
                    return 0;
                }
                else
                {
                    bChessBoard[iChild_i][iChild_j+2] = BOX;
                    bChessBoard[iChild_i][iChild_j+1] = EMPTY;
                    iChild_j++;
                    break;
                }
                __asm int 3;
                break;
            default:
                __asm int 3;
                break;
            }
            //检测是否OK了
            iCountStep++;
            if (bChessBoard[3][3] == BOX &&
                bChessBoard[4][2] == BOX &&
                bChessBoard[4][4] == BOX &&
                bChessBoard[4][6] == BOX &&
                bChessBoard[5][3] == BOX &&
                bChessBoard[5][5] == BOX)
            {
                for (int j=i+1; j<4; j++)
                {
                    if (b4[j] != 0)
                    {
                        return 0;
                    }
                }
                if (iLength == iPos+1)
                {
                    return 100-iCountStep;
                }
                else
                    return 0;
            }
        }
        iPos++;
    }
    return 0;
}


这是核心判断代码了  如果写个简单VM把这个函数处理一下   难度会大上n倍   
下面讲述如何假如简单  防爆破   我用了简单的CRC32做校验算法。
我想的方法很弱   得用OD自己patch  记得海风大侠有个cm防爆  不用OD patch 直接代码编译出来的
CRC32 算法代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
unsigned int GetCrc32(char* InStr,unsigned int len)
    //生成Crc32的查询表
    unsigned int Crc32Table[256] = {0};
    unsigned int Crc;
    for (unsigned int i = 0; i < 256; i++)
    
        Crc = i;
        for (unsigned int j = 0; j < 8; j++)
        
            if (Crc & 1) 
                Crc = (Crc >> 1) ^ 0xEDB88320;
            else 
                Crc >>= 1;
        }
        Crc32Table[i] = Crc; 
    
     
    //开始计算CRC32校验值
    Crc = 0xFFFFFFFF;
    for(i=0; i<len; i++)
    {
        Crc = (Crc >> 8) ^ Crc32Table[(Crc & 0xFF) ^ (BYTE)InStr[i]]; 
    }
     
    Crc ^= 0xFFFFFFFF;
    return Crc;
}


下面是ok按钮的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
BYTE g_szCaption[100] = {0xcc,0xe1,0xca,0xbe, 0x00};    //需要用crc1 来异或  用OD自己patch
BYTE g_szText[100] = {0xB9,0xA7,0xCF,0xB2,0xB9,0xFD,0xB9,0xD8,0x00}; //需要用crc2 来异或  用OD自己patch
 
//5943d297ea29cf30d5424094  这是一个合理的路径  也可以自己找一个
void CCrackMeDlg::OnOK()
{
    DWORD dwFucAddr = 0x12345678;   //这个地址需要修改为导入表MessageBoxIndirectA的地址  需要自己用LordPE 查 然后自己patch
    int i=0;
    int iResult = 0;
    int iKeyLength = 0;
    char szKey[1024] = {0};
    BYTE bKey[512] = {0};
 
    MSGBOXPARAMSA msg;
    ZeroMemory(&msg, sizeof(msg));
    msg.cbSize = sizeof(MSGBOXPARAMSA);
    msg.lpszCaption = (LPSTR)g_szCaption;
    msg.lpszText = (LPSTR)g_szText;
    MessageBoxIndirectA(&msg);  //这里调用一下只是为了让导入表里有此函数  需要自己patch掉
 
    DWORD dwCrcSubFuction = 0;
    DWORD dwCrcJudge = 0;
 
    GetDlgItemText(IDC_EDIT1, szKey, 1024);
    iKeyLength = lstrlen(szKey);
    if (iKeyLength <= 4 || iKeyLength >= 1000 || iKeyLength%2 != 0)
    {
        goto __error;
    }
    for (i=0; i<iKeyLength; i++)
    {
        if ((szKey[i] >= 'A' && szKey[i] <= 'F') || (szKey[i] >= '0' && szKey[i] <= '9') || (szKey[i] >= 'a' && szKey[i] <= 'z'))
        {
            __asm nop
        }
        else
            goto __error;
    }
__Judge_s:
    StringToHex(szKey, bKey);
    iResult = IsRightKey(bKey, iKeyLength/2);
    if (iResult == 0)
    {
        goto __error;
    }
 
    __asm
    {
        mov eax, offset __Judge_s
        mov dwCrcJudge, eax
    }
    //跟踪到这里 记住俩crc值  需要调试找到这俩值
    dwCrcJudge = GetCrc32((char *)dwCrcJudge, 0x36);  //其实这里直接把OK按钮开始到 本句的地址 做个crc就更好了
    dwCrcSubFuction = GetCrc32((char *)IsRightKey+1, 0x300);
 
    *(DWORD*)g_szCaption ^= dwCrcJudge;
    *(DWORD*)g_szText ^= dwCrcSubFuction;
    *(DWORD*)(g_szText+4) ^= dwCrcSubFuction;
 
    dwFucAddr ^= dwCrcJudge;
    dwFucAddr ^= dwCrcSubFuction;
    dwFucAddr = *(DWORD*)dwFucAddr;  //解密得到真正的api地址
 
    dwCrcJudge = (DWORD)&msg;
    __asm
    {
        push dwCrcJudge
        call dwFucAddr
    }
__error:
    __asm nop
}


如果您有什么好的 防爆破 思路欢迎  一起跟帖讨论。
上传的附件:
2011-2-16 10:11
0
雪    币: 435
活跃值: (1387)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
20
s大貌似很喜欢这种奇怪有难度又有趣味的cm
2012-2-17 23:15
0
雪    币: 9
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
21
不知道是什么情况,当你填入真的注册码以后,一次出来的对话框是正确的,但是你再点击就出来了乱码,在OD中可以查找这个字符串额,没有分析出来只是后来发现这个才实现的
上传的附件:
  • 1.jpg (14.46kb,132次下载)
  • 2.jpg (14.12kb,131次下载)
  • 3.jpg (37.38kb,135次下载)
2012-2-20 14:56
0
雪    币: 278
活跃值: (709)
能力值: ( LV15,RANK:520 )
在线值:
发帖
回帖
粉丝
22
膜拜各路大神显灵
2012-2-20 15:26
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册