Fork me on GitHub

160个CrackMe练习

前言

160个CrackMe题目量较大,而且有些CM逻辑重复度较高,因此挑选一些比较有价值的题目做一下以提高本🥦(菜)的逆向水平。

0x01 Acid burn

在x64dbg里查找字符串找到相关的错误提示,找到相关调用地址,在附近找到疑似关键跳转的部分下断:

在此处函数调用之后出现了序列号的关键部分:

序列号拼接之后得出name为1234,serial为CW-4018-CRACKED

跟踪一波算法:

总结一下就是:CW-itoa((用户的name的第一个字符的ascii码)*0x29*2)-CRACKED

第二部分直接检验serial的不必多说,找到判断函数,可以直接看到目标serial:

0x02 Afkayas_1

本来是写好了的但是这部分忘记保存导致丢失因此就简要写一下吧:

首先根据字符串找到判断位置:

单步运行可以找到对应abcd的serial:AKA-390221

下面分析一下算法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
004023F7   | 68 A0000000       | push A0                                      |
004023FC | 68 5C1B4000 | push afkayas.1.401B5C |
00402401 | 53 | push ebx |
00402402 | 50 | push eax |
00402403 | FF15 04414000 | call dword ptr ds:[<&__vbaHresultCheckObj>] |
00402409 | 8B95 50FFFFFF | mov edx,dword ptr ss:[ebp-B0] |
0040240F | 8B45 E4 | mov eax,dword ptr ss:[ebp-1C] | [ebp-1C]:L"abcd"
00402412 | 50 | push eax |
00402413 | 8B1A | mov ebx,dword ptr ds:[edx] |
00402415 | FF15 E4404000 | call dword ptr ds:[<&__vbaLenBstr>] |
0040241B | 8BF8 | mov edi,eax |
0040241D | 8B4D E8 | mov ecx,dword ptr ss:[ebp-18] | [ebp-18]:L"abcd"
00402420 | 69FF FB7C0100 | imul edi,edi,17CFB |
00402426 | 51 | push ecx |
00402427 | 0F80 91020000 | jo afkayas.1.4026BE |
0040242D | FF15 F8404000 | call dword ptr ds:[<&rtcRightVar>] |
00402433 | 0FBFD0 | movsx edx,ax |
00402436 | 03FA | add edi,edx |
00402438 | 0F80 80020000 | jo afkayas.1.4026BE |
0040243E | 57 | push edi |
0040243F | FF15 E0404000 | call dword ptr ds:[<&__vbaStrI4>] |

总结一下就是

1
serial = hex2dec(strlen(name)*0x17CFB + name[0])

0x03 Afkayas_2

单步走找到对应name:name的serial:1066990

接下来写注册机,先看算法:

第一步跟上一题一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
004081F2   | 50                | push eax                                     | eax:L"355662"
004081F3 | 8B1A | mov ebx,dword ptr ds:[edx] | edx:L"355662"
004081F5 | FF15 F8B04000 | call dword ptr ds:[<&__vbaLenBstr>] | 获取name字段长度
004081FB | 8BF8 | mov edi,eax | edi:L"-1-0", eax:L"355662"
004081FD | 8B4D E8 | mov ecx,dword ptr ss:[ebp-18] | [ebp-18]:L"name"
00408200 | 69FF 385B0100 | imul edi,edi,15B38 | strlen(name)*0x15b38=0x56ce0
00408206 | 51 | push ecx |
00408207 | 0F80 B7050000 | jo afkayas.2.4087C4 |
0040820D | FF15 0CB14000 | call dword ptr ds:[<&rtcRightVar>] |
00408213 | 0FBFD0 | movsx edx,ax | edx:L"355662"
00408216 | 03FA | add edi,edx | (strlen(name)*0x15b38)+name[0]=0x56d4e
00408218 | 0F80 A6050000 | jo afkayas.2.4087C4 |
0040821E | 57 | push edi | edi:L"-1-0"
0040821F | FF15 F4B04000 | call dword ptr ds:[<&__vbaStrI4>] | hex2dec 355662
00408225 | 8BD0 | mov edx,eax | edx:L"355662", eax:L"355662"
00408227 | 8D4D E0 | lea ecx,dword ptr ss:[ebp-20] |

