新手破解练习Crackme160之117 - CoDe_InSiDe

本程序依旧是98下的程序, 98下OD载入程序, 代码量比较少, 运行后直接上翻就可以看到按键事件相关代码, 智能搜索界面定位关键词也可以定位到事件~, 004011B8, 00401144与004010A9处分别下断, 输入Name: abc, Organization: 123, Serial: 4567890, 按验证按钮后停在了004010A9处, 所以这个是按钮入口, 算法分析:
1). 将Name每一位对应的asc值作为位置, 在固定串的开始位置00402300, 对应的位置标为1
2). 将公司名每一位对应的asc值作为位置, 在上面固定串的最后一位(004023FF)开始位置的对应反向位置上标1
3). 找出固定串中每个1的位置+1并存到00401E90对应的每一位上得到 00401E90 62 63 64 CC CD CE bcd掏?:
4). 将上面得到的几位分别判断是否在0x20~0x7E之间的可见字符内, 不是的话, 小于0x20的+0x45, 大于0x7E的-0x46 得到新串 00401E90 62 63 64 86 87 88 bcd唶?:
5). 再来一遍4). 得到 00401E90 62 63 64 40 41 42 bcd@AB
6). 对比用户名和公司名长度和与系列号长度, 如果大于则失败结束~, 如果小于则跳到0040118A继续运行~
7). 00401E90开始每4位是否为0, 为0跳出循环, 不为0则将值与00401FA9 00 0D 0C 0B 0A, 异或, 存入edi+20地址中
8). 将结果串判断是否是可见字符, 小于0x20的+0x30, 大于0x7E的+0xD0
9). 得到的串与系列号对比, 到此算法分析完成,
用户名与公司名的长度和len要符合len%4!=0, 系列号长度为: ((int)len/4 + 1)*4, 调试过程可知, 作者给每个变量的空间是32位, 系列号最长只有20位, 所以用户名和公司名总长度不得超过20位, 可以开始写注册机代码了~

#include <stdio.h>
#include <string.h>

int main() {
	int lenn,lenp,lenc, tmp, codei = 0;
	char name[21] = {0};
	char comp[21] = {0};
	char code[21] = {0}; 
	char str[257] = {0x30}; str[256] = 0; //固定串256个0 
	printf("用户名: "); scanf("%s", name);
	lenn = strlen(name);
	printf("公司名: "); scanf("%s", comp);
	lenp = strlen(comp);
	if(lenn + lenp >= 20){
		printf("用户名和公司名总长不得超过20位!");
		return 0;
	}
	if((lenn + lenp) % 4 == 0) {
		printf("用户名和公司名总长不能为4的倍数~");
		return 0;
	}
	for(int i=0; i<lenn; i++){ //将用户名每一位的值在str中标注为1
		str[name[i]] = '1';
	}
	for(int i=0; i<lenp; i++){ //将公司名每一位的值反向在str中标注为1
		str[0xFE - comp[i]] = '1';
	}
	for(int i=0; i<0xFF; i++){ //找出所有字符的正序位置
		if(str[i] == '1'){
			tmp = i+1;
			while((tmp < 0x20) || (tmp > 0x7E)) { //使其在可见字符区内 
				if(tmp < 0x20) tmp += 0x45;
				if(tmp > 0x7E) tmp -= 0x46;
			}
			code[codei++] = (char) tmp;
		}
	}
	char c4;
	for(int i=0; i<lenn+lenp; i+=4){
		tmp = 0;
		tmp += code[i+0];
		tmp += code[i+1] << 8;
		tmp += code[i+2] << 16;
		tmp += code[i+3] << 24;
		tmp ^= 0x0A0B0C0D;
		c4 = (tmp & 0xFF); tmp = tmp >> 8;
		if(c4 < 0x20) { c4 += 0x30; } else if(c4 > 0x7E){ c4 += 0xD0; } //修正可见区 
		code[i+0] = (char)c4;
		c4 = (tmp & 0xFF); tmp = tmp >> 8;
		if(c4 < 0x20) { c4 += 0x30; } else if(c4 > 0x7E){ c4 += 0xD0; }
		code[i+1] = (char)c4;
		c4 = (tmp & 0xFF); tmp = tmp >> 8;
		if(c4 < 0x20) { c4 += 0x30; } else if(c4 > 0x7E){ c4 += 0xD0; }
		code[i+2] = (char)c4;
		c4 = (tmp & 0xFF); tmp = tmp >> 8;
		if(c4 < 0x20) { c4 += 0x30; } else if(c4 > 0x7E){ c4 += 0xD0; }
		code[i+3] = (char)c4;
	} 
	
	printf("序列号: %s\n", code);
	getchar();getchar();
	return 0;
}

