160CrackMe-007

本文最后更新于:2021-08-09 晚上

初探

打开程序还是和上一个有很熟悉的画面,不愧是同一个作者做的。

about按钮了解情况,还是需要让按钮消失然后露出logo就算成功了。

分析

无壳,是使用delphi编写的。

还是直接使用DeDark查看,然后去下断

断下来之后进行分析,可以看到一个较为关键的跳转,在此之前的函数比较重要,进去查看一下。

进来之后果然看到了算法

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
004429EE  |.  8945 F4       mov dword ptr ss:[ebp-0xC],eax
004429F1 |. BE 01000000 mov esi,0x1
004429F6 |> 8B45 F8 /mov eax,dword ptr ss:[ebp-0x8]
004429F9 |. E8 3610FCFF |call aLoNg3x_.00403A34
004429FE |. 83F8 01 |cmp eax,0x1
00442A01 |. 7C 1D |jl short aLoNg3x_.00442A20
00442A03 |> 8B55 F8 |/mov edx,dword ptr ss:[ebp-0x8]
00442A06 |. 0FB65432 FF ||movzx edx,byte ptr ds:[edx+esi-0x1]
00442A0B |. 8B4D F8 ||mov ecx,dword ptr ss:[ebp-0x8]
00442A0E |. 0FB64C01 FF ||movzx ecx,byte ptr ds:[ecx+eax-0x1]
00442A13 |. 0FAFD1 ||imul edx,ecx
00442A16 |. 0FAFD7 ||imul edx,edi
00442A19 |. 03DA ||add ebx,edx
00442A1B |. 48 ||dec eax
00442A1C |. 85C0 ||test eax,eax
00442A1E |.^ 75 E3 |\jnz short aLoNg3x_.00442A03
00442A20 |> 46 |inc esi
00442A21 |. FF4D F4 |dec dword ptr ss:[ebp-0xC]
00442A24 |.^ 75 D0 \jnz short aLoNg3x_.004429F6
00442A26 |> 8BC3 mov eax,ebx
00442A28 |. 99 cdq
00442A29 |. 33C2 xor eax,edx
00442A2B |. 2BC2 sub eax,edx
00442A2D |. B9 2A2C0A00 mov ecx,0xA2C2A
00442A32 |. 99 cdq
00442A33 |. F7F9 idiv ecx
00442A35 |. 8BDA mov ebx,edx
00442A37 |. 8B45 FC mov eax,dword ptr ss:[ebp-0x4]
00442A3A |. B9 59000000 mov ecx,0x59
00442A3F |. 99 cdq
00442A40 |. F7F9 idiv ecx
00442A42 |. 8BC8 mov ecx,eax
00442A44 |. 8B45 FC mov eax,dword ptr ss:[ebp-0x4]
00442A47 |. BE 50000000 mov esi,0x50
00442A4C |. 99 cdq
00442A4D |. F7FE idiv esi
00442A4F |. 03CA add ecx,edx
00442A51 |. 41 inc ecx
00442A52 |. 894D FC mov dword ptr ss:[ebp-0x4],ecx
00442A55 |. 3B5D FC cmp ebx,dword ptr ss:[ebp-0x4]

但是问题是,其中edi的值一直为0,这导致一直在计算的值都是0,然后再进行比较,是不可以的,必须要找到edi在何处被赋值。

往上慢慢寻找一下,可以看到此处edi的值是通过eax赋值的,那么又要寻找eax的值,函数内部没有,需要出去函数寻找。

出函数之后,看到eax的值是通过一个地址传递的

继续找寻此地址的值是从何处得来,下硬件断点,没有断下来,说明不满足条件,不过在上面不远处就可以看到这个地址的赋值。看到如果想要进入此处需要让上面的JZ跳转不跳走,进入前面的函数看看

进去发现是一个判断你输入的codice中是否含有非数字的一个判断,但是其中又有一点限制,就是第一位如果输入-,+,$,X,x,剩下都是数字的话,也是可以的,反正就是,输入非纯数字的codice以便可以进入后面,如果输入第一位为以上几个的话,那么其中还需要至少再含有一个非数字就可以。

