警告
本文最后更新于 2023-04-08,文中内容可能已过时。
NewCrackMe | 018 CrackMe_0006
查壳
无壳,是MASM编译的,说明是直接用汇编写的程序
破解
直接到入口点观察汇编
这里调用了DialogBoxParamA
来调出DialogFunc
然后通过WM_COMMAND
选择不同的按钮模块,其中0x3F0
是About界面,0x3EE
是check界面
所以check界面就是验证的逻辑部分
这个程序的验证逻辑分为了三个部分
第一部分是计算盘符序列号
程序获取了C盘和D盘的序列号,中间加了一段花指令,最后对两个序列号进行浮点数运算,获得sum1
第二部分是计算输入的name
首先将name
每一位累乘起来,累乘是自己写的函数,定义如下
这个函数是将每位累乘之后,乘法的结果保存在EDX:EAX
中,将高位和地位相加得到最后的结果sum2
对sum2
进行循环左移一位的操作,然后和sum1
进行或运算得到sum3
第三部分是计算出series
程序硬编码了一个table,将sum3 % 16
作为数组索引得到series
,每次操作完对sum3 / 4
,直到sum3 == 0
最后一部分就是比较输入的序列号是否和series
相同
暴力破解
依旧是修改关键跳即可
生成注册码
下面的代码需要用MSVC编译
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
#include <Windows.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
// #define DEBUG
DWORD GetVolumeSerialNumber(const char* lpRootPathName) {
DWORD serialNumber = 0;
GetVolumeInformationA(lpRootPathName, NULL, 0, &serialNumber, NULL, NULL,
NULL, 0);
return serialNumber;
}
DWORD FloatCalculate(DWORD a1, DWORD a2) {
DWORD res = 0;
__asm {
fwait;
fninit;
fild dword ptr[a1];
fld st(0);
fmulp st(1), st(0);
fild dword ptr[a2];
fld st(0);
fmulp st(1), st(0);
faddp st(1), st(0);
fsqrt;
fistp dword ptr[res];
}
return res;
}
void LshiftRotate(DWORD* a1, DWORD a2) {
__asm {
mov eax, DWORD PTR[a1];
mov ecx, DWORD PTR[a2];
rol DWORD PTR[eax], cl;
}
}
int main() {
const char* const_buffer = "071362de9f8ab45c";
char buffer[32] = { 0 };
char name[32] = "bronya";
DWORD C_series, D_series;
DWORD sum1, sum2 = 1, sum3;
C_series = GetVolumeSerialNumber("C:\\");
D_series = GetVolumeSerialNumber("D:\\");
sum1 = FloatCalculate(C_series, D_series);
LONGLONG sum2_1 = 1;
for (int i = 0; name[i]; i++) {
sum2_1 *= name[i];
sum2 = sum2_1 & 0x00000000FFFFFFFF;
sum2 += (sum2_1 & 0xffffffff00000000) >> 32;
}
LshiftRotate(&sum2, 1);
sum3 = sum1 | sum2;
sum3 &= 0x0FFFFFFF;
int i = 0;
do {
buffer[i++] = const_buffer[sum3 % 0x10];
sum3 /= 4;
} while (sum3);
std::cout << buffer << std::endl;
return 0;
}
|
参考