第二部分:

1
2
3
4
5
6
7
0040832A   | DD1C24            | fstp qword ptr ss:[esp],st(0)                |
0040832D | FF15 48B14000 | call dword ptr ds:[<&__vbaStrR8>] | serial+=(10.0/5.0) = 355664
00408333 | 8BD0 | mov edx,eax | eax:L"355664"
00408335 | 8D4D E4 | lea ecx,dword ptr ss:[ebp-1C] |
00408338 | FF15 94B14000 | call dword ptr ds:[<&__vbaStrMove>] |
0040833E | 899D 34FFFFFF | mov dword ptr ss:[ebp-CC],ebx |
00408344 | 8B9D 58FFFFFF | mov ebx,dword ptr ss:[ebp-A8] |

第三部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
004083F2   | 52                 | push edx                                     |
004083F3 | 8B19 | mov ebx,dword ptr ds:[ecx] |
004083F5 | FF15 74B14000 | call dword ptr ds:[<&__vbaR8Str>] |
004083FB | DC0D 10104000 | fmul st(0),qword ptr ds:[401010] |
00408401 | 83EC 08 | sub esp,8 |
00408404 | DC25 18104000 | fsub st(0),qword ptr ds:[401018] |
0040840A | DFE0 | fnstsw ax |
0040840C | A8 0D | test al,D |
0040840E | 0F85 AB030000 | jne afkayas.2.4087BF |
00408414 | DD1C24 | fstp qword ptr ss:[esp],st(0) |
00408417 | FF15 48B14000 | call dword ptr ds:[<&__vbaStrR8>] |
0040841D | 8BD0 | mov edx,eax | eax:L"1066990"
0040841F | 8D4D E4 | lea ecx,dword ptr ss:[ebp-1C] |
00408422 | FF15 94B14000 | call dword ptr ds:[<&__vbaStrMove>] |
00408428 | 899D 2CFFFFFF | mov dword ptr ss:[ebp-D4],ebx |
0040842E | 8B9D 58FFFFFF | mov ebx,dword ptr ss:[ebp-A8] |
00408434 | 50 | push eax | eax:L"1066990"

总结算法:

1
serial = hex2dec((strlen(name)*0x15b38 + name[0]+2)*3-2-(-15))

0x04 ajj_1

OD可以搜索到中文字符串,但是x64dbg搜不到,可能是x64dbg对中文字符串的搜索支持不是太好吧:

向上找到关键跳转:

1
2
3
0045802F   | 75 AB              | jne ckme.457FDC                              |
00458031 | 81BE 0C030000 8500 | cmp dword ptr ds:[esi+30C],85 |
0045803B | 75 76 | jne ckme.4580B3 |

直接修改ZF寄存器强制不跳转:

0x05 ajj_2

发现加了UPX壳,先脱壳,脱壳后继续分析。

1
2
3
4
5
6
7
8
9
10
D:\Tools\Security_Tools\010\upx-3.95-win64\upx-3.95-win64>upx.exe -d CKme002.exe
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2018
UPX 3.95w Markus Oberhumer, Laszlo Molnar & John Reiser Aug 26th 2018

File size Ratio Format Name
-------------------- ------ ----------- -----------
458752 <- 146432 31.92% win32/pe CKme002.exe

Unpacked 1 file.

这道题好像看起来有点复杂,从看雪工具包中下载Delphi的反汇编工具:DeDe

分析文件看到如下事件:

