016-fty_crkme3 的 weite up
1. 程序的执行
2. 查壳
有壳脱壳
3. 分析
将程序拖入OD的时候,右键智能搜索字符串,滑到最下面,然后找到关键的提示字符串,如下图:
双击进入跟踪,可以看到一根跳转的红线,有很多的跳转都来到了这里,如下图:
所以我们可以学一个新的技能就是右键地址处,加标签,加完标签后地址就会变红色字体如图:
所以我们就可以看到这些跳转都会显示<错误处>,而不是一个地址,便于分析,这是一个小技巧,如下图:
然后我们往上滑就可以看到函数的入口点,我们下断点然后运行到这里开始正式分析,如下图:
解释:上图划线分成了三部分。第一部分是堆栈平衡,第二部分主要是判断输入的是否为空,第三部分主要就是确用户数输入的只能是0-9的数字或者是字符“-”。
继续往下单步执行分析如下图:
解释:上图划线也分成了三部分。第一部分:判定输入字符串长度必须在0x9~0xB之间,然后后面的算法计算大概意思差不多,所以我们后面只用字符串长度为0x9时举例。第二部分:当字符串长度为0x9时,第三个字符和第七个字符必须为“-”,否则直接跳转到错误处。第三部分,后面很大一块就是将字符串中的的数字提取出来拼接成一串纯数字。
继续往下分析如下图:
解释:这就是加密算法的主要部分了,主要的流程就是把输入正确长度的字符串进行纯数字的提取,将这些纯数字字符串以十六进制保存在esi中,然后依次把这些纯数字取单个进行七次方的运算,每次得到的运算结果都要累加起来,最后储存在edi中。
最后的关键跳如下图,就是对比esi和edi中的结果,如果相同则正确:
4. 注册机的编写
//me 写的小白程序
#include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> void generatekey(); main() { generatekey(); system("pause"); return 0; } void generatekey() { char arr[10]={ '0','1','2','3','4','5','6','7','8','9' }; char key[10] = { 0 }; char serialkey[10] = { 0 }; int serial = 0; int edi = 0; int length = 10; int ar = 0; for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { for (int n = 0; n < length; n++) { for (int m = 0; m < length; m++) { for (int a = 0; a < length; a++) { for (int b = 0; b < length; b++) { for (int c = 0; c < length; c++) { key[0] = arr[i]; key[1] = arr[j]; key[2] = arr[n]; key[3] = arr[m]; key[4] = arr[a]; key[5] = arr[b]; key[6] = arr[c]; for (int d = 0; d < 7; d++) { char str = { 0 }; str = key[d] - '0'; //ar = pow(a, 7);//pow()是双精度的次方运算,在这里不可用 edi = edi + (str * str * str * str * str * str * str);//计算次方的函数 } serial = atoi(key);//将字符串转化为十进制数 if (serial == edi) { serialkey[0] = arr[i]; serialkey[1] = arr[j]; serialkey[2] = '-'; serialkey[3] = arr[n]; serialkey[4] = arr[m]; serialkey[5] = arr[a]; serialkey[6] = '-'; serialkey[7] = arr[b]; serialkey[8] = arr[c]; printf("serialkey: %s\n", serialkey); } } } } } } } } return 0; }
//极安御信写的
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <Windows.h> int main() { for (int i = 1000000; i < 9999999; i++) { int sum = 0; char tmp[8] = { 0 }; _itoa(i, tmp, 10); for (int j = 0; j < 7; j++) sum += pow(tmp[j] - '0', 7); if (i == sum)std::cout << i << std::endl; } }