新CrackMe160之146 - br0ken - cm2

OD载入程序, 搜索界面定位到成功关键词00401421,向上找到入口00401366(输入处)下断点,分析算法:
00401366 ~ 00401397 分析可得 len * len * len - len * len * 5 - len * 6 = 0x38 => len * (len + 1) * (len - 6) = 1 * 7 * 8 => len = 7 一元三次方程唯一整数解
输入7位试一下是否通过第一长度验证,(肯定是会通过的,正经解出来的)
004013B1 ~ 0040141B 为真正算法处,

  1. 注册码前5位累加: sum += (user[i] * 3 - 0x28) * user[i]
  2. eax = 0x66666667 * sum => 0x6666667=1,717,986,919, 右移0x22位相当于除以2^34 = 17,179,869,184
  3. edx = eax >> 0x22 = sum / 10, eax = eax & 0xFFFFFFFF
  4. eax = edx - (sum >> 0x1F) // sum>>31基本可以确定是0,7位相加都不会超过31位
  5. eax = (eax << 2 + edx) * 2 = edx * 10
  6. sum - eax == 0 => sum / 10 * 10 ?== sum
    由上分析可得 sum / 10 * 10 还要等于sum, 说明sum/10得整除, 也就是sum最后一位一定要为0
    注册机如下:
#include <stdio.h>
#include <string.h>

int chkCode(char *code);
int getCode(int index, int len, char* code);

int main() {
	int rlt;
	char code[8] = {0};
	rlt = getCode(0, 7, code);
	printf("结束\n"); 
	getchar(); return 0;
}

int chkCode(char *code){
	int i, sum=0;
	for(i=0; i<6; i++){
		sum += (code[i] * 3 - 0x28) * code[i];
	}
	if(sum % 10 == 0){
		return 1;
	}
	return 0;
}

int getCode(int index, int len, char* code){
	int i, rlt = 0;
	if(index == len){
		rlt = chkCode(code);
		if(rlt == 1){
			printf("注册码: %s\n", code);
			return 1; // 0:返回所有情况, 1:返回第1个 
		}
		return rlt;
	}
	//for(int i=0x20; i<0x7F; i++){ //可见字符区域abcdefghijklmnopqrstuvwxyz
	//	name[index] = (char) i;
	char *str = "0123456789"; //自定义注册码值类型 
	for(i=0; i<strlen(str); i++){
		code[index] = str[i];
		rlt = getCode(index+1, len, code);
		if(rlt == 1) return 1; 
	}
	return 0;
}

运行示例:
注册码: 0000020

 
 
本节高手录制的视频,点击前往查看

 
 
 
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载

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

posted @ 2024-12-30 14:35  hankerstudio  阅读(5)  评论(0)    收藏  举报