分别查看这些事件的代码,在Timer2Timer中看到如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
004473E4   53                     push    ebx
004473E5 8BD8 mov ebx, eax
004473E7 81BB04030000340C0000 cmp dword ptr [ebx+$0304], $00000C34
004473F1 0F8488000000 jz 0044747F
004473F7 81BB080300000D230000 cmp dword ptr [ebx+$0308], $0000230D
00447401 747C jz 0044747F
00447403 81BB10030000940F0000 cmp dword ptr [ebx+$0310], $00000F94
0044740D 7570 jnz 0044747F
0044740F 8B8318030000 mov eax, [ebx+$0318]
00447415 3B8314030000 cmp eax, [ebx+$0314]
0044741B 7562 jnz 0044747F
0044741D 81BB1C030000E7030000 cmp dword ptr [ebx+$031C], $000003E7
00447427 7456 jz 0044747F
00447429 33D2 xor edx, edx

修改跳转逻辑之后可以看到注册成功的界面:

0x06 aLoNg3x_1

还是一个Delphi程序,DeDe看一下发现几个比较重要的事件,分别下断分析函数执行逻辑。

在ResoucesHacker中可以看到窗口控件的信息:

00442E22处看到一个cmp,修改跳转路径之后发现ok按钮可用了:

1
2
3
4
5
6
00442E22   | 8078 47 00         | cmp byte ptr ds:[eax+47],0                   |
00442E26 | 75 0F | jne along3x.1.442E37 |
00442E28 | B2 01 | mov dl,1 |
00442E2A | 8B83 CC020000 | mov eax,dword ptr ds:[ebx+2CC] |
00442E30 | 8B08 | mov ecx,dword ptr ds:[eax] |
00442E32 | FF51 60 | call dword ptr ds:[ecx+60] |

在Ok按钮的处理函数中爆破掉两个跳转指令之后按钮消失:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
00442D80   | 8078 47 01         | cmp byte ptr ds:[eax+47],1                   |
00442D84 | 75 12 | jne along3x.1.442D98 |
00442D86 | BA 002E4400 | mov edx,along3x.1.442E00 |
00442D8B | 8B83 E0020000 | mov eax,dword ptr ds:[ebx+2E0] |
00442D91 | E8 5A05FEFF | call along3x.1.4232F0 |
00442D96 | EB 3F | jmp along3x.1.442DD7 |
00442D98 | 8D55 FC | lea edx,dword ptr ss:[ebp-4] |
00442D9B | 8B83 E0020000 | mov eax,dword ptr ds:[ebx+2E0] |
00442DA1 | E8 1A05FEFF | call along3x.1.4232C0 |
00442DA6 | 8B45 FC | mov eax,dword ptr ss:[ebp-4] |
00442DA9 | E8 C248FCFF | call along3x.1.407670 |
00442DAE | 50 | push eax |
00442DAF | 8D55 FC | lea edx,dword ptr ss:[ebp-4] |
00442DB2 | 8B83 DC020000 | mov eax,dword ptr ds:[ebx+2DC] |
00442DB8 | E8 0305FEFF | call along3x.1.4232C0 |
00442DBD | 8B45 FC | mov eax,dword ptr ss:[ebp-4] |
00442DC0 | 5A | pop edx |
00442DC1 | E8 DAFDFFFF | call along3x.1.442BA0 |
00442DC6 | 84C0 | test al,al |
00442DC8 | 74 0D | je along3x.1.442DD7 |
00442DCA | 33D2 | xor edx,edx |
00442DCC | 8B83 CC020000 | mov eax,dword ptr ds:[ebx+2CC] |
00442DD2 | E8 D903FEFF | call along3x.1.4231B0 |

同样在Cancella按钮的处理函数中也有如下逻辑:

1
2
3
00442EE7   | E8 08FCFFFF        | call along3x.1.442AF4                        |
00442EEC | 84C0 | test al,al |
00442EEE | 74 1C | je along3x.1.442F0C |

爆破之后发现两个按钮都消失了,达到了题目效果:

