找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 5475|回复: 3

虚拟机检测程序的分析

[复制链接]
发表于 2015-2-8 13:18:52 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
工作了就忙了,抽空研究写个文章:

起因:前几个礼拜在网上下了个视频exe(5.exe),win7下运行直接异常,因此想放到xp虚拟机里看看,结果直接检测出虚拟机,弹窗后直接关闭,很好奇想知道怎么检测的。

用windbg加载该exe,运行到弹窗后暂停,“Play请不要在虚拟机中播放!!”。查看调用栈,发现空空如也,感觉不太妙,试着移动窗体,发现居然可以移动!那么这一定是另一个进程的,也就是说5.exe启动了另一个进程。用process explorer查看进程,发现进程树中5.exe居然开启了C:\WINDOWS\system32\winver.exe,命令行参数传的是F238FF10FB00F72CD46CD727B402EC259151C620E00AEC26C25EE230F90AEC28C276D135E00CF01D66C260B2C817E732C55E967AF11BE7,之后我在真正的(非虚拟机)win7系统里运行了一下,这个串变成了F238FF01E706F032ED6ECA37FC02ED1DF567D03FE00CF21D842CC62CF1,现在奇怪的事情来了,自己手动执行winver.exe,参数是后面那个长串,预期会弹上面那个窗口,结果却只是winver自己的界面。后来搞了很长时间没有什么进展,无意间我看到5.exe资源(DEL_FD1)里有个pe文件(记为DEL_FD1.exe),把它dump出来,加上那个参数运行了一下,居然弹窗了,也就说5.exe吧资源在内存dump下来直接运行了,没有通过生成文件这一步。。。而虚拟机检测和参数解析都是DEL_FD1.exe做的,5.exe仅仅用于产生另一个进程。详细看了字符串引用还会有更多发现,原来5.exe用到了BoxedApp SDK来实现资源直接生成进程这一步。如果将资源DEL_FD1替换成其他exe,会发现运行的恰好是替换的这个文件!!!

