新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 为真正算法处,
- 注册码前5位累加: sum += (user[i] * 3 - 0x28) * user[i]
- eax = 0x66666667 * sum => 0x6666667=1,717,986,919, 右移0x22位相当于除以2^34 = 17,179,869,184
- edx = eax >> 0x22 = sum / 10, eax = eax & 0xFFFFFFFF
- eax = edx - (sum >> 0x1F) // sum>>31基本可以确定是0,7位相加都不会超过31位
- eax = (eax << 2 + edx) * 2 = edx * 10
- 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个是最常用的界面,其它的我基本上没用到~


浙公网安备 33010602011771号