还是要看一下判断逻辑,找到Cancella按钮处理函数中关键的跳转前的判断函数:

1
2
3
4
5
6
7
8
9
10
00442ECF   | E8 9C47FCFF        | call along3x.1.407670                        | 获取密码
00442ED4 | 50 | push eax | eax:"1234567890"
00442ED5 | 8D55 FC | lea edx,dword ptr ss:[ebp-4] | [ebp-4]:"1234567890"
00442ED8 | 8B83 DC020000 | mov eax,dword ptr ds:[ebx+2DC] | eax:"1234567890"
00442EDE | E8 DD03FEFF | call along3x.1.4232C0 | 获取用户名
00442EE3 | 8B45 FC | mov eax,dword ptr ss:[ebp-4] | [ebp-4]:"1234567890"
00442EE6 | 5A | pop edx |
00442EE7 | E8 08FCFFFF | call along3x.1.442AF4 |
00442EEC | 84C0 | test al,al |
00442EEE | 74 1C | je along3x.1.442F0C |

单步步进看一下,找到如下运算过程:

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
00442AF4   | 55                 | push ebp                                     |
00442AF5 | 8BEC | mov ebp,esp |
00442AF7 | 83C4 F8 | add esp,FFFFFFF8 |
00442AFA | 53 | push ebx | ebx:",(D"
00442AFB | 56 | push esi |
00442AFC | 8955 F8 | mov dword ptr ss:[ebp-8],edx |
00442AFF | 8945 FC | mov dword ptr ss:[ebp-4],eax | [ebp-4]:"ZZZZZZZZZZ"
00442B02 | 8B45 FC | mov eax,dword ptr ss:[ebp-4] | [ebp-4]:"ZZZZZZZZZZ"
00442B05 | E8 DE10FCFF | call along3x.1.403BE8 | 判断字符串是否为空
00442B0A | 33C0 | xor eax,eax | eax:"ZZZZZZZZZZ"
00442B0C | 55 | push ebp |
00442B0D | 68 902B4400 | push along3x.1.442B90 |
00442B12 | 64:FF30 | push dword ptr fs:[eax] |
00442B15 | 64:8920 | mov dword ptr fs:[eax],esp |
00442B18 | 8B45 FC | mov eax,dword ptr ss:[ebp-4] | [ebp-4]:"ZZZZZZZZZZ"
00442B1B | E8 140FFCFF | call along3x.1.403A34 | 获取name字段长度
00442B20 | 83F8 05 | cmp eax,5 | 用户名长度是否大于5
00442B23 | 7E 53 | jle along3x.1.442B78 |
00442B25 | 8B45 FC | mov eax,dword ptr ss:[ebp-4] | [ebp-4]:"ZZZZZZZZZZ"
00442B28 | 0FB640 04 | movzx eax,byte ptr ds:[eax+4] | 取用户名第5位字母的ASCII
00442B2C | B9 07000000 | mov ecx,7 |
00442B31 | 33D2 | xor edx,edx |
00442B33 | F7F1 | div ecx |
00442B35 | 8BC2 | mov eax,edx | 用户名第5位字母的ASCII值/7
00442B37 | 83C0 02 | add eax,2 | 取余+2
00442B3A | E8 E1FEFFFF | call along3x.1.442A20 | 余数+2的阶乘
00442B3F | 8BF0 | mov esi,eax | eax:"ZZZZZZZZZZ"
00442B41 | 33DB | xor ebx,ebx | ebx:",(D"
00442B43 | 8B45 FC | mov eax,dword ptr ss:[ebp-4] | [ebp-4]:"ZZZZZZZZZZ"
00442B46 | E8 E90EFCFF | call along3x.1.403A34 | 判断用户名是否为空
00442B4B | 85C0 | test eax,eax | eax:"ZZZZZZZZZZ"
00442B4D | 7E 16 | jle along3x.1.442B65 |
00442B4F | BA 01000000 | mov edx,1 |
00442B54 | 8B4D FC | mov ecx,dword ptr ss:[ebp-4] | [ebp-4]:"ZZZZZZZZZZ"
00442B57 | 0FB64C11 FF | movzx ecx,byte ptr ds:[ecx+edx-1] | 对用户名循环取值
00442B5C | 0FAFCE | imul ecx,esi | name[i]*(余数+2的阶乘)
00442B5F | 03D9 | add ebx,ecx | 对上一步运算求和
00442B61 | 42 | inc edx |
00442B62 | 48 | dec eax | eax:"ZZZZZZZZZZ"
00442B63 | 75 EF | jne along3x.1.442B54 |
00442B65 | 2B5D F8 | sub ebx,dword ptr ss:[ebp-8] | 求和的结果-注册码 |
00442B68 | 81FB 697A0000 | cmp ebx,7A69 | 判断差是否等于0x7A69
00442B6E | 75 04 | jne along3x.1.442B74 |
00442B70 | B3 01 | mov bl,1 |
00442B72 | EB 06 | jmp along3x.1.442B7A |
00442B74 | 33DB | xor ebx,ebx | ebx:",(D"
00442B76 | EB 02 | jmp along3x.1.442B7A |
00442B78 | 33DB | xor ebx,ebx | ebx:",(D"
00442B7A | 33C0 | xor eax,eax | eax:"ZZZZZZZZZZ"
00442B7C | 5A | pop edx |
00442B7D | 59 | pop ecx |
00442B7E | 59 | pop ecx |
00442B7F | 64:8910 | mov dword ptr fs:[eax],edx |
00442B82 | 68 972B4400 | push along3x.1.442B97 |
00442B87 | 8D45 FC | lea eax,dword ptr ss:[ebp-4] | [ebp-4]:"ZZZZZZZZZZ"
00442B8A | E8 290CFCFF | call along3x.1.4037B8 |
00442B8F | C3 | ret |

