成都信息工程学院第八届信息安全大赛---crackme2的分析

crackme下载地址:

https://files.cnblogs.com/tk091/crackme2.7z

 

很习惯的,首先查壳,ASPack 2.12 -> Alexey Solodovnikov,很简单,一个esp定律就搞定,dump后再说。

dump后的文件下载:

https://files.cnblogs.com/tk091/dump.rar

运行后发现这个程序是反虚拟机的,反虚拟机的方式有很多,比如,通过特权指令来检测、利用IDT基址检测、利用LDTGDT的检测方法、基于STR(Store Task Register)的检测方法、通过注册表检测虚拟机(是否安装了tools工具等)、基于时间差的检测方式(通过RDTSC)、利用虚拟硬件指纹检测(MAC地址检查等)等。

 

通过分析发现,这个crackme是通过特权指令来检测虚拟机的,有两种方式去除,一种是不让它检测,一种是检测后什么都不干(默认会显示提示并两秒后自动退出)。

我们用IDA来看看程序大致的流程,其中有一部分是:

瞬间就看到了dwMilliseconds,毫秒嘛,那么就是检测到虚拟机后的动作了,我们让它跳过这个,也就是不处理这段程序。

进入main函数的起始:

1 0040C6D0 /> \55 push ebp

找到关键跳:

 1 0040CACF  |. /75 2C         jnz     short 0040CAFD
 2 0040CAD1  |. |8D8D 0CFBFFFF lea     ecx, dword ptr [ebp-4F4]
 3 0040CAD7  |. |51            push    ecx
 4 0040CAD8  |. |68 C80D4200   push    00420DC8                         ;  ASCII "%s",LF
 5 0040CADD  |. |E8 024EFFFF   call    004018E4
 6 0040CAE2  |. |83C4 08       add     esp, 8
 7 0040CAE5  |. |8BF4          mov     esi, esp
 8 0040CAE7  |. |68 D0070000   push    7D0                              ; /Timeout = 2000. ms
 9 0040CAEC  |. |FF15 F4624200 call    dword ptr [<&kernel32.Sleep>]    ; \Sleep
10 0040CAF2  |. |3BF4          cmp     esi, esp
11 0040CAF4  |. |E8 134AFFFF   call    0040150C
12 0040CAF9  |. |33C0          xor     eax, eax
13 0040CAFB  |. |EB 79         jmp     short 0040CB76                   ;  检测到虚拟机,跳转到程序退出的地方

上面的第一行就是关键跳,即是跳转到正常的代码,直接修改为jmp,然后保存即可。这样,程序执行到这里的时候就会直接跳过。

下面是去掉反虚拟机后的程序:

https://files.cnblogs.com/tk091/Anti-Anti-virtual.rar

下面是完整的反虚拟机的汇编代码:

反虚拟机代码
 1 00401400   > \55            push    ebp
 2 00401401   .  8BEC          mov     ebp, esp
 3 00401403   .  6A FF         push    -1
 4 00401405   .  68 68004200   push    00420068
 5 0040140A   .  68 E4204000   push    004020E4                         ;  SE 处理程序安装
 6 0040140F   .  64:A1 0000000>mov     eax, dword ptr fs:[0]
 7 00401415   .  50            push    eax
 8 00401416   .  64:8925 00000>mov     dword ptr fs:[0], esp
 9 0040141D   .  83C4 B4       add     esp, -4C
10 00401420   .  53            push    ebx
11 00401421   .  56            push    esi
12 00401422   .  57            push    edi
13 00401423   .  8965 E8       mov     dword ptr [ebp-18], esp
14 00401426   .  8D7D A4       lea     edi, dword ptr [ebp-5C]
15 00401429   .  B9 11000000   mov     ecx, 11
16 0040142E   .  B8 CCCCCCCC   mov     eax, CCCCCCCC
17 00401433   .  F3:AB         rep     stos dword ptr es:[edi]
18 00401435   .  C645 E4 01    mov     byte ptr [ebp-1C], 1
19 00401439   .  C745 FC 00000>mov     dword ptr [ebp-4], 0
20 00401440   .  52            push    edx
21 00401441   .  51            push    ecx
22 00401442   .  53            push    ebx
23 00401443   .  B8 68584D56   mov     eax, 564D5868
24 00401448   .  BB 00000000   mov     ebx, 0
25 0040144D   .  B9 0A000000   mov     ecx, 0A
26 00401452   .  BA 58560000   mov     edx, 5658
27 00401457   .  ED            in      eax, dx
28 00401458   .  81FB 68584D56 cmp     ebx, 564D5868
29 0040145E   .  0F9445 E4     sete    byte ptr [ebp-1C]
30 00401462   .  5B            pop     ebx
31 00401463   .  59            pop     ecx
32 00401464   .  5A            pop     edx
33 00401465   .  C745 FC FFFFF>mov     dword ptr [ebp-4], -1
34 0040146C   .  EB 14         jmp     short 00401482
35 0040146E   .  B8 01000000   mov     eax, 1
36 00401473   .  C3            retn

 