现在目标明确了,用Windbg分析该del_fd1.exe,当然要加上会弹窗的那个参数,再弹窗时,暂停下来看调用栈:
0012F67C  77D19418   包含ntdll.KiFastSystemCallRet           USER32.77D19416               0012F6AC
0012F680  00469032  <JMP.&user32.WaitMessage>             DEL_FD1.0046902D              0012F6AC
0012F6B0  004684AC   ? DEL_FD1.00468F00                    DEL_FD1.004684A7              0012F6AC
0012F6D4  00464C28   DEL_FD1.00468490                      DEL_FD1.00464C23              0012F730
这次仍然不是很明显(调Dephi程序好难受,各种奇怪的库函数),后几个函数跟进去以后可能是窗口回调之类的。没办法,搜字符串吧,0x4a9eb0处可以搜到结果,之后在这里下访问断点,再看调用栈:
0012F61C  77D1AE26  ntdll.RtlMultiByteToUnicodeN         USER32.77D1AE20              0012F618
0012F644  77D3C76E   USER32.MBToWCSEx                      USER32.77D3C769               0012F640
0012F674  77D3C730   USER32.DrawTextExA                    USER32.77D3C72B               0012F670
0012F678  01010054     hDC = 01010054
0012F67C  004A9EB0     Text = "请不要在虚拟机中播放!!"
0012F680  00000017     Count = 17 (23.)
0012F684  0012F6E8     pRect = 0012F6E8{0.,0.,960.,0.}
0012F688  00000450     Flags =DT_LEFT|DT_TOP|DT_WORDBREA
0012F68C  00000000     pDrawTextParams =NULL
0012F6A8  0043B898  <JMP.&user32.DrawTextA>               DEL_FD1.0043B893              0012F6A4
0012F6AC  01010054     hDC = 01010054
0012F6B0  004A9EB0     Text = "请不要在虚拟机中播放!!"
0012F6B4  00000017     Count = 17 (23.)
0012F6B8  0012F6E8     pRect = 0012F6E8{0.,0.,960.,0.}
0012F6BC  00000450     Flags =DT_LEFT|DT_TOP|DT_WORDBREA
0012F74C  0043BC52   ? DEL_FD1.0043B68C                    DEL_FD1.0043BC4D              0012F748
0012F758  0043BD9B   ? DEL_FD1.0043BC2C                    DEL_FD1.0043BD96
0012F778  0043BC93   ? DEL_FD1.0043BD34                    DEL_FD1.0043BC8E
0012F77C  00000000     Arg1 = 00000000
0012F780  FFFFFFFF     Arg2 = FFFFFFFF
0012F784  FFFFFFFF     Arg3 = FFFFFFFF
0012F788  00000000     Arg4 = 00000000
0012F794  0043BDCE   DEL_FD1.0043BC74                      DEL_FD1.0043BDC9              0012F790
0012F798  FFFFFFFF     Arg1 = FFFFFFFF
0012F79C  FFFFFFFF     Arg2 = FFFFFFFF
0012F7A0  00000000     Arg3 = 00000000
0012F7A4  0043BDBB   DEL_FD1.0043BDBC                      DEL_FD1.0043BDB6              0012FB78
0012F7A8  004A94F7   DEL_FD1.0043BDB0                      DEL_FD1.004A94F2              0012FB78
可以发现窗口是DrawTextA产生的,怪不得MessageBox断不下呢!输入at 004A94F7转到反汇编,跟到最后终于快得到结果了:
。。。。。。。。。。。。前面一堆代码。。。。。。。。。。。
  1. .text:004A94CE loc_4A94CE:                             ; CODE XREF:sub_4A8A1C+AAAj
  2. .text:004A94CE                                         ; DATA XREF: sub_4A8A1C+A95o
  3. .text:004A94CE                 call    sub_4A88D0
  4. .text:004A94D3                 mov     eax, ds:dword_53DF44
  5. .text:004A94D8                 mov     edx, offset dword_4A9EA4
  6. .text:004A94DD                 call    sub_4056B0
  7. .text:004A94E2                 jnz     short loc_4A9527
  8. .text:004A94E4                 call    sub_4A866C
  9. .text:004A94E9                 test    eax, eax
  10. .text:004A94EB                 jz      short loc_4A9501
  11. .text:004A94ED                 mov     eax, offset aIKST ; "请不要在虚拟机中播放!!\xFF\xFF\xFF\xFF\x17"
  12. .text:004A94F2                 call    @ShowMessage
  13. .text:004A94F7                 mov     eax, ds:dword_53DF0C
  14. .text:004A94FC                 call    @TCustomForm@Close ; TCustomForm::Close
  15. .text:004A9501
  16. .text:004A9501 loc_4A9501:                             ; CODE XREF:sub_4A8A1C+ACFj
  17. .text:004A9501                 call    sub_4A871C
  18. .text:004A9506                 test    al, al
  19. .text:004A9508                 jnz     short loc_4A9513
  20. .text:004A950A                 call    loc_4A86CC
  21. .text:004A950F                 test    al, al
  22. .text:004A9511                 jz      short loc_4A9527
  23. .text:004A9513
  24. .text:004A9513 loc_4A9513:                             ; CODE XREF:sub_4A8A1C+AECj
  25. .text:004A9513                 mov    eax, offset aIKST_0 ; "请不要在虚拟机中播放!!!\xFF\xFF\xFF\xFF\x01"
  26. .text:004A9518                 call    @ShowMessage
  27. .text:004A951D                 mov     eax, ds:dword_53DF0C
  28. .text:004A9522                 call    @TCustomForm@Close ; TCustomForm::Close
  29. .text:004A9527
  30. .text:004A9527 loc_4A9527:                             ; CODE XREF:sub_4A8A1C+AC6j
  31. .text:004A9527                                         ;sub_4A8A1C+AF5j
  32. .text:004A9527                 mov     eax, ds:dword_53DF44
  33. .text:004A952C                 mov     edx, offset dword_4A9EA4
  34. .text:004A9531                 call    sub_4056B0
  35. .text:004A9536                 jnz     short loc_4A9567
  36. .text:004A9538                 call    sub_4A866C
  37. .text:004A953D                 test    eax, eax
  38. .text:004A953F                 jz      short loc_4A954B
  39. .text:004A9541                 mov     eax, ds:dword_53DF0C
  40. .text:004A9546                 call    @TCustomForm@Close ; TCustomForm::Close
  41. .text:004A954B
  42. .text:004A954B loc_4A954B:                             ; CODE XREF: sub_4A8A1C+B23j
  43. .text:004A954B                 call    sub_4A871C
  44. .text:004A9550                 test    al, al
  45. .text:004A9552                 jnz     short loc_4A955D
  46. .text:004A9554                 call    loc_4A86CC
  47. .text:004A9559                 test    al, al
  48. .text:004A955B                 jz      short loc_4A9567
  49. .text:004A955D
  50. .text:004A955D loc_4A955D:                             ; CODE XREF:sub_4A8A1C+B36j
  51. .text:004A955D                 mov     eax, ds:dword_53DF0C
  52. .text:004A9562                 call    @TCustomForm@Close ; TCustomForm::Close