可以分析出算法:用户名第5个字母的ASCII码处以7的余数加2为X,算出X的阶乘Y,Y乘用户名ASCII值的和得Z,Z-serial=0x7A69时验证通过。

公式:

1
serial = ((((name[4]%7) + 2)!)*(name[0] + name[1] + ... + name[i])) - 0x7A69

按照这个逻辑得出ZZZZZZZZZZ对应的注册码是36256663,输入之后发现Cancella按钮消失且Ok按钮状态改变:

但是此时点Ok按钮还是没有任何反应,因此猜测Ok按钮处也有验证算法,话不多说下断:

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
00442D64   | 55                 | push ebp                                     | OK_Click
00442D65 | 8BEC | mov ebp,esp |
00442D67 | 6A 00 | push 0 |
00442D69 | 53 | push ebx |
00442D6A | 8BD8 | mov ebx,eax | eax:",(D"
00442D6C | 33C0 | xor eax,eax | eax:",(D"
00442D6E | 55 | push ebp |
00442D6F | 68 ED2D4400 | push along3x.1.442DED |
00442D74 | 64:FF30 | push dword ptr fs:[eax] |
00442D77 | 64:8920 | mov dword ptr fs:[eax],esp |
00442D7A | 8B83 D0020000 | mov eax,dword ptr ds:[ebx+2D0] | eax:",(D"
00442D80 | 8078 47 01 | cmp byte ptr ds:[eax+47],1 |
00442D84 | 75 12 | jne along3x.1.442D98 |
00442D86 | BA 002E4400 | mov edx,along3x.1.442E00 |
00442D8B | 8B83 E0020000 | mov eax,dword ptr ds:[ebx+2E0] | eax:",(D"
00442D91 | E8 5A05FEFF | call along3x.1.4232F0 |
00442D96 | EB 3F | jmp along3x.1.442DD7 |
00442D98 | 8D55 FC | lea edx,dword ptr ss:[ebp-4] |
00442D9B | 8B83 E0020000 | mov eax,dword ptr ds:[ebx+2E0] | eax:",(D"
00442DA1 | E8 1A05FEFF | call along3x.1.4232C0 |
00442DA6 | 8B45 FC | mov eax,dword ptr ss:[ebp-4] |
00442DA9 | E8 C248FCFF | call along3x.1.407670 |
00442DAE | 50 | push eax | eax:",(D"
00442DAF | 8D55 FC | lea edx,dword ptr ss:[ebp-4] |
00442DB2 | 8B83 DC020000 | mov eax,dword ptr ds:[ebx+2DC] | eax:",(D"
00442DB8 | E8 0305FEFF | call along3x.1.4232C0 |
00442DBD | 8B45 FC | mov eax,dword ptr ss:[ebp-4] |
00442DC0 | 5A | pop edx |
00442DC1 | E8 DAFDFFFF | call along3x.1.442BA0 | 隐藏Ok按钮的判断函数
00442DC6 | 84C0 | test al,al |
00442DC8 | 74 0D | je along3x.1.442DD7 | Ok按钮隐藏
00442DCA | 33D2 | xor edx,edx |
00442DCC | 8B83 CC020000 | mov eax,dword ptr ds:[ebx+2CC] | eax:",(D"
00442DD2 | E8 D903FEFF | call along3x.1.4231B0 |
00442DD7 | 33C0 | xor eax,eax | eax:",(D"
00442DD9 | 5A | pop edx |
00442DDA | 59 | pop ecx |
00442DDB | 59 | pop ecx |
00442DDC | 64:8910 | mov dword ptr fs:[eax],edx |
00442DDF | 68 F42D4400 | push along3x.1.442DF4 |
00442DE4 | 8D45 FC | lea eax,dword ptr ss:[ebp-4] |
00442DE7 | E8 CC09FCFF | call along3x.1.4037B8 |
00442DEC | C3 | ret |
00442DED | E9 8604FCFF | jmp along3x.1.403278 |
00442DF2 | EB F0 | jmp along3x.1.442DE4 |
00442DF4 | 5B | pop ebx |
00442DF5 | 59 | pop ecx |
00442DF6 | 5D | pop ebp |
00442DF7 | C3 | ret |