继续分析,再赋值前一条语句的函数就是关键的生成函数,进入分析,发现算法。

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
00442ACD  |.  B9 01000000   mov ecx,0x1
00442AD2 |> 8B45 FC /mov eax,dword ptr ss:[ebp-0x4]
00442AD5 |. 0FB60408 |movzx eax,byte ptr ds:[eax+ecx]
00442AD9 |. BF 11000000 |mov edi,0x11
00442ADE |. 33D2 |xor edx,edx
00442AE0 |. F7F7 |div edi
00442AE2 |. 42 |inc edx
00442AE3 |. 8B45 FC |mov eax,dword ptr ss:[ebp-0x4]
00442AE6 |. 0FB64408 FF |movzx eax,byte ptr ds:[eax+ecx-0x1]
00442AEB |. 0FAFD0 |imul edx,eax
00442AEE |. 03F2 |add esi,edx
00442AF0 |. 41 |inc ecx ; user32.75B16D51
00442AF1 |. 4B |dec ebx
00442AF2 |.^ 75 DE \jnz short aLoNg3x_.00442AD2
00442AF4 |. EB 02 jmp short aLoNg3x_.00442AF8
00442AF6 |> 33F6 xor esi,esi
00442AF8 |> 8BC6 mov eax,esi
00442AFA |. B9 48710000 mov ecx,0x7148
00442AFF |. 99 cdq
00442B00 |. F7F9 idiv ecx ; user32.75B16D51
00442B02 |. 8BC2 mov eax,edx
00442B04 |. 99 cdq
00442B05 |. 33C2 xor eax,edx ; XOR0
00442B07 |. 2BC2 sub eax,edx ; -0
00442B09 |. 8BD8 mov ebx,eax
00442B0B |. 33C0 xor eax,eax

这里会生成一个标志值,用于后面的计算

1
2
3
4
5
6
7
8
9
int len = strlen(szCodice);
int remainder;
int sum = 0x37B;
for (int i = 1; i < len ; i++) {
remainder = szCodice[i] % 0x11 + 1;
sum += remainder * szCodice[i - 1];
}
sum = sum % 0x7148;
return sum;

生成标志值之后就可以继续刚才的算法计算了,

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
int len = strlen(szName);
int sum = 0;
for (int i = 0; i <= len; i++) {
for (int j = 0; j <= len; j++) {
sum += (szName[i] * szName[len - j]) * FlagNumber;
}
}
__asm {
mov eax,sum
cdq
xor eax,edx
sub eax,edx
mov ecx,0xA2C2A
cdq
idiv ecx
mov ebx,edx
mov sum,ebx
}
int serial;
for (int i = 1; i < 0xFFFFFFFF; i++) {
if (((i / 0x59) + (i % 0x50) + 1) == sum) {
printf("codice:%d\n", i);
break;
}
}

到这里算出了一个可以用的codice

输入后发现又出现了一个again按钮。

从dedark中找到againClick事件,经过分析发现其实是和OK按钮一模一样的流程,也就是把刚才输入的在输入一次就好了

注册机

完整注册机如下:

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
#include <stdio.h>
#include <string.h>
#include <Windows.h>
//字母
int getFlagNumber(char* szCodice) {
int len = strlen(szCodice);
int remainder;
int sum = 0x37B;
for (int i = 1; i < len ; i++) {
remainder = szCodice[i] % 0x11 + 1;
sum += remainder * szCodice[i - 1];
}
sum = sum % 0x7148;
return sum;
}


void OkClick(char* szName,int FlagNumber) {
int len = strlen(szName);
int sum = 0;
for (int i = 0; i <= len; i++) {
for (int j = 0; j <= len; j++) {
sum += (szName[i] * szName[len - j]) * FlagNumber;
}
}
__asm {
mov eax,sum
cdq
xor eax,edx
sub eax,edx
mov ecx,0xA2C2A
cdq
idiv ecx
mov ebx,edx
mov sum,ebx
}
int serial;
for (int i = 1; i < 0xFFFFFFFF; i++) {
if (((i / 0x59) + (i % 0x50) + 1) == sum) {
printf("codice:%d\n", i);
break;
}
}
}

int main() {
printf("请先输入第一位是字母的Codice以便生成标志值\n");
char Codice[20];
gets_s(Codice, 20);
int FlagNumber = getFlagNumber(Codice);

printf("输入用户名\n");
char name[20];
gets_s(name, 20);
OkClick(name, FlagNumber);
return 0;
}

总结

这个程序就是需要先输入非纯数字codice生成一个标志值计算,然后再输入codice就可以了,连续两次即可。注册机那段内联汇编,实在不知道怎么用C写了…


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!