新CrackMe160之141 - NTS Crackme5
OD载入程序, 搜索界面定位到成功关键词00401534,向上找到方法入口004014B0即为按钮事件入口,下好断点开始单步跟踪算法
004014F8处, 用这个正则表达式 %[^+]+%s 将注册码分成两段, 说明注册码中间有个+号
接下来0040150E和00401524两处结果为0都会跳到失败处, 所以这两个地方都是关键算法, 看IDA源码也一目了然:
int __thiscall sub_4014B0(CWnd *this)
{
CWnd *v1; // esi@1
int v2; // edi@1
int result; // eax@1
char v4; // [sp+8h] [bp-80h]@3
char v5; // [sp+1Ch] [bp-6Ch]@3
char v6; // [sp+30h] [bp-58h]@1
char Src; // [sp+54h] [bp-34h]@1
v1 = this;
v2 = CWnd::GetDlgItemTextA(this, 1000, &v6, 32);
result = CWnd::GetDlgItemTextA(v1, 1001, &Src, 40);
if ( v2 > 6 && result > 32 )
{
sscanf(&Src, aS, &v4, &v5);
result = sub_401320(&v6, &v4); //这里 0040150E
if ( result )
{
result = sub_4013E0(&v6, &v5); //这里 00401524
if ( result )
result = CWnd::MessageBoxA(v1, aSerialIsCorrec, 0, 0); //成功了
}
}
return result;
}
所以分别进这两个方法看看:
BOOL __cdecl sub_401320(int a1, const char *a2) //a1:用户名 a2:系列号前半段
{
unsigned int v2; // ecx@1
unsigned int v3; // edx@1
int v4; // edi@1
char i; // al@1
int v6; // ecx@2
int v7; // eax@2
int v8; // esi@2
char Dest; // [sp+Ch] [bp-14h]@3
v2 = 0;
v3 = 1;
v4 = a1;
for ( i = *(_BYTE *)a1; i; ++v4 )
{
v6 = (i ^ 0x32142001) + v2;
v7 = v6 | v3 * i;
v8 = v7;
v2 = (v7 % 7u + 2) * v6;
i = *(_BYTE *)(v4 + 1);
v3 = v8 * (v2 % 5 + 3);
}
sprintf(&Dest, Format, v2, v3); //%08X-%08X
return strcmp(&Dest, a2) == 0;
}
BOOL __cdecl sub_4013E0(int a1, const char *a2) //a1:用户名 a2:系列号后半段
{
unsigned int v2; // ecx@1
int v3; // ebx@1
char v4; // al@1
unsigned int v5; // esi@1
unsigned int i; // edi@1
int v7; // ecx@2
unsigned int v8; // esi@2
char Dest; // [sp+Ch] [bp-14h]@3
v2 = 1;
v3 = a1;
v4 = *(_BYTE *)a1;
v5 = 0;
for ( i = 0; v4; v5 = i + v8 * (i % 0xB + 2) )
{
v7 = v2 * v4;
v8 = v5 - (v4 | 0xF001F001);
i += v7 + v8;
v2 = i + (i % 7 + 3) * (v8 | v7);
v4 = *(_BYTE *)(v3++ + 1);
}
sprintf(&Dest, Format, v5, v2); //%08X-%08X
return strcmp(&Dest, a2) == 0;
}
由上面两个算法明显可得,由用户名计算得到两个串分别与系列号前后串对比, 代码很完整可直接引用
注册机如下:
#include <stdio.h>
void sub_401320(char *user);
void sub_4013E0(char *user);
int main() {
char user[51] = {0};
printf("用户名: ");
scanf("%s", user); getchar();
int len = sizeof(user);
if(len < 7){
printf("用户名7位以上");
getchar(); return 0;
}
printf("系列号: ");
sub_401320(user);
printf("+");
sub_4013E0(user);
getchar(); return 0;
}
void sub_401320(char *user)
{
unsigned int v2=0, v3=1;
int v4, v6, v7, v8;
char i;
v4 = *(int *)&user;
for ( i = *user; i; ++v4 )
{
v6 = (i ^ 0x32142001) + v2;
v7 = v6 | v3 * i;
v8 = v7;
v2 = (v7 % 7u + 2) * v6;
i = *(char *)(v4 + 1);
v3 = v8 * (v2 % 5 + 3);
}
printf("%08X-%08X", v2, v3);
}
void sub_4013E0(char *user)
{
unsigned int i, v2=1, v5=0, v8;
int v3, v7;
char v4;
v3 = *(int *)&user;
v4 = *user;
for ( i = 0; v4; v5 = i + v8 * (i % 0xB + 2) )
{
v7 = v2 * v4;
v8 = v5 - (v4 | 0xF001F001);
i += v7 + v8;
v2 = i + (i % 7 + 3) * (v8 | v7);
v4 = *(char *)(v3++ + 1);
}
printf("%08X-%08X", v5, v2);
}
运行示例:
用户名: Crackme5
系列号: 1600A8F8-DE196FF4+45990050-4AA47438
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载
下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~


浙公网安备 33010602011771号