首页
社区
课程
招聘
CrackMe第四题分析记录
发表于: 2016-11-9 22:52 2817

CrackMe第四题分析记录

2016-11-9 22:52
2817
--- 以下仅为个人见解

公式:

(Md5(sn.sub(0, 7)) + Md5(sn.sub(0, 7)).sub(0,7)) ^ 
ConstArray ^ sn.sub(7, 23) = XArray


unsigned char ConstArray[23] = 
{
	0x44, 0xAD, 0x5C, 0xCC, 0x12, 0x90, 0x73, 
        0x8D, 0x47, 0x81, 0xE3, 0x89, 0x84, 0x9C, 
        0xDF, 0xF9, 0x47, 0x6A, 0xB6, 0x9E, 0x11, 0x30, 0x27
};

XArray 需要后续分析,为迷宫路线

sn最后由穷举产生,不唯一




题目使用了虚拟机,如果不是对虚拟机本身的安全性感兴趣的话可以只寻找虚拟机的关键点,主要包括普通代码段对虚拟机内部的调用边界,还有就是虚拟机的出口(VMEXIT);

这里只表述虚拟机的出口处:
     1. 进入虚拟机, 这个比较简单,主程序中GetDlgItemTextA断点就可返回到

00401491  |.  8BD0          MOV EDX,EAX
00401493  |.  8D8D FCFDFFFF LEA ECX,DWORD PTR SS:[EBP-204]
00401499  |.  E8 62FBFFFF   CALL CrackMe.00401000
0040149E  |.  83F8 01       CMP EAX,1


40149E为返回结果判断,从00401499进入,直到Jmp:
004010B0   .  0FB647 06     MOVZX EAX,BYTE PTR DS:[EDI+6]
004010B4   .  8845 96       MOV BYTE PTR SS:[EBP-6A],AL
004010B7   .  E9 7CDF0200   JMP CrackMe.0042F038
004010BC      00            DB 00
004010BD      00            DB 00

然后来到虚拟机入口:
0042F052    8BFC            MOV EDI,ESP
[COLOR="Red"]0042F054    BE 0E544300     MOV ESI,CrackMe.0043540E[/COLOR]
0042F059    E9 7B0C0000     JMP CrackMe.0042FCD9
0042F05E    0000            ADD BYTE PTR DS:[EAX],AL
0042F060    0000            ADD BYTE PTR DS:[EAX],AL

取码分发:
0042FCDB    4B              DEC EBX
0042FCDC    66:F7D3         NOT BX
0042FCDF    66:81EB D165    SUB BX,65D1
0042FCE4    0FB646 FF       MOVZX EAX,BYTE PTR DS:[ESI-1]
0042FCE8    4E              DEC ESI
0042FCE9    2AC3            SUB AL,BL
0042FCEB    F6D0            NOT AL
0042FCED    04 57           ADD AL,57
0042FCEF    FEC8            DEC AL
0042FCF1    2C 3E           SUB AL,3E
0042FCF3    FF3485 DDF84200 PUSH DWORD PTR DS:[EAX*4+42F8DD]
0042FCFA    C3              RETN

有兴趣的可以看一下Handler表,但重点不在此,此时略。

     2. 跟踪Handler,定位VM_EIP查看字节码内存,粗略定位:
本程序字节码即VM_EIP由esi指定,上面的红色指令已经给出。同时字节码倒序取出执行(走一下就能看到),见下图:

图略。

在内存中查看VM_EIP执行的数据块:

