首页
社区
课程
招聘
[原创]看雪2016 第四题 CrackMe逆向分析
发表于: 2016-11-9 16:46 2717

[原创]看雪2016 第四题 CrackMe逆向分析

2016-11-9 16:46
2717
OD加载crackme,Ctrl+N 查找GetDlgItemTextA来到

00401474  |.  68 00020000   push    200                              ; /Count = 200 (512.)
00401479  |.  8D85 FCFDFFFF lea     eax, dword ptr [ebp-204]         ; |
0040147F  |.  50            push    eax                              ; |Buffer
00401480  |.  68 E8030000   push    3E8                              ; |ControlID = 3E8 (1000.)
00401485  |.  56            push    esi                              ; |hWnd
00401486  |.  FF15 04D14000 call    dword ptr [<&USER32.GetDlgItemTe>; \GetDlgItemTextA
0040148C  |.  83F8 1E       cmp     eax, 1E
0040148F  |.  75 25         jnz     short 004014B6
00401491  |.  8BD0          mov     edx, eax
00401493  |.  8D8D FCFDFFFF lea     ecx, dword ptr [ebp-204]
00401499  |.  E8 62FBFFFF   call    00401000
0040149E  |.  83F8 01       cmp     eax, 1
004014A1  |.  75 13         jnz     short 004014B6
004014A3  |.  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
004014A5  |.  68 80374100   push    00413780                         ; |Title = "information"
004014AA  |.  68 8C374100   push    0041378C                         ; |Text = ""D7,"",A2,"",B2,"岢晒",A6,""
004014AF  |.  56            push    esi                              ; |hOwner
004014B0  |.  FF15 00D14000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
004014B6  |>  8B4D FC       mov     ecx, dword ptr [ebp-4]           ;  Default case of switch 0040143A

明显 00401499  |.  E8 62FBFFFF   call    00401000 为注册函数,且返回1表示成功。

继续分析发现
0042FCD9    F7D3            not     ebx
0042FCDB    4B              dec     ebx
0042FCDC    66:F7D3         not     bx
0042FCDF    66:81EB D165    sub     bx, 65D1
0042FCE4    0FB646 FF       movzx   eax, byte ptr [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 [eax*4+42F8DD]
0042FCFA    C3              retn
这个是vm_loop 作者使用了虚拟机。好吧,这里先不分析了。

对输入内容下硬件断点,来到 MD5
004014F0  /$  55            push    ebp                              ;  md5_update
004014F1  |.  8BEC          mov     ebp, esp
004014F3  |.  83EC 0C       sub     esp, 0C
004014F6  |.  53            push    ebx
004014F7  |.  8B5D 08       mov     ebx, dword ptr [ebp+8]
004014FA  |.  56            push    esi
004014FB  |.  57            push    edi

PEID工具也可确认是MD5

MD5 :: 00000B37 :: 00401737
        The reference is above.
SHA-512/384 [mixing] :: 00010198 :: 00411998
        The reference is above.

I1 =
0019F6A0  32 32 32 32 32 32 32 00 00 00 00 00 00 00 00 00  2222222.........
输入数据为 前7个字符

通过vm_loop 找到handler表
0042F8DD  70 4A ED 20 AA F1 42 00 BD F1 42 00 D6 F1 42 00  pJ?B.今B.竹B.
0042F8ED  06 F2 42 00 31 F2 42 00 5C F2 42 00 7F F2 42 00  駼.1駼.\駼.駼.
0042F8FD  A2 F2 42 00 BE F2 42 00 E5 F2 42 00 FE F2 42 00  ⅡB.掘B.弪B.B.
0042F90D  16 F3 42 00 3C F3 42 00 54 F3 42 00 7A F3 42 00  驜.<驜.T驜.z驜.
0042F91D  A3 F3 42 00 CF F3 42 00 00 F4 42 00 34 F4 42 00  sB.象B..鬊.4鬊.
0042F92D  41 F4 42 00 72 F4 42 00 85 F4 42 00 A2 F4 42 00  A鬊.r鬊.咊B.ⅣB.
0042F93D  BA F4 42 00 DE F4 42 00 F6 F4 42 00 1C F5 42 00  呼B.摁B.鲷B.魾.
0042F94D  4A F5 42 00 63 F5 42 00 88 F5 42 00 AD F5 42 00  J魾.c魾.堳B.B.
0042F95D  C5 F5 42 00 DC F5 42 00 01 F6 42 00 23 F6 42 00  捧B.荃B.鯞.#鯞.

依次查看可找到 vm_exit
0042F76F    8BE5            mov     esp, ebp                         ; vm_exit
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

几次断点后来到
0040115E      8B8D 2CFCFFFF mov     ecx, dword ptr [ebp-3D4]
00401164      8B41 17       mov     eax, dword ptr [ecx+17]
00401167      0F1041 07     movups  xmm0, dqword ptr [ecx+7]
0040116B      8945 E0       mov     dword ptr [ebp-20], eax
0040116E      0FB741 1B     movzx   eax, word ptr [ecx+1B]
00401172      66:8945 E4    mov     word ptr [ebp-1C], ax
00401176      0FB641 1D     movzx   eax, byte ptr [ecx+1D]
0040117A      33C9          xor     ecx, ecx
0040117C      0F1145 D0     movups  dqword ptr [ebp-30], xmm0
00401180      8845 E6       mov     byte ptr [ebp-1A], al
00401183      8A440D D0     mov     al, byte ptr [ebp+ecx-30]
00401187      32840D 14FCFF>xor     al, byte ptr [ebp+ecx-3EC]
0040118E      88840D E8FBFF>mov     byte ptr [ebp+ecx-418], al
00401195      83F9 17       cmp     ecx, 17
00401198      0F83 68020000 jnb     00401406
0040119E      C6440D D0 00  mov     byte ptr [ebp+ecx-30], 0
004011A3      C6840D 14FCFF>mov     byte ptr [ebp+ecx-3EC], 0
004011AB      41            inc     ecx
004011AC      83F9 17       cmp     ecx, 17
004011AF    ^ 7C D2         jl      short 00401183

发现这里是
I2=
0019F6E0  32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32  2222222222222222
0019F6F0  32 32 32 32 32 32 32                             2222222
y2=
0019F324  44 AD 5C CC 12 90 73 8D 47 81 E3 89 84 9C DF F9  D璡?恠岹併墑溸?
0019F334  47 6A B6 9E 11 30 27                             Gj稙0'.

I2= I2^y2 对输入进行异或操作。

004011C0      8A840D 90FDFF>mov     al, byte ptr [ebp+ecx-270]
004011C7      32840D E8FBFF>xor     al, byte ptr [ebp+ecx-418]
004011CE      88440D D0     mov     byte ptr [ebp+ecx-30], al
004011D2      83F9 17       cmp     ecx, 17
004011D5      0F83 2B020000 jnb     00401406
004011DB      C6840D E8FBFF>mov     byte ptr [ebp+ecx-418], 0
004011E3      C6840D 90FDFF>mov     byte ptr [ebp+ecx-270], 0
004011EB      41            inc     ecx
004011EC      83F9 17       cmp     ecx, 17
004011EF    ^ 7C CF         jl      short 004011C0

y1 = MD5(I1)^I2
0019F4A0  79 D8 86 01 01 86 EB 60 E3 61 1C D4 A5 D0 BC AE  y貑嗠`鉧豫屑?
0019F4B0  79 D8 86 01 01 86 EB                             y貑嗠..
上面是 I2与MD5后的结果异或。为了达到23字节所以循环取值了一下。

004011F1      B9 40000000   mov     ecx, 40
004011F6      8DBD 90FCFFFF lea     edi, dword ptr [ebp-370]
004011FC      BE 98374100   mov     esi, 00413798
00401201      33C0          xor     eax, eax
00401203      F3:A5         rep     movs dword ptr es:[edi], dword ptr [esi]
00401205      B9 40000000   mov     ecx, 40
0040120A      8985 30FCFFFF mov     dword ptr [ebp-3D0], eax
00401210      BE 98384100   mov     esi, 00413898
00401215      8DBD 90FEFFFF lea     edi, dword ptr [ebp-170]
0040121B      F3:A5         rep     movs dword ptr es:[edi], dword ptr [esi]
0040121D      33C9          xor     ecx, ecx
复制 2个 256字节的数据,通过下面的分析 这里应该是迷宫(16X16 )数据(被加密的)分别记t1和t2

0040121F      898D 2CFCFFFF mov     dword ptr [ebp-3D4], ecx
00401225   >  8A4C0D D0     mov     cl, byte ptr [ebp+ecx-30]
00401229   .  0FB6C9        movzx   ecx, cl
0040122C   .  C785 0CFCFFFF>mov     dword ptr [ebp-3F4], 6
00401236   .  898D 00FCFFFF mov     dword ptr [ebp-400], ecx
0040123C      0F1F4000      dd      crackme.00401F0F
00401240   >  8BD1          mov     edx, ecx
00401242   .  8985 10FCFFFF mov     dword ptr [ebp-3F0], eax
00401248   .  8A8D 0CFCFFFF mov     cl, byte ptr [ebp-3F4]                        ;  cl == 6
0040124E   .  D3EA          shr     edx, cl
00401250   .  83E2 03       and     edx, 3
00401253   .  FF2495 0C1440>jmp     dword ptr [edx*4+40140C]                      ;  jmp[y&0x03]??
0040125A   >  83E8 10       sub     eax, 10
0040125D   .  EB 09         jmp     short 00401268
0040125F   >  40            inc     eax
00401260   .  EB 06         jmp     short 00401268
00401262   >  83C0 10       add     eax, 10
00401265   .  EB 01         jmp     short 00401268
00401267   >  48            dec     eax
00401268   >  8985 30FCFFFF mov     dword ptr [ebp-3D0], eax
这里应该是计算走迷宫的步骤,每2bit代表一个方向
eax = 0
0=eax-10
1=eax+1
2=eax+10
3=eax-1

00401283   .  25 0F000080   and     eax, 8000000F
00401288   .  79 05         jns     short 0040128F
0040128A   .  48            dec     eax                                           ;  <0
0040128B   .  83C8 F0       or      eax, FFFFFFF0
0040128E   .  40            inc     eax
0040128F   >  8985 04FCFFFF mov     dword ptr [ebp-3FC], eax
00401295   .- E9 DBB10300   jmp     0043C475
这里进虚拟机,先不管他

退出虚拟机后来到这里
004012B5   ?  8B8D 08FCFFFF mov     ecx, dword ptr [ebp-3F8]
004012BB   ?  8D95 90FEFFFF lea     edx, dword ptr [ebp-170]
004012C1   ?  8B85 04FCFFFF mov     eax, dword ptr [ebp-3FC]
004012C7   ?  C1E1 04       shl     ecx, 4
004012CA   .  03C1          add     eax, ecx
004012CC   .  03D0          add     edx, eax
004012CE   >  8995 04FCFFFF mov     dword ptr [ebp-3FC], edx
004012D4   .  8A8C05 90FCFF>mov     cl, byte ptr [ebp+eax-370]
004012DB   .  8AC1          mov     al, cl
004012DD   .  888D 37FCFFFF mov     byte ptr [ebp-3C9], cl
004012E3   .  C0C8 02       ror     al, 2
004012E6   .  0FB6C8        movzx   ecx, al
004012E9   .  0FB602        movzx   eax, byte ptr [edx]
004012EC   .  33C8          xor     ecx, eax
004012EE   .  83F9 30       cmp     ecx, 30
004012F1   .  0F84 E2000000 je      004013D9
004012F7   .  83F9 20       cmp     ecx, 20
004012FA   .  0F84 D9000000 je      004013D9
00401300   .  83F9 58       cmp     ecx, 58
00401303   .  0F84 E5000000 je      004013EE
上面是走迷宫的算法,包含迷宫解密算法如下:
t3[i] = ror(t1[i], 2) xor t2[i]
0x00CFF878  43 30 30 30 30 31 31 31 31 31 31 31 31 30 30 30  C000011111111000
0x00CFF888  31 30 30 30 30 31 30 30 30 30 30 30 31 30 30 30  1000010000001000
0x00CFF898  31 30 30 30 30 31 30 31 31 31 31 31 31 30 30 30  1000010111111000
0x00CFF8A8  31 31 31 31 30 31 30 31 30 30 30 30 30 30 30 30  1111010100000000
0x00CFF8B8  30 30 30 31 30 31 30 31 31 31 31 31 31 31 31 30  0001010111111110
0x00CFF8C8  30 30 30 31 30 31 30 30 30 30 30 30 30 30 31 30  0001010000000010
0x00CFF8D8  30 31 31 31 30 31 30 30 30 30 30 30 30 30 31 30  0111010000000010
0x00CFF8E8  30 31 30 30 30 31 30 31 31 31 30 30 30 30 31 30  0100010111000010
0x00CFF8F8  30 31 30 30 30 31 30 31 30 31 30 30 30 30 31 30  0100010101000010
0x00CFF908  30 31 30 30 30 31 30 31 30 31 30 30 30 30 31 30  0100010101000010
0x00CFF918  30 31 30 30 30 31 31 31 30 31 30 30 30 30 31 30  0100011101000010
0x00CFF928  30 31 30 30 30 30 30 30 30 31 30 30 30 30 31 30  0100000001000010
0x00CFF938  30 31 30 30 30 30 30 30 30 31 30 31 31 31 31 30  0100000001011110
0x00CFF948  30 31 31 31 31 31 31 31 30 31 30 31 30 30 30 30  0111111101010000
0x00CFF958  30 30 30 30 30 30 30 31 30 31 30 31 30 30 30 30  0000000101010000
0x00CFF968  30 30 30 30 30 30 30 31 31 31 30 31 31 58 30 30  0000000111011X00

这句是关键 00401300   .  83F9 58       cmp     ecx, 58
也就是迷宫出口,30或20 表示出错(迷宫没走对)

写程序计算走法
	
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

至此可得出公式
I2 = MD5(I1)^x1^y2;

由于I1和I2未知,所以需要枚举一下,条件是 I1和I2必须为可见字符,程序如下:

static int check(unsigned char *i2)
{
	for (int i = 0; i < 23; i++)
	{
		if (i2[i] < ' ')
			return -1;
		if (i2[i] > 0x7e)
			return -1;
	}
	return 0;
}

int main(void)
{
  unsigned char y1[23] = {};
  unsigned char x1[] = {
	  0xA9, 0x5A, 0xBE, 0xAA, 0xA5, 0x55, 0xA5, 0x00, 0x00, 0xFA, 0xBC, 0x00, 0x00, 0x15, 0x55, 0xAF,
	  0xFE, 0x95, 0x55, 0xAA, 0xAA, 0xFE, 0xA5 };

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

  for (int i = 0; i < 23; i++)
  {
	  y1[i] = x1[i] ^ y2[i];
  }

  char I1[8] = { "0000000" };
  unsigned char i1[32] = { 0 };
  unsigned char I2[32] = { 0 };

  for (int i = 0; i <= 0xFFFFFFF; i++)
	{
		sprintf(I1, "%07x", i);

		zmd5_init(&md);
		zmd5_update(&md, I1, 7);
		zmd5_final(&md, i1);

		*(int *)&i1[0x10] = *(int*)&i1[0];
		*(int *)&i1[0x14] = *(int*)&i1[4];

		for (int k = 0; k < 23; k++)
		{
			I2[k] = i1[k] ^ y1[k]; // 简化为 y1 = x1^y2
		}
		if (check(I2) == 0)
		{
			printf("sn=%s%s\n", I1, I2);
		}
	}
	  printf("\n");
	  printf("    ok.\n");
  return 0;
}


输出如下:
sn=033a5449NE6t,iMft0mVbhJmFDdx'=
sn=0c1e344e9]%GH`"@cgE$o.811\wKC4
sn=10f3797.;Q <?n+URr@:}D)z3Pr04:
sn=15701ad;LYskzk(5Zv2"Z9NoDX!gq?
sn=1ddb354cZ,66,{~2?qAS*VJ7R-d:'/
sn=377bca1$Jn7,jj{t-):Wjk~pBoe a>
sn=3ae70c1jnLmECpHr*WLGU(S>fM?IH$
sn=7ab0f24je685qmF4Vo:v\~c>m7j9z9
sn=8187e32jMQe 4ugy YUxED1>EP7,?!

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

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