找到442BA0,进去看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
00442BF9   | 8D45 F4            | lea eax,dword ptr ss:[ebp-C]                 | [ebp-C]:"362566MI"
00442BFC | E8 0310FCFF | call along3x.1.403C04 |
00442C01 | 8D4430 FF | lea eax,dword ptr ds:[eax+esi-1] |
00442C05 | 50 | push eax |
00442C06 | 8B45 F8 | mov eax,dword ptr ss:[ebp-8] | [ebp-8]:"36256663"
00442C09 | 0FB64430 FF | movzx eax,byte ptr ds:[eax+esi-1] |
00442C0E | F7E8 | imul eax | 每个数字平方
00442C10 | 0FBFC0 | movsx eax,ax |
00442C13 | F7EE | imul esi | *剩余注册码的长度
00442C15 | B9 19000000 | mov ecx,19 |
00442C1A | 99 | cdq |
00442C1B | F7F9 | idiv ecx | /19
00442C1D | 83C2 41 | add edx,41 | 余数+41
00442C20 | 58 | pop eax |
00442C21 | 8810 | mov byte ptr ds:[eax],dl |
00442C23 | 4E | dec esi |
00442C24 | 85F6 | test esi,esi |
00442C26 | 75 D1 | jne along3x.1.442BF9 |

首先注册码长度要大于5,倒序对注册码中每个数字进行处理,第i个数字的平方乘以未处理注册码字符的长度再与19取余,结果加41后得出用户名的第i个字母。

当注册码为36256663时运算得出的用户名为BHALFVMI,输入程序发现Ok按钮也消失了:

0x07 aLoNg3x_2

您的支持是我最大的动力🍉