至于后面的分析,就难了,我加了些注释,希望能够继续分析

 1 0040CAFD      BA 01000000   mov     edx, 1
 2 0040CB02  |.  85D2          |test    edx, edx
 3 0040CB04  |.  74 6E         |je      short 0040CB74                  ;  跳到 结束
 4 0040CB06  |.  8D85 5CFBFFFF |lea     eax, dword ptr [ebp-4A4]
 5 0040CB0C  |.  50            |push    eax                             ;  0012FADC  please input password:
 6 0040CB0D  |.  68 74004200   |push    00420074                        ;  ASCII "%s       "
 7 0040CB12  |.  E8 CD4DFFFF   |call    004018E4
 8 0040CB17  |.  83C4 08       |add     esp, 8                          ;  恢复堆栈
 9 0040CB1A  |.  8D8D FCFBFFFF |lea     ecx, dword ptr [ebp-404]
10 0040CB20  |.  51            |push    ecx                             ;  输入scanf
11 0040CB21  |.  68 6C0D4200   |push    00420D6C                        ;  ASCII "%s"
12 0040CB26  |.  E8 894DFFFF   |call    004018B4                        ;  输入的信息保存在堆栈中
13 0040CB2B  |.  83C4 08       |add     esp, 8
14 0040CB2E  |.  8D95 FCFBFFFF |lea     edx, dword ptr [ebp-404]
15 0040CB34  |.  52            |push    edx
16 0040CB35  |.  E8 CB44FFFF   |call    00401005                        ;  可能的关键call
17 0040CB3A  |.  83C4 04       |add     esp, 4
18 0040CB3D  |.  8945 FC       |mov     dword ptr [ebp-4], eax          ;  这两句相当于test   eax,eax
19 0040CB40      837D FC 00    cmp     dword ptr [ebp-4], 0
20 0040CB44      75 16         jnz     short 0040CB5C                   ;  进行判断
21 0040CB46  |.  8D85 C4FBFFFF |lea     eax, dword ptr [ebp-43C]
22 0040CB4C  |.  50            |push    eax
23 0040CB4D  |.  68 C80D4200   |push    00420DC8                        ;  ASCII "%s",LF
24 0040CB52  |.  E8 8D4DFFFF   |call    004018E4                        ;  调用printf函数
25 0040CB57  |.  83C4 08       |add     esp, 8
26 0040CB5A  |.  EB 16         |jmp     short 0040CB72
27 0040CB5C  |>  8D8D 90FBFFFF |lea     ecx, dword ptr [ebp-470]        ;  这里是正确信息保存的位置
28 0040CB62  |.  51            |push    ecx
29 0040CB63  |.  68 C80D4200   |push    00420DC8                        ;  ASCII "%s",LF
30 0040CB68  |.  E8 774DFFFF   |call    004018E4
31 0040CB6D  |.  83C4 08       |add     esp, 8
32 0040CB70  |.  EB 02         |jmp     short 0040CB74                  ;  结果正确,跳出循环
33 0040CB72  |>^ EB 89         \jmp     short 0040CAFD                  ;  重新开始判断

算法分析始终是个大难题。

程序的分析就大致这样吧。

勿在浮沙筑高台,还是回去好好学基础吧。

 

-----2012-5-2-22:10---------继续分析----------

通过52的几个大牛的帮助,搞到了真码(真码为:lEpynapmoi),任何我用IDA继续调试

 1 int __cdecl sub_40BA10(const char *szKey)
 2 {
 3   char v2; // [sp+Ch] [bp-50h]@1
 4   int v3; // [sp+4Ch] [bp-10h]@2
 5   int i; // [sp+50h] [bp-Ch]@11
 6   int v5; // [sp+54h] [bp-8h]@7
 7   size_t ilength; // [sp+58h] [bp-4h]@1
 8 
 9   memset(&v2, 0xCCCCCCCCu, 0x50u);
10   ilength = strlen(szKey);
11   if ( ilength == 10 )
12   {
13     if ( szKey[1] == 69 )
14     {
15       if ( *szKey == SomeString[(signed int)ilength % 24] )
16       {
17         v5 = 2 * (signed int)ilength % 24;
18         if ( v5 > 24 )
19           v5 -= 24;
20         if ( szKey[2] == SomeString[v5] )
21         {
22           v5 = 0;
23           for ( i = 3; i <= 8; ++i )
24           {
25             v5 = szKey[2] + v5 - 65;
26             if ( v5 > 24 )
27               v5 %= 24;
28             if ( szKey[i] != SomeString[v5] )
29             {
30               printf("%c", SomeString[v5]);
31               v3 = 0;
32               return unknown_libname_1();
33             }
34           }
35           v5 = 0;
36           for ( i = 0; i < 9; ++i )
37             v5 += szKey[i];
38           v5 /= 9;
39           v3 = szKey[9] == (char)v5;
40         }
41         else
42         {
43           v3 = 0;
44         }
45       }
46       else
47       {
48         v3 = 0;
49       }
50     }
51     else
52     {
53       v3 = 0;
54     }
55   }
56   else
57   {
58     v3 = 0;
59   }
60   return unknown_libname_1();
61 }

这个crackme没有上面算法,只有上面的这个,IDA显示SomeString为: UIT_SYC_Flowers_Company

这样,分析就完成了。

posted @ 2012-04-27 11:07  r3call  阅读(1317)  评论(0编辑  收藏  举报