结合前辈们的分析,自己再作一个分析,算是当做学习笔记吧!
OD 下GetDlgItemTextA 这个断点
0040148C |. 83F8 1E cmp eax,0x1E 检测注册码长度是否为30位
0040148F |. 75 25 jnz short CrackMe.004014B6
00401491 |. 8BD0 mov edx,eax
00401493 |. 8D8D FCFDFFFF lea ecx,[local.129]
00401499 |. E8 62FBFFFF call CrackMe.00401000 关键算法
0040149E |. 83F8 01 cmp eax,0x1
004014A1 |. 75 13 jnz short CrackMe.004014B6
进入call CrackMe.00401000
引用别人的话:
此CrackMe加了开源的 WProtect, 因此有部分是虚拟机。但是虚拟机部分也不是特别重要。因为一般vm是以函数为单位的,当调用子函数时,会退出当前虚拟机(ps:函数要返回时也需要退出虚拟机),还原环境,然后调用。正好此程序只是把外层函数给vm了(只有一个地方是在虚拟机里进行的,后面会讲到)。只需在vm出口等待返回即可。不需要去查看整个虚拟机流程。
进入call 401000是发现被VM了,我们直接找到vm_Exit 这个handler
0042F052 8BFC mov edi,esp
0042F054 BE 0E544300 mov esi,CrackMe.0043540E 字节码表
0042F059 E9 7B0C0000 jmp CrackMe.0042FCD9
0042FCD9 F7D3 not ebx
0042FCDB 4B dec ebx
0042FCDC 66:F7D3 not bx
0042FCDF 66:81EB D165 sub bx,0x65D1
0042FCE4 0FB646 FF movzx eax,byte ptr ds:[esi-0x1] 读取字节码
0042FCE8 4E dec esi
0042FCE9 2AC3 sub al,bl
0042FCEB F6D0 not al
0042FCED 04 57 add al,0x57
0042FCEF FEC8 dec al
0042FCF1 2C 3E sub al,0x3E
0042FCF3 FF3485 DDF84200 push dword ptr ds:[eax*4+0x42F8DD] 派发表
0042FCFA C3 retn
从esi处找到最后一个字节码下断点(向上拖动查找)
0042F76F 8BE5 mov esp,ebp
0042F771 5F pop edi
0042F772 5E pop esi
0042F773 5D pop ebp
0042F774 5B pop ebx
0042F775 5A pop edx
0042F776 59 pop ecx
0042F777 58 pop eax
0042F778 9D popfd
0042F779 C3 retn
VM退出handler
以后直接在VM退出handl下断点跟踪就可以了。
004014F0 /$ 55 push ebp md5_update
004014F1 |. 8BEC mov ebp,esp
004014F3 |. 83EC 0C sub esp,0xC
004014F6 |. 53 push ebx
004014F7 |. 8B5D 08 mov ebx,[arg.1]
004014FA |. 56 push esi
004014FB |. 57 push edi
004014FC |. 8BF9 mov edi,ecx
004014FE |. 8955 FC mov [local.1],edx
00401501 |. 897D F8 mov [local.2],edi
00401504 |. 8B47 10 mov eax,dword ptr ds:[edi+0x10]
00401507 |. 8BC8 mov ecx,eax
00401509 |. C1E9 03 shr ecx,0x3
0040150C |. 83E1 3F and ecx,0x3F
0040150F |. 894D F4 mov [local.3],ecx
00401512 |. 8D14D8 lea edx,dword ptr ds:[eax+ebx*8]
00401515 |. 8D04DD 000000>lea eax,dword ptr ds:[ebx*8]
将注册码前七位进行md5处理
00401183 8A440D D0 mov al,byte ptr ss:[ebp+ecx-0x30]
00401187 32840D 14FCFFFF xor al,byte ptr ss:[ebp+ecx-0x3EC]
0040118E 88840D E8FBFFFF mov byte ptr ss:[ebp+ecx-0x418],al
00401195 83F9 17 cmp ecx,0x17
00401198 0F83 68020000 jnb CrackMe.00401406
0040119E C6440D D0 00 mov byte ptr ss:[ebp+ecx-0x30],0x0
004011A3 C6840D 14FCFFFF>mov byte ptr ss:[ebp+ecx-0x3EC],0x0
004011AB 41 inc ecx
004011AC 83F9 17 cmp ecx,0x17
004011AF ^ 7C D2 jl short CrackMe.00401183
异或加密剩余的23个假码
和 密钥 44 AD 5C CC 12 90 73 8D 47 81 E3 89 84 9C DF F9 47 6A B6 9E 11 30 27
进行异或
得出:
7C 94 1D 8E 51 D4 36 CB 00 C9 AA C3 CF D0 92 B7 08 3A E7 CC 42 64 72
004011C0 8A840D 90FDFFFF mov al,byte ptr ss:[ebp+ecx-0x270]
004011C7 32840D E8FBFFFF xor al,byte ptr ss:[ebp+ecx-0x418]
004011CE 88440D D0 mov byte ptr ss:[ebp+ecx-0x30],al
004011D2 83F9 17 cmp ecx,0x17
004011D5 0F83 2B020000 jnb CrackMe.00401406
004011DB C6840D E8FBFFFF>mov byte ptr ss:[ebp+ecx-0x418],0x0
004011E3 C6840D 90FDFFFF>mov byte ptr ss:[ebp+ecx-0x270],0x0
004011EB 41 inc ecx
004011EC 83F9 17 cmp ecx,0x17
004011EF ^ 7C CF jl short CrackMe.004011C0
继续进行异或
然后再和前7位的md5值进行异或
得出:
80 7E 8F 81 25 C6 83 11 7B 29 65 81 77 19 A5 EE F4 D0 75 C3 36 76 C7
引用:
将异或后的结果当作路线开始寻路。
00401240 8BD1 mov edx,ecx //每次取一个字节
00401242 8985 10FCFFFF mov dword ptr ss:[ebp-0x3F0],eax
00401248 8A8D 0CFCFFFF mov cl,byte ptr ss:[ebp-0x3F4]
0040124E D3EA shr edx,cl //依次取两位
00401250 83E2 03 and edx,0x3 //最大为3,也就是0,1,2,3
00401253 FF2495 0C144000 jmp dword ptr ds:[edx*4+0x40140C]
Case 0:
0040125A 83E8 10 sub eax,0x10
0040125D EB 09 jmp short CrackMe。00401268
case 1:
0040125F 40 inc eax
00401260 EB 06 jmp short CrackMe。00401268
case 2:
00401262 83C0 10 add eax,0x10
00401265 EB 01 jmp short CrackMe。00401268
case 3:
00401267 48 dec eax
为0即-0x10也即返回一行;
为1则+1,也即前进一列;
为2则+0x10,也即前进一行;
为3则-1,也即返回一列
引用:
判断下一步要走的地方
004012B5 8B8D 08FCFFFF mov ecx,dword ptr ss:[ebp-0x3F8]
004012BB 8D95 90FEFFFF lea edx,dword ptr ss:[ebp-0x170]
004012C1 8B85 04FCFFFF mov eax,dword ptr ss:[ebp-0x3FC]
004012C7 C1E1 04 shl ecx,0x4
004012CA 03C1 add eax,ecx
004012CC 03D0 add edx,eax
004012CE 8995 04FCFFFF mov dword ptr ss:[ebp-0x3FC],edx
004012D4 8A8C05 90FCFFFF mov cl,byte ptr ss:[ebp+eax-0x370]
004012DB 8AC1 mov al,cl
004012DD 888D 37FCFFFF mov byte ptr ss:[ebp-0x3C9],cl
004012E3 C0C8 02 ror al,0x2
004012E6 0FB6C8 movzx ecx,al
004012E9 0FB602 movzx eax,byte ptr ds:[edx]
004012EC 33C8 xor ecx,eax
004012EE 83F9 30 cmp ecx,0x30 //是否为墙,如果是则失败
004012F1 0F84 E2000000 je CrackMe。004013D9
004012F7 83F9 20 cmp ecx,0x20 //暂时未看到过
004012FA 0F84 D9000000 je CrackMe。004013D9
00401300 83F9 58 cmp ecx,0x58 //0x58可以确定为是否到终点了。
00401303 0F84 E5000000 je CrackMe。004013EE
00401309 8B8D 10FCFFFF mov ecx,dword ptr ss:[ebp-0x3F0]
0040130F 8BC1 mov eax,ecx
00401311 99 cdq
00401312 83E2 0F and edx,0xF
00401315 03C2 add eax,edx
00401317 C1F8 04 sar eax,0x4
0040131A 8985 08FCFFFF mov dword ptr ss:[ebp-0x3F8],eax
00401320 81E1 0F000080 and ecx,0x8000000F
00401326 79 05 jns short CrackMe。0040132D
00401328 49 dec ecx
00401329 83C9 F0 or ecx,0xFFFFFFF0
0040132C 41 inc ecx
0040132D 898D 10FCFFFF mov dword ptr ss:[ebp-0x3F0],ecx
这里就是检测操作是否撞墙即是否等于0x30和0x20 如果等于0x58就是通关成功
004011F1 B9 40000000 mov ecx,0x40
004011F6 8DBD 90FCFFFF lea edi,dword ptr ss:[ebp-0x370]
004011FC BE 98374100 mov esi,CrackMe.00413798
00401201 33C0 xor eax,eax
00401203 F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi]
将esi的加密表复制到edi里
6E D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9 02 18 74 95 1F C2 4D 33 3C F0 3B EC E9 81
4B 9C 0F 47 5C AD D9 09 B0 87 53 9B F2 E3 0F 01 92 8D C2 F5 0C DD 42 CC AF B4 D5 E4 86 D3
9A 0B 62 63 A7 D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9 02 18 74 95 1F C2 4D 33 38 F0
3B EC ED 81 4B 9C 0B 47 5C AD DD 09 B0 87 57 9B F2 E3 0B 01 92 8D C2 F5 0C DD 42 CC AF B4
D5 E4 86 D3 9A 0B 62 63 A7 D4 1B 69 5F 4E E8 AA 95 F6 AF CE 32 1A 62 D9 02 18 74 95 1F C2
4D 33 38 F0 3B EC E9 81 4B 9C 0F 47 5C AD D9 09 B0 87 53 9B F2 E3 0F 01 92 8D C2 F5 0C DD
42 CC AF B4 D5 E4 86 D3 9A 0B 62 63 A7 D4 1B 69 5B 4E E8 AA 91 F6 AF CE 36 1A 62 D9 02 18
74 95 1F C2 4D 33 38 F0 3B EC E9 81 4B 9C 0B 47 5C AD DD 09 B0 87 57 9B F2 E3 0B 01 92 8D
C6 F5 0C DD 42 CC AF B4 D5 E4 86 D3 9A 0B 62 63
00401210 BE 98384100 mov esi,CrackMe.00413898
00401215 8DBD 90FEFFFF lea edi,dword ptr ss:[ebp-0x170]
0040121B F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi]
0040121D 33C9 xor ecx,ecx
0040121F 898D 2CFCFFFF mov dword ptr ss:[ebp-0x3D4],ecx
同样复制操作
D8 05 F6 6A E7 A2 0B 9B 54 8C DA 82 BD B6 A8 46 B1 36 2D 55 F7 81 63 FC 3F 0C FE 0B 4B 50
E2 17 F2 E1 27 5B 46 73 1C D0 E5 D7 8D C9 F2 70 94 53 81 4C 32 46 A0 02 DB 1C 45 09 91 C4
96 F2 A8 E8 D9 05 F6 6B E7 A2 0A 9B 54 8C DA 82 BD B7 A9 46 B0 36 2D 54 F7 81 63 FC 3E 0C
FE 0B 4B 50 E3 17 F2 E0 26 5A 47 73 1C D1 E5 D6 8C C8 F2 70 95 53 80 4C 33 47 A0 02 DB 1C
44 08 91 C4 96 F2 A9 E8 D9 04 F6 6A E7 A2 0A 9B 55 8C DB 83 BC B6 A9 46 B0 37 2D 55 F7 81
63 FD 3E 0D FE 0B 4A 50 E3 17 F3 E0 27 5B 46 73 1D D0 E4 D7 8C C8 F3 70 95 53 80 4C 33 47
A0 03 DB 1D 45 08 91 C4 96 F2 A9 E8 D9 04 F6 6A E6 A3 0A 9A 54 8C DB 82 BC B7 A9 46 B0 37
2C 54 F6 81 62 FD 3E 0D FE 0A 4A 50 E2 17 F2 E1 27 5B 47 72 1C D0 E5 D7 8C C9 F2 70 94 53
81 4D 33 47 A0 03 DB 1C 44 08 91 C5 97 9A A8 E8
解密流程:
lea edx,dword ptr ss:[ebp-0x170]
add edx, eax
mov cl,byte ptr ss:[ebp+eax-0x370]
mov al,cl
ror al,0x2
movzx ecx,al
movzx eax,byte ptr ds:[edx]
xor ecx,eax
这里生成一个迷宫地图,就是将上面的两个特定表进行异或生成的
引用别人的源码
int i = 0;
int j = 0;
unsigned char cch = 0; int m = 6;
ctx xx[] = { { 16, 2 }, { 1, 1 }, { -1, 3}, { -16, 0 } };
while (t3[i] != 0x58)
{
for (int k = 0; k < 4; k++)
{
int v = i + xx[k].n;
if (v < 0 || v > 255)
continue;
if (j != v && ((t3[v] == 0x31) || (t3[v] == 0x58)))
{
j = i;
i = v;
cch |= ((xx[k].bit & 0x03) << m);
if (m == 0)
{
printf("%02X ", cch);
cch = 0;
m = 8;
}
m -= 2;
break;
}
}
}
printf("%02X ", cch);
输出为:
x1=
A9 5A BE AA A5 55 A5 00 00 FA BC 00 00 15 55 AF FE 95 55 AA AA FE A5
由路线图可以得到序列2221 1122 2332 2222 2211 1111 2211 0000 0000 3322 2330 0000 0000 0111 1111 2233 3332 2111 1111 2222 2222 3332 2211
16进制
0xA9,0x5A,0xbe,0xaa, 0xa5,0x55,0xa5,0x00,
0x00,0xfa,0xbc,0x00, 0x00,0x15,0x55,0xaf,
0xfe,0x95,0x55,0xaa, 0xaa,0xfe,0xa5,0x00
上面是手动走出来的数据
我们知道这个步进的数据是经过两个xor出来的,所以还要xor回去得到正确的注册码
注册码前7位的md5作为xor列表,只有16个字节,步进数据要23个字节,后面的7个字节用前面的来补齐,然后再
xor {0x44, 0xAD, 0x5C, 0xCC, 0x12, 0x90, 0x73, 0x8D, 0x47, 0x81,
0xE3, 0x89, 0x84, 0x9C, 0xDF, 0xF9, 0x47, 0x6A, 0xB6, 0x9E,
0x11, 0x30, 0x27}
参考文章:
http://bbs.pediy.com/showthread.php?t=213796
http://bbs.pediy.com/showthread.php?t=213802
http://bbs.pediy.com/showthread.php?t=213805
等等