复制代码

。。。。。。。。。。。。后面一堆代码。。。。。。。。。。。
可以得到如下关键逻辑:
if(sub_4A866C() || sub_4A871C() ||sub_4A86CC())
{
ShowMessage(“请不要在虚拟机中播放”);
TcustomForm.Close();
}
。。。。。。。。。。。。。。。

先来看sub_4A866C:
  1. .text:004A866C                 push    ebp
  2. .text:004A866D                 mov     ebp, esp
  3. .text:004A866F                 push    ecx
  4. .text:004A8670                 push    ebx
  5. .text:004A8671                 push    esi
  6. .text:004A8672                 push    edi
  7. .text:004A8673                 xor     eax, eax
  8. .text:004A8675                 mov     [ebp+var_4], eax
  9. .text:004A8678                 xor     eax, eax
  10. .text:004A867A                 push    ebp
  11. .text:004A867B                 push    offset loc_4A86B4
  12. .text:004A8680                 push    dword ptr fs:[eax]
  13. .text:004A8683                 mov     fs:[eax], esp
  14. .text:004A8686                 mov     eax, 564D5868h
  15. .text:004A868B                 mov     ebx, 0
  16. .text:004A8690                 mov     ecx, 0Ah
  17. .text:004A8695                 mov     edx, 5658h
  18. .text:004A869A                 in      eax, dx
  19. .text:004A869B                 cmp     ebx, 564D5868h
  20. .text:004A86A1                 jnz     short loc_4A86AA
  21. .text:004A86A3                 mov     [ebp+var_4], 1
  22. .text:004A86AA
  23. .text:004A86AA loc_4A86AA:                             ; CODE XREF:sub_4A866C+35j
  24. .text:004A86AA                 xor     eax, eax
  25. .text:004A86AC                 pop     edx
  26. .text:004A86AD                 pop     ecx
  27. .text:004A86AE                 pop     ecx
  28. .text:004A86AF                 mov     fs:[eax], edx
  29. .text:004A86B2                 jmp    short loc_4A86C3
  30. .text:004A86B4 ;---------------------------------------------------------------------------
  31. .text:004A86B4
  32. .text:004A86B4 loc_4A86B4:                             ; DATA XREF:sub_4A866C+Fo
  33. .text:004A86B4                 jmp     @@HandleAnyException ; __linkproc__HandleAnyException
  34. .text:004A86B9 ;---------------------------------------------------------------------------
  35. .text:004A86B9                 xor     eax, eax
  36. .text:004A86BB                 mov     [ebp+var_4], eax
  37. .text:004A86BE                 call    @@DoneExcept    ; __linkproc__ DoneExcept
  38. .text:004A86C3
  39. .text:004A86C3 loc_4A86C3:                             ; CODE XREF:sub_4A866C+46j
  40. .text:004A86C3                 mov     eax, [ebp+var_4]
  41. .text:004A86C6                 pop     edi
  42. .text:004A86C7                 pop     esi
  43. .text:004A86C8                 pop     ebx
  44. .text:004A86C9                 pop     ecx
  45. .text:004A86CA                 pop     ebp
  46. .text:004A86CB                 retn
复制代码