运行示例:
用户名: abcde
公司名: 12345
序列号: ooook24JLN;:

10). 作者在后面还准备了彩蛋~, 当你第一次不小心输错系列号以后, 后面再输入正确的系列号就无法再验证通过了~ 跟踪发现, 作者第二次验证又进入到了新的算法, 也就是只你要第一次输入的不是正确的序列号, 那后面的正确系列号将是另外的了~ 原来的系列号将作废(不过重启程序后, 第一组正确的序列号仍然可以用_), 这里也附上第二组系列号算法注册机~

#include <stdio.h>
#include <string.h>

int main() {
	int lenn,lenp,lenc, tmp, codei = 0;
	char name[21] = {0};
	char comp[21] = {0};
	char code[21] = {0};
	char cod1[21] = {0}; //第一次输入错误系列号
	char str[257] = {0x30}; str[256] = 0; //固定串256个0 
	printf("用户名: "); scanf("%s", name);
	lenn = strlen(name);
	printf("公司名: "); scanf("%s", comp);
	lenp = strlen(comp);
	printf("错误系列号: "); scanf("%s", cod1);
	lenc = strlen(cod1); 
	if(lenn + lenp >= 20){
		printf("用户名和公司名总长不得超过20位!");
		return 0;
	}
	if((lenn + lenp) % 4 == 0) {
		printf("用户名和公司名总长不能为4的倍数~");
		return 0;
	}
	if((lenn + lenp) >= lenc) {
		printf("系列号长度必须大于用户名和公司名总长!");
		return 0;
	}
	for(int i=0; i<20; i+=4) { // 将错误系列号前4位初始化20位给正确系列号 
		code[i+0] = cod1[0];
		code[i+1] = cod1[1];
		code[i+2] = cod1[2];
		code[i+3] = cod1[3];
	}
	for(int i=0; i<lenn; i++){ //将用户名每一位的值在str中标注为1
		str[name[i]] = '1';
	}
	for(int i=0; i<lenp; i++){ //将公司名每一位的值反向在str中标注为1
		str[0xFE - comp[i]] = '1';
	}
	for(int i=0; i<0xFF; i++){ //找出所有字符的正序位置
		if(str[i] == '1'){
			tmp = i+1;
			while((tmp < 0x20) || (tmp > 0x7E)) { //使其在可见字符区内 
				if(tmp < 0x20) tmp += 0x45;
				if(tmp > 0x7E) tmp -= 0x46;
			}
			code[codei++] = (char) tmp;
		}
	}
	char c4;
	for(int i=0; i<lenn+lenp; i+=4){
		tmp = 0;
		tmp += code[i+0];
		tmp += code[i+1] << 8;
		tmp += code[i+2] << 16;
		tmp += code[i+3] << 24;
		tmp ^= 0x0A0B0C0D;
		c4 = (tmp & 0xFF); tmp = tmp >> 8;
		if(c4 < 0x20) { c4 += 0x30; } else if(c4 > 0x7E){ c4 += 0xD0; } //修正可见区 
		code[i+0] = (char)c4;
		c4 = (tmp & 0xFF); tmp = tmp >> 8;
		if(c4 < 0x20) { c4 += 0x30; } else if(c4 > 0x7E){ c4 += 0xD0; }
		code[i+1] = (char)c4;
		c4 = (tmp & 0xFF); tmp = tmp >> 8;
		if(c4 < 0x20) { c4 += 0x30; } else if(c4 > 0x7E){ c4 += 0xD0; }
		code[i+2] = (char)c4;
		c4 = (tmp & 0xFF); tmp = tmp >> 8;
		if(c4 < 0x20) { c4 += 0x30; } else if(c4 > 0x7E){ c4 += 0xD0; }
		code[i+3] = (char)c4;
	} 
	printf("正确序列号: %s\n", code);
	
	getchar();getchar();
	return 0;
}

运行示例:
用户名: abc
公司名: 123
错误系列号: 4567890 (第一次输入这个, 无法验证通过)
正确序列号: oooJLN==456745674567 (第二次输入这个可以验证通过)

 
 
 
这是160个软件part1
这是160个软件part2

1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载

新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~

下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~
OD界面布局

posted @ 2024-07-19 18:01  hankerstudio  阅读(8)  评论(0)    收藏  举报