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

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

2011-2-10 18:15
13410

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

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

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


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (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
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
4
突然发现  防暴做的太烂了。。。谁能给点防爆的方法   跪求。。。
2011-2-10 20:49
0
雪    币: 27
活跃值: (127)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
5
看到这篇帖子,我正想学习一下防爆呢?
2011-2-10 21:04
0
雪    币: 4022
活跃值: (92)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
搞不定,等待高手出现。。。
2011-2-11 00:02
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
7
5D429430D5297C29A9CF309740
2011-2-11 03:29
0
雪    币: 2105
活跃值: (424)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
拜模.1234
2011-2-11 09:17
0
雪    币: 458
活跃值: (421)
能力值: ( 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
活跃值: (4518)
能力值: ( LV15,RANK:2473 )
在线值:
发帖
回帖
粉丝
11
从上图得知s是雌性的
2011-2-11 10:40
0
雪    币: 2105
活跃值: (424)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
♀ ~123345
2011-2-11 10:47
0
雪    币: 458
活跃值: (421)
能力值: ( 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
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
19
先看一张图片和一个函数



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

好了  设计函数如下
#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 算法代码。
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按钮的函数
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
活跃值: (1282)
能力值: ( 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
游客
登录 | 注册 方可回帖
返回
//