
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:ToolsSecurity_Tools 10upx-3.95-win64upx-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
近期评论