可以得到如下代码:
  1. bool IsUnderVM1()
  2. {
  3. bool flag=false;
  4. __try
  5. {
  6. _asm
  7. {
  8. mov eax,’VMXh’;
  9. mov ebx,0;
  10. mov ecx,0Ah;
  11. mov edx,’VX’;
  12. in eax,dx;
  13. cmp ebx,’VMXh’;
  14. jnz RESULT;
  15. mov flag,1;
  16. RESULT:   ;
  17. }
  18. }
  19. __except(1)
  20. {
  21.         flag=false;
  22. }
  23. return flag;
  24. }
复制代码


下面来看sub_4A871C函数:
  1. .text:004A871C                 push    ebp
  2. .text:004A871D                 mov     ebp, esp
  3. .text:004A871F                 push    ecx
  4. .text:004A8720                 push    ebx
  5. .text:004A8721                 push    esi
  6. .text:004A8722                 push   edi
  7. .text:004A8723                 mov     [ebp+var_1], 0
  8. .text:004A8727                 xor     eax, eax
  9. .text:004A8729                 push    ebp
  10. .text:004A872A                 push    offset loc_4A875F
  11. .text:004A872F                 push    dword ptr fs:[eax]
  12. .text:004A8732                 mov     fs:[eax], esp
  13. .text:004A8735                 push    edx
  14. .text:004A8736                 push    ecx
  15. .text:004A8737                 push    ebx
  16. .text:004A8738                 mov     eax, 'VMXh'
  17. .text:004A873D                 mov     ecx, 0Ah
  18. .text:004A8742                 mov     edx, 5658h
  19. .text:004A8747                 in      eax, dx
  20. .text:004A8748                 cmp     ebx, 'VMXh'
  21. .text:004A874E                 setz    [ebp+var_1]
  22. .text:004A8752                 pop     ebx
  23. .text:004A8753                 pop     ecx
  24. .text:004A8754                 pop     edx
  25. .text:004A8755                 xor     eax, eax
  26. .text:004A8757                 pop     edx
  27. .text:004A8758                 pop     ecx
  28. .text:004A8759                 pop     ecx
  29. .text:004A875A                 mov     fs:[eax], edx
  30. .text:004A875D                 jmp     short loc_4A8769
  31. .text:004A875F ;---------------------------------------------------------------------------
  32. .text:004A875F
  33. .text:004A875F loc_4A875F:                             ; DATA XREF:sub_4A871C+Eo
  34. .text:004A875F                 jmp     @@HandleAnyException ; __linkproc__HandleAnyException
  35. .text:004A8764 ;---------------------------------------------------------------------------
  36. .text:004A8764                 call    @@DoneExcept    ; __linkproc__ DoneExcept
  37. .text:004A8769
  38. .text:004A8769 loc_4A8769:                             ; CODE XREF:sub_4A871C+41j
  39. .text:004A8769                 movzx   eax, [ebp+var_1]
  40. .text:004A876D                 pop     edi
  41. .text:004A876E                 pop     esi
  42. .text:004A876F                 pop     ebx
  43. .text:004A8770                 pop     ecx
  44. .text:004A8771                 pop     ebp
  45. .text:004A8772                 retn
复制代码

翻译以后为:
  1. bool IsUnderVM2()
  2. {
  3. bool flag=false;
  4. __try
  5. {
  6. _asm
  7. {
  8. mov eax,’VMXh’;
  9. mov ecx,0Ah;//注意和IsUnderVM1不同
  10. mov edx,’VX’;
  11. in eax,dx;
  12. cmp ebx,’VMXh’
  13. setz flag;
  14. }
  15. }
  16. __except(1)
  17. {
  18.         flag=false;
  19. }
  20. return flag;
  21. }
复制代码


