新CrackMe160之057 - keygen-crackme4
-
脱壳
OD手动脱壳, F8运行一次,ESP变红,右键HW break [ESP]下好硬件断点, F9运行,看到了下面的jmp, 以为要成功了, 结果又跳到了乱码处, 说明还需要继续解密, 重来,F9运行到jmp前面时, 再F9两次来到00401871处, 观察下面的代码, 虽然不乱了, 但还是一堆的push, pop, 说明还是不对, F8单步跟踪, 直到00401930 call 00401690, 运行这一行,程序界面就出来了,说明到这里就完成脱壳了, 继续重来, 运行到00401930这一行后不继续F8了,改为F7进入方法,这里就是程序入口处了(00401690), 接着便右键 ollydump 方式1脱壳成功~ -
破解
运行脱壳后程序, 按验证按钮有错误提示信息, 搜索界面可定位到004015FA,向上找到入口0040158A, 下好断点, 输入伪码, 开始分析算法(004011B0处)
算法比较简单, 注册机如下:
#include <stdio.h>
#include <string.h>
int main() {
unsigned int sid, edx, esi = 0x12345678;
char user[51] = {0};
char code[51] = {0};
printf("系统ID: ");
fgets(code, sizeof(code), stdin);
code[strlen(code)-1] = 0;
char *endstr;
sid = strtol(code, &endstr, 16);
if(*endstr != 0) {
printf("系统ID输入错误!");
return 0;
}
printf("用户名: ");
fgets(user, sizeof(user), stdin);
int i, rnd, len = strlen(user) - 1;
for(i=0; i<len; i++){
edx = esi;
esi *= 2;
edx = edx >> 7;
edx |= esi;
esi = user[i] ^ edx;
}
esi ^= sid;
printf("系列号: %X\r\n", esi);
getchar();
return 0;
}
运行示例:
系统ID: 12345DC0 (这个每个人电脑不一样)
用户名: crackme4
系列号: 2442228B
可用计算器直接将这个示例系列号转为你自己的系列号 => 2442228B ^ 12345DC0 ^ 你的系统ID
[( 后记 )]
系统ID是004014C9处设置的, (通过命令行下断点可跟踪: bp SetDlgItemTextA), 值的产生在004014A6这行的方法中, 跟踪进去有一个小阻碍, 作者设置了防调试栏路虎, 这个也简单, F8运行到00401012处,不要再继续向下运行了, 这时只要在00401037处右键设为新EIP即可跳过验证,
00401057~00401065是密文,运行完00401057这行即可解密, 向下就可以很容易看到, 系统ID的值就等于0x12345678 ^ cpuid, cpuid这行参数的入参
eax当前值为0x00401057, 到此, 分析完毕, 上面的注册机也可以简化一点了,不需要再手动输入系统ID号了:
#include <stdio.h>
#include <string.h>
//32bit
void cpuid(int code, int data[4])
{
asm volatile("cpuid"
: "=a" (data[0]),
"=b" (data[1]),
"=c" (data[2]),
"=d" (data[3])
: "0" (code));
}
/*//64bit
void cpuid(int code, int data[4]) {
__cpuid(data, code);
}
*/
int main() {
unsigned int sid, edx, esi = 0x12345678;
char user[51] = {0};
char code[51] = {0};
int data[4];
cpuid(0x00401057, data);
sid = esi ^ data[0]; //cpuid
printf("系统ID: %X\n", sid);
printf("用户名: ");
fgets(user, sizeof(user), stdin);
int i, rnd, len = strlen(user) - 1;
for(i=0; i<len; i++){
edx = esi;
esi *= 2;
edx = edx >> 7;
edx |= esi;
esi = user[i] ^ edx;
}
esi ^= sid;
printf("系列号: %X\r\n", esi);
getchar();
return 0;
}
运行示例:
系统ID: 12345DC0
用户名: crackme4
系列号: 2442228B
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载
下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~