看雪CTF 2016_第四题分析

结合前辈们的分析,自己再作一个分析,算是当做学习笔记吧!

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

这里生成一个迷宫地图,就是将上面的两个特定表进行异或生成的

要求从C开始走到X,0为墙,相当于吃豆子游戏。

引用别人的源码

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

等等

 

文档下载:http://www.vdisk.cn/down/index/19774317

原文地址:https://www.cnblogs.com/Sendige/p/9601040.html