0043539E  B6 ED 08 27 5A 7C A4 95 FE 0F 60 84 C2 1E 1C 77  俄'Z|?`劼w
004353AE  66 AC B8 E5 0A 3F 54 54 AE CD 10 47 72 DC CC 36  f??TTGr芴6
004353BE  16 6F 68 A4 BA FD 04 17 5E 8C C0 06 22 9F 7C F4  ohず?^尷"焲
004353CE  C6 2E 18 67 6A BC B4 D5 0E 4F 70 14 06 B9 EF 30  ?gj即?Op癸0
004353DE  B4 49 1F 27 56 79 30 E6 B3 14 3E C0 79 ED 6E 24  碔'Vy0娉>纘韓$
004353EE  01 5F 50 17 44 18 05 50 19 89 23 CA 06 1E 5C EE  _PDP??\
004353FE  20 42 08 A2 0C 7E 28 75 24 04 3C 19 18 77 00 AB   B?~(u$<w.
0043540E  00                                               .



接着往上看,直到出现一段内存为0为止... ... ...

0043025E  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0043026E  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0043027E  00 [COLOR="red"]86[/COLOR] E4 F2 5E 4C 24 96 8D E8 66 3A 2F 84 C3 DE  .嗕騘L$枍鑖:/劽
0043028E  8E 40 A8 53 F4 8C A4 8A D2 9B F3 6F 2C 50 AD 50  嶡⊿魧覜髈,P璓
0043029E  94 0D DC 20 EE 62 25 67 42 FD EA F0 B5 48 79 86  ??頱%gB鸬Hy



红色数据断点,运行,会断在取码处,往前走走,就到了虚拟机退出位置。

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
0042F77A    F6D3            NOT BL
0042F77C    8A46 FF         MOV AL,BYTE PTR DS:[ESI-1]



再跟下去,就返回了壳外代码。

在本题目里,此后就没虚拟机什么事情了

        3. 出入虚拟机

每次都从虚拟机出来进行跟踪,此时需要对栈上数据留意下,配合预先用PEID对对程序扫描的结果,会先进行md5的计算,个人分别定位出Md5Update, Md5Final, 但可不必纠结这个,因为只要可以在后续遇到字节流是可以确定那个是由MD5生成即可,但要关注下取了注册码的多少个字节进行的md5,不过这是在栈中可以看到的。

         4. 后来

后续就来到了对注册码的主要操作阶段,包括对30个字节码后续23字节的处理,一些异或的过程,由于这些过程是没有被虚拟化的,简单带过,数据为主:


// 
unsigned char data1[256] = {
	0x6E, 0xD4, 0x1B, 0x69, 0x5F, 0x4E, 0xE8, 0xAA, 0x95, 0xF6, 0xAF, 0xCE, 0x32, 0x1A, 0x62, 0xD9,
	0x02, 0x18, 0x74, 0x95, 0x1F, 0xC2, 0x4D, 0x33, 0x3C, 0xF0, 0x3B, 0xEC, 0xE9, 0x81, 0x4B, 0x9C,
	0x0F, 0x47, 0x5C, 0xAD, 0xD9, 0x09, 0xB0, 0x87, 0x53, 0x9B, 0xF2, 0xE3, 0x0F, 0x01, 0x92, 0x8D,
	0xC2, 0xF5, 0x0C, 0xDD, 0x42, 0xCC, 0xAF, 0xB4, 0xD5, 0xE4, 0x86, 0xD3, 0x9A, 0x0B, 0x62, 0x63,
	0xA7, 0xD4, 0x1B, 0x69, 0x5F, 0x4E, 0xE8, 0xAA, 0x95, 0xF6, 0xAF, 0xCE, 0x32, 0x1A, 0x62, 0xD9,
	0x02, 0x18, 0x74, 0x95, 0x1F, 0xC2, 0x4D, 0x33, 0x38, 0xF0, 0x3B, 0xEC, 0xED, 0x81, 0x4B, 0x9C,
	0x0B, 0x47, 0x5C, 0xAD, 0xDD, 0x09, 0xB0, 0x87, 0x57, 0x9B, 0xF2, 0xE3, 0x0B, 0x01, 0x92, 0x8D,
	0xC2, 0xF5, 0x0C, 0xDD, 0x42, 0xCC, 0xAF, 0xB4, 0xD5, 0xE4, 0x86, 0xD3, 0x9A, 0x0B, 0x62, 0x63,
	0xA7, 0xD4, 0x1B, 0x69, 0x5F, 0x4E, 0xE8, 0xAA, 0x95, 0xF6, 0xAF, 0xCE, 0x32, 0x1A, 0x62, 0xD9,
	0x02, 0x18, 0x74, 0x95, 0x1F, 0xC2, 0x4D, 0x33, 0x38, 0xF0, 0x3B, 0xEC, 0xE9, 0x81, 0x4B, 0x9C,
	0x0F, 0x47, 0x5C, 0xAD, 0xD9, 0x09, 0xB0, 0x87, 0x53, 0x9B, 0xF2, 0xE3, 0x0F, 0x01, 0x92, 0x8D,
	0xC2, 0xF5, 0x0C, 0xDD, 0x42, 0xCC, 0xAF, 0xB4, 0xD5, 0xE4, 0x86, 0xD3, 0x9A, 0x0B, 0x62, 0x63,
	0xA7, 0xD4, 0x1B, 0x69, 0x5B, 0x4E, 0xE8, 0xAA, 0x91, 0xF6, 0xAF, 0xCE, 0x36, 0x1A, 0x62, 0xD9,
	0x02, 0x18, 0x74, 0x95, 0x1F, 0xC2, 0x4D, 0x33, 0x38, 0xF0, 0x3B, 0xEC, 0xE9, 0x81, 0x4B, 0x9C,
	0x0B, 0x47, 0x5C, 0xAD, 0xDD, 0x09, 0xB0, 0x87, 0x57, 0x9B, 0xF2, 0xE3, 0x0B, 0x01, 0x92, 0x8D,
	0xC6, 0xF5, 0x0C, 0xDD, 0x42, 0xCC, 0xAF, 0xB4, 0xD5, 0xE4, 0x86, 0xD3, 0x9A, 0x0B, 0x62, 0x63
};

// 
unsigned char data2[256] = {
	0xD8, 0x05, 0xF6, 0x6A, 0xE7, 0xA2, 0x0B, 0x9B, 0x54, 0x8C, 0xDA, 0x82, 0xBD, 0xB6, 0xA8, 0x46,
	0xB1, 0x36, 0x2D, 0x55, 0xF7, 0x81, 0x63, 0xFC, 0x3F, 0x0C, 0xFE, 0x0B, 0x4B, 0x50, 0xE2, 0x17,
	0xF2, 0xE1, 0x27, 0x5B, 0x46, 0x73, 0x1C, 0xD0, 0xE5, 0xD7, 0x8D, 0xC9, 0xF2, 0x70, 0x94, 0x53,
	0x81, 0x4C, 0x32, 0x46, 0xA0, 0x02, 0xDB, 0x1C, 0x45, 0x09, 0x91, 0xC4, 0x96, 0xF2, 0xA8, 0xE8,
	0xD9, 0x05, 0xF6, 0x6B, 0xE7, 0xA2, 0x0A, 0x9B, 0x54, 0x8C, 0xDA, 0x82, 0xBD, 0xB7, 0xA9, 0x46,
	0xB0, 0x36, 0x2D, 0x54, 0xF7, 0x81, 0x63, 0xFC, 0x3E, 0x0C, 0xFE, 0x0B, 0x4B, 0x50, 0xE3, 0x17,
	0xF2, 0xE0, 0x26, 0x5A, 0x47, 0x73, 0x1C, 0xD1, 0xE5, 0xD6, 0x8C, 0xC8, 0xF2, 0x70, 0x95, 0x53,
	0x80, 0x4C, 0x33, 0x47, 0xA0, 0x02, 0xDB, 0x1C, 0x44, 0x08, 0x91, 0xC4, 0x96, 0xF2, 0xA9, 0xE8,
	0xD9, 0x04, 0xF6, 0x6A, 0xE7, 0xA2, 0x0A, 0x9B, 0x55, 0x8C, 0xDB, 0x83, 0xBC, 0xB6, 0xA9, 0x46,
	0xB0, 0x37, 0x2D, 0x55, 0xF7, 0x81, 0x63, 0xFD, 0x3E, 0x0D, 0xFE, 0x0B, 0x4A, 0x50, 0xE3, 0x17,
	0xF3, 0xE0, 0x27, 0x5B, 0x46, 0x73, 0x1D, 0xD0, 0xE4, 0xD7, 0x8C, 0xC8, 0xF3, 0x70, 0x95, 0x53,
	0x80, 0x4C, 0x33, 0x47, 0xA0, 0x03, 0xDB, 0x1D, 0x45, 0x08, 0x91, 0xC4, 0x96, 0xF2, 0xA9, 0xE8,
	0xD9, 0x04, 0xF6, 0x6A, 0xE6, 0xA3, 0x0A, 0x9A, 0x54, 0x8C, 0xDB, 0x82, 0xBC, 0xB7, 0xA9, 0x46,
	0xB0, 0x37, 0x2C, 0x54, 0xF6, 0x81, 0x62, 0xFD, 0x3E, 0x0D, 0xFE, 0x0A, 0x4A, 0x50, 0xE2, 0x17,
	0xF2, 0xE1, 0x27, 0x5B, 0x47, 0x72, 0x1C, 0xD0, 0xE5, 0xD7, 0x8C, 0xC9, 0xF2, 0x70, 0x94, 0x53,
	0x81, 0x4D, 0x33, 0x47, 0xA0, 0x03, 0xDB, 0x1C, 0x44, 0x08, 0x91, 0xC5, 0x97, 0x9A, 0xA8, 0xE8
};


       以上两组数据在以下代码中---拷贝,其上方就是公式中表现的一些异或操作(略):


... XOR ... 
... XOR...
... ... ...
004011F1    B9 40000000     MOV ECX,40
004011F6    8DBD 90FCFFFF   LEA EDI,DWORD PTR SS:[EBP-370]
004011FC    BE 98374100     MOV ESI,CrackMe.00413798
00401201    33C0            XOR EAX,EAX
00401203    F3:A5           REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
00401205    B9 40000000     MOV ECX,40
0040120A    8985 30FCFFFF   MOV DWORD PTR SS:[EBP-3D0],EAX
00401210    BE 98384100     MOV ESI,CrackMe.00413898
00401215    8DBD 90FEFFFF   LEA EDI,DWORD PTR SS:[EBP-170]
0040121B    F3:A5           REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
0040121D    33C9            XOR ECX,ECX
0040121F    898D 2CFCFFFF   MOV DWORD PTR SS:[EBP-3D4],ECX



接着后面就是迷宫操作,该判断来自于一下代码片段:


00401248    8A8D 0CFCFFFF   MOV CL,BYTE PTR SS:[EBP-3F4]
0040124E    D3EA            SHR EDX,CL
00401250    83E2 03         AND EDX,3
00401253    FF2495 0C144000 JMP DWORD PTR DS:[EDX*4+40140C]
0040125A    83E8 10         SUB EAX,10
0040125D    EB 09           JMP SHORT CrackMe.00401268
0040125F    40              INC EAX
00401260    EB 06           JMP SHORT CrackMe.00401268
00401262    83C0 10         ADD EAX,10
00401265    EB 01           JMP SHORT CrackMe.00401268
00401267    48              DEC EAX
00401268    8985 30FCFFFF   MOV DWORD PTR SS:[EBP-3D0],EAX


起初是不太清楚是推箱子还是迷宫,只能判断是个16*16的,,,推迷宫了,,,但后来把这上上下下的几片代码摆在一起就清晰了,从这么大的数据栈看来,作者有可能是为了能充分的减少边界而都堆在一个函数里面的,也有可能偷懒,再或者... 毕竟作者才是作者...

            5. 谜底

继续看下去就都明了了,如下:

004012CE    8995 04FCFFFF   MOV DWORD PTR SS:[EBP-3FC],EDX
004012D4    8A8C05 90FCFFFF MOV CL,BYTE PTR SS:[EBP+EAX-370]
004012DB    8AC1            MOV AL,CL
004012DD    888D 37FCFFFF   MOV BYTE PTR SS:[EBP-3C9],CL
[COLOR="red"]004012E3    C0C8 02         ROR AL,2[/COLOR]
004012E6    0FB6C8          MOVZX ECX,AL
004012E9    0FB602          MOVZX EAX,BYTE PTR DS:[EDX]
004012EC    33C8            XOR ECX,EAX
[COLOR="red"]004012EE    83F9 30         CMP ECX,30[/COLOR]
004012F1    0F84 E2000000   JE CrackMe.004013D9
[COLOR="red"]004012F7    83F9 20         CMP ECX,20[/COLOR]
004012FA    0F84 D9000000   JE CrackMe.004013D9
[COLOR="red"]00401300    83F9 58         CMP ECX,58[/COLOR]
00401303    0F84 E5000000  [COLOR="DarkOrchid"] JE CrackMe.004013EE[/COLOR]
00401309    8B8D 10FCFFFF   MOV ECX,DWORD PTR SS:[EBP-3F0]
0040130F    8BC1            MOV EAX,ECX
00401311    99              CDQ
00401312    83E2 0F         AND EDX,0F
00401315    03C2            ADD EAX,EDX
00401317    C1F8 04         SAR EAX,4
0040131A    8985 08FCFFFF   MOV DWORD PTR SS:[EBP-3F8],EAX


这里面有对两个数组的使用,对数值的比较,紫色为爆破参考点。唯一缺少的就是复原下两个数组的关系了,写段程序,按照上面的处理方式,于是柳暗花明。

	for (int i = 0; i < 256; i++)
	{
		unsigned char tmp = ((data1[i] >> 2) | ((data1[i]) & 0x00000003) << 6);
		printf("%d[%02x] = %02x - %d\n", i, tmp, tmp ^ data2[i], tmp ^ data2[i]);
		mig[i] = tmp^data2[i];
	}



如图:


4330303030                303030
  30303030  303030303030  303030
  30303030  30            303030
        30  30  3030303030303030
303030  30  30                30
303030  30  3030303030303030  30
30      30  3030303030303030  30
30  303030  30      30303030  30
30  303030  30  30  30303030  30
30  303030  30  30  30303030  30
30  303030      30  30303030  30
30  30303030303030  30303030  30
30  30303030303030  30        30
30              30  30  30303030
30303030303030  30  30  30303030
30303030303030      30    583030



看到了这个图(把部分数据过滤掉了),云雾彻底揭开,可在写出路径的前,需要根据一段不曾提及的代码来确定路径编码规则:

0040122C    C785 0CFCFFFF 0>MOV DWORD PTR SS:[EBP-3F4],6


程序中对每个字节分四段来处理判断,所以规则就是...
                                  所以路径就是...

unsigned char path[23] = {
0xa9, 0x5a, 0xbe, 0xaa, 0xa5, 0x55,
0xa5, 0x00, 0x00, 0xfa, 0xbc, 0x00, 
0x00, 0x15, 0x55, 0xaf, 0xfe, 0x95, 
0x55, 0xaa, 0xaa, 0xfe, 0xa5
};


   6. 穷举

得到路径后根据公式,MD5穷举,刚开始还残了一下,想要随机碰撞,,,但还是,,,穷举好点
代码片段:

[CODE]
[CODE]
[CODE]
[CODE]
[CODE]
[CODE]

	testt[0] = enumt[x1];
	testt[1] = enumt[x2];
	testt[2] = enumt[x3];
	testt[3] = enumt[x4];
	testt[4] = enumt[x5];
	testt[5] = enumt[x6];
	testt[6] = enumt[x7];

	MD5_CTX ctx = { 0 };
	MD5Init(&ctx);
	MD5Update(&ctx, testt, 7);
	MD5Final(&ctx);

	memcpy(tmp, ctx.digest, 16);
	memcpy(tmp + 16, ctx.digest, 7);

	unsigned char tmp2[28] = { 0 };
	for (int i = 0; i < 23; i++)
	{
		tmp2[i] = tmp[i] ^ destv[i];
	}

	int ok = 1;
	for (int i = 0; i < 23; i++)
	{
		if (tmp2[i] < '0' ||
		(tmp2[i] > '9'&& tmp2[i] < 'A') ||
		(tmp2[i] > 'Z' &&tmp2[i] < 'a') ||
		(tmp2[i] > 'z'))
		{
			ok = 0;
			break;
		}
	}
	if (ok == 0)
	{
		continue;
	}

	printf("ok: try use this: %s - %s \n", testt, tmp2);
	break;


[/CODE]
[/CODE]
[/CODE]
[/CODE]
[/CODE]
[/CODE]

配合脑补,七层代码七层循环... 原本放在几个线程里分段算,,,结果发现没那么慢...


ok: try use this: 007RiQS - vXasVB,)o7g_2;g!"P`!ZIx
ok: try use this: 00a4YwD - f'ypKMq+Y^so]eKM2/x"GF%



测试成功,如图:



---------------------------
information
---------------------------
注册成功:)
---------------------------
确定   
---------------------------




最后配上一张视力表:



土陋了哈...

.End

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//