zoukankan      html  css  js  c++  java
  • 关于KeyFile的破解,含注册机源代码

    程序来自于《加密与解密3》的第五章的PacMe.exe。书中并没有给出C语言实现的加密与解密代码,自己花了一些时间,把代码还原了,并且写了一个C语言的注册机。

    加密原理:正如书中所说,此程序是生成一个11x16的迷宫,其中*表示不通,.表示通,起点为C,终点为X。所经过的路径的方向,每4个作为1字节,成为加密的数据。

    解密思路:通过IDA导出程序的迷宫数据,通过寻路算法,找到唯一路径,然后按照KeyFile格式加密并生成KeyFile。

    迷宫数据:

    char Maze[] = { "****************"
    							"C*......*...****"
    							".*.****...*....*"
    							".*..**********.*"
    							"..*....*...*...*"
    							"*.****.*.*...***"
    							"*.*....*.*******"
    							"..*.***..*.....*"
    							".*..***.**.***.*"
    							"...****....*X..*"
    							"****************" };//11*16

    先看下从程序里反汇编出的解密函数:

    bool KeyCode(const char *szFilename, char *pMaze) {//KwazyWeb.bit
    	HANDLE hFile;
    	if ((hFile = CreateFileA(szFilename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
    		0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
    		CloseHandle(hFile);
    		return false;
    	}
    	DWORD dwByteRead;
    	BYTE bUsersize;
    	ReadFile(hFile, &bUsersize, 1, &dwByteRead, NULL);
    	if (bUsersize == 0) {
    		CloseHandle(hFile);
    		return false;
    	}
    	//0x403288
    	DWORD dwByteUser = 0;
    	char szUserInfo[100];
    	ReadFile(hFile, szUserInfo, bUsersize, &dwByteRead, NULL);
    	//用户名求和
    	for (int i = 0; i < (int)bUsersize; i++)
    		dwByteUser += szUserInfo[i];
    	//0x4034e8
    	BYTE szDataInfo[18];
    	ReadFile(hFile, szDataInfo, 18, &dwByteRead, NULL);
    	//异或数据
    	for (int i = 0; i < 18; i++) 
    		szDataInfo[i] = szDataInfo[i] ^ (BYTE)dwByteUser;
    	int k;
    	char *pos = &pMaze[16];
    	for (int j = 0; j < 18; j++)
    		for (int i = 8; i != 0;) {
    			i -= 2;
    			k = szDataInfo[j] >> i & 3;
    			if (k == 0)
    				pos = pos - 16;//↑
    			else if (k == 1)//→
    				pos++;
    			else if (k == 2)//↓
    				pos = pos + 16;
    			else//←
    				pos--;
    		}
    	//判断是否到达位置X
    		if (pos[0] != 'X'){
    			CloseHandle(hFile);
    			return false;
    		}
    	CloseHandle(hFile);
    	return true;
    }
    

    注册机实现(第一次写注册机,还专门学习了下寻路算法):

    void KeyGen(const char *szFilename, char *pMaze, const char *szName) {
    	HANDLE hFile;
    	if ((hFile = CreateFileA(szFilename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
    		0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
    		CloseHandle(hFile);
    		return;
    	}
    	std::list<int> path;
    	std::vector<int> pack;
    	int len = lstrlenA(pMaze), pos;
    	char *pMaze1 = new char[len + 1];
    	memcpy(pMaze1, pMaze, len + 1);//包含''
    	for (pos = 0; pos < len; pos++)
    		if (pMaze1[pos] == 'C')
    			break;
    	path.push_back(pos);
    	Walk(pMaze1, pos / 16, pos - pos / 16 * 16, path);
    	//计算序列值
    	int i, j;
    	pos = path.front();
    	path.pop_front();
    	while (!path.empty()) {
    		i = path.front() / 16 - pos / 16;
    		j = path.front() - path.front() / 16 * 16 - (pos - pos / 16 * 16);
    		if (j == 0) {
    			if (i > 0)
    				pack.push_back(2);
    			else if (i < 0)
    				pack.push_back(0);
    		}
    		else if (i == 0) {
    			if (j > 0)
    				pack.push_back(1);
    			else if (j < 0)
    				pack.push_back(3);
    		}
    		pos = path.front();
    		path.pop_front();
    	}
    	pos = lstrlenA(szName);
    	len = 0;
    	for (i = 0; i < pos; i++)
    		len += szName[i];
    	for (i = 0; i < (int)pack.size(); i += 4)
    		path.push_back((pack[i] << 6 | pack[i + 1] << 4 | pack[i + 2] << 2 | pack[i + 3]) ^ (BYTE)len);
    	WriteFile(hFile, &pos, 1, (DWORD *)&j, NULL);
    	WriteFile(hFile, szName, pos, (DWORD *)&j, NULL);
    	for (auto itr = path.begin(); itr != path.end(); itr++) 
    		WriteFile(hFile, &(*itr), 1, (DWORD *)&j, NULL);
    	delete[] pMaze1;
    	CloseHandle(hFile);
    }
    

    其中寻路算法函数Walk实现如下:

    bool Walk(char *pMaze, int i, int j, std::list<int> &path) {
    	if (pMaze[i * 16 + j] == 'X') 
    		return true;
    	int distX[] = { -1,0,1,0 }, distY[] = { 0,1,0,-1 };
    	for (int k = 0; k < 4; k++) {
    		if (i + distX[k] >= 0 && i + distX[k] < 11 && j + distY[k] >= 0 && j + distY[k] < 16
    			&& (pMaze[(i + distX[k]) * 16 + j + distY[k]] == '.' || pMaze[(i + distX[k]) * 16 + j + distY[k]]=='X')) {//下一步通路
    			pMaze[i * 16 + j] = '*';//当前封路
    			path.push_back((i + distX[k]) * 16 + j + distY[k]);//下一步入栈
    			if (!Walk(pMaze, i + distX[k], j + distY[k], path)) {
    				path.pop_back();
    				pMaze[i * 16 + j] = '.';//开路
    				continue;
    			}
    			return true;
    		}
    	}
    	return false;
    }
    

    Main函数测试如下:

    int main(){
    	KeyGen("key.bit", Maze, "Thanks, pediy!");//注册机
    	if (KeyCode("key.bit", Maze))//解码
    		printf("Valid Key file
    ");
    	else 
    		printf("Contact me to get Key file
    ");
    	system("pause");
    }
    

    代码测试图

  • 相关阅读:
    windows下 删除指定文件夹里面一周前的所有文件和文件夹的bat
    freeswitch 把SIP注册信息数据库从SQLITE 改为MYSQL的方法
    memcached+Mysql(主从)
    Linux下的MySQL主主复制
    RabbitMQ php 使用
    如果你写PHP, 请多注意自己是否有良好的习惯
    MySQL主从配置的一些总结
    Mongodb与mysql语法比较
    Yii框架tips
    Windows下Python添加MySQLdb扩展模块
  • 原文地址:https://www.cnblogs.com/dalgleish/p/9973674.html
Copyright © 2011-2022 走看看