下面来看004A86CC处的函数,IDA未能正确识别:
  1. .text:004A86CC                 push    ebp
  2. .text:004A86CD                 mov     ebp, esp
  3. .text:004A86CF                 push    ecx
  4. .text:004A86D0                 push    ebx
  5. .text:004A86D1                 push   esi
  6. .text:004A86D2                 push    edi
  7. .text:004A86D3                 mov     byte ptr [ebp-1], 0
  8. .text:004A86D7                 xor     eax, eax
  9. .text:004A86D9                 push    ebp
  10. .text:004A86DA                 push    offset unk_4A8705
  11. .text:004A86DF                 push    dword ptr fs:[eax]
  12. .text:004A86E2                 mov     fs:[eax], esp
  13. .text:004A86E5                 push    ebx
  14. .text:004A86E6                 mov     ebx, 0
  15. .text:004A86EB                 mov     eax, 1
  16. .text:004A86EB ;---------------------------------------------------------------------------
  17. .text:004A86F0                 db 0Fh
  18. .text:004A86F1                 db 3Fh
  19. .text:004A86F2                 db 7
  20. .text:004A86F3                 db 0Bh
  21. .text:004A86F4                 db  85h ; ?
  22. .text:004A86F5                 db 0DBh ; ?
  23. .text:004A86F6                 db  0Fh
  24. .text:004A86F7                 db  94h ; ?
  25. .text:004A86F8                 db  45h ; E
  26. .text:004A86F9                 db 0FFh
  27. .text:004A86FA                 db  5Bh ; [
  28. .text:004A86FB                 db  33h ; 3
  29. .text:004A86FC                 db 0C0h ; ?
  30. .text:004A86FD                 db  5Ah ; Z
  31. .text:004A86FE                 db  59h ; Y
  32. .text:004A86FF                 db  59h ; Y
  33. .text:004A8700                 db  64h ; d
  34. .text:004A8701                 db  89h ; ?
  35. .text:004A8702                 db  10h
  36. .text:004A8703                 db 0EBh ; ?
  37. .text:004A8704                 db  0Ah
  38. .text:004A8705 unk_4A8705      db 0E9h ; ?            ; DATA XREF: .text:004A86DAo
  39. .text:004A8706                 db  5Eh ; ^
  40. .text:004A8707                 db 0C1h ; ?
  41. .text:004A8708                 db 0F5h ; ?
  42. .text:004A8709                 db 0FFh
  43. .text:004A870A                 db 0E8h ; ?
  44. .text:004A870B                 db  69h ; i
  45. .text:004A870C                 db 0C5h ; ?
  46. .text:004A870D                 db 0F5h ; ?
  47. .text:004A870E                 db 0FFh
  48. .text:004A870F                 db  0Fh
  49. .text:004A8710                 db 0B6h ; ?
  50. .text:004A8711                 db  45h ; E
  51. .text:004A8712                 db 0FFh
  52. .text:004A8713                 db  5Fh ; _
  53. .text:004A8714                 db  5Eh ; ^
  54. .text:004A8715                 db  5Bh ; [
  55. .text:004A8716                 db  59h ; Y
  56. .text:004A8717                 db  5Dh ; ]
  57. .text:004A8718                 db 0C3h ; ?
复制代码


经过手动识别指令最终可以得到:
  1. .text:004A86CC loc_4A86CC:                             ; CODE XREF:sub_4A8A1C+AEEp
  2. .text:004A86CC                                         ;sub_4A8A1C+B38p
  3. .text:004A86CC                 push    ebp
  4. .text:004A86CD                 mov     ebp, esp
  5. .text:004A86CF                 push    ecx
  6. .text:004A86D0                 push    ebx
  7. .text:004A86D1                 push    esi
  8. .text:004A86D2                 push    edi
  9. .text:004A86D3                 mov     byte ptr [ebp-1], 0
  10. .text:004A86D7                 xor     eax,eax
  11. .text:004A86D9                 push    ebp
  12. .text:004A86DA                 push    offset loc_4A8705//注册异常回调
  13. .text:004A86DF                 push    dword ptr fs:[eax]
  14. .text:004A86E2                 mov     fs:[eax], esp
  15. .text:004A86E5                 push    ebx
  16. .text:004A86E6                 mov     ebx, 0
  17. .text:004A86EB                 mov     eax, 1
  18. .text:004A86EB ;---------------------------------------------------------------------------
  19. .text:004A86F0                 db 0Fh
  20. .text:004A86F1                 db 3Fh
  21. .text:004A86F2                 db 7
  22. .text:004A86F3                 db 0Bh
  23. .text:004A86F4 ;---------------------------------------------------------------------------
  24. .text:004A86F4                 test    ebx, ebx//ZF位为1
  25. .text:004A86F6                 setz    byte ptr [ebp-1]//ebp[-1]=1;
  26. .text:004A86FA                 pop     ebx
  27. .text:004A86FB                 xor     eax, eax
  28. .text:004A86FD                 pop     edx
  29. .text:004A86FE                 pop     ecx
  30. .text:004A86FF                 pop    ecx
  31. .text:004A8700                 mov     fs:[eax], edx
  32. .text:004A8703                 jmp     short loc_4A870F
  33. .text:004A8705 ;---------------------------------------------------------------------------
  34. .text:004A8705
  35. .text:004A8705 loc_4A8705:                             ; DATA XREF:.text:004A86DAo
  36. .text:004A8705                 jmp     @@HandleAnyException ; __linkproc__HandleAnyException
  37. .text:004A870A ;---------------------------------------------------------------------------
  38. .text:004A870A                 call    @@DoneExcept    ; __linkproc__ DoneExcept
  39. .text:004A870F
  40. .text:004A870F loc_4A870F:                             ; CODE XREF:.text:004A8703j
  41. .text:004A870F                 movzx   eax, byte ptr [ebp-1]
  42. .text:004A8713                 pop     edi
  43. .text:004A8714                 pop     esi
  44. .text:004A8715                 pop     ebx
  45. .text:004A8716                 pop     ecx
  46. .text:004A8717                 pop     ebp
  47. .text:004A8718                 retn
复制代码

中间的0F3F070B是什么,我也不知道于是百度到了这个网站http://hp.vector.co.jp/authors/VA028184/OllyDbgQA.htm,原来是Virtual PC自造的一个指令(不过具体是什么指令我没查到,知道的可以说下),在其他架构下(如x86)为非法指令会产生异常(情况1),而Virutal PC下能正常执行(情况2)。下面分别讨论:

函数公共部分:ebp[-1]=0,eax=0;004A86D9~ 004A86E2为异常初始化,004A8705为发生异常的回调地址;ebx=0;eax=1

情况1:走到004A86F0处,由于不识别指令因此引发异常,直接到004A8705,后面走到004A870F,eax=ebp[-1]=0。

情况2:004A86F0处指令正常执行,test指令置ZF位为1,setz的结果是ebp[-1]=1,eax=0,接下来几个pop抵销前面注册异常处理的push,edx刚好对应004A86DF代码处原先入栈的异常帧,movfs:[eax], edx恢复了原始异常链,之后运行到004A870F,eax=ebp[-1]=1。

原始代码是Delphi写的,这里用MSVC的C代码表示:
  1. bool IsUnderVM3()
  2. {
  3. bool flag=false;
  4. __try
  5. {
  6. _asm
  7. {
  8. _EMIT 0x0F;
  9. _EMIT 0x3F;
  10. _EMIT 0x07;
  11. _EMIT 0x0B;
  12. }
  13. flag=true;
  14. }
  15. __except(1)
  16. {
  17. }
  18. return flag;
  19. }
复制代码

现在我对BoxedAppSDK产生了兴趣,以后有时间会研究,感觉很有用,看了一下可以用虚拟方式操作文件、注册表、环境变量、内存、进程。收费蛮高的,从官网上下了一份demo,看了例子有4个:嵌入dll加载,嵌入flash加载,使用内存pe生成进程,使用notepad打开内存文件。这套技术应该是很有用的!!!

回复

使用道具 举报

 楼主| 发表于 2015-2-8 13:26:48 | 显示全部楼层
用到的文件 5.rar (569.7 KB, 下载次数: 2)
回复 赞! 靠!

使用道具 举报

发表于 2015-2-10 09:26:12 | 显示全部楼层
学习了 不过这个检测虚拟机的方法都被用烂了.
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2015-2-10 19:18:18 | 显示全部楼层
0x01810 发表于 2015-2-10 09:26
学习了 不过这个检测虚拟机的方法都被用烂了.

第三个方法没看到有谁弄过
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-22 15:25 , Processed